Skip to content

Commit

Permalink
Merge pull request #14 from Azure-Samples/jdrefke/need4speed
Browse files Browse the repository at this point in the history
Improve regex perf for CustomLookupSkill and refactor code for readability
  • Loading branch information
jadrefke authored Oct 11, 2019
2 parents f07983b + 702237c commit 68e98f3
Show file tree
Hide file tree
Showing 8 changed files with 418 additions and 324 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,35 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace AzureCognitiveSearch.PowerSkills.Tests.CustomEntitySearchTests
{
public static class CustomEntitySearchHelpers
{
private const string TestJsonFileName = "testWords.json";
private const string TestCsvFileName = "testWords.csv";

private static readonly Func<HttpRequest, Task<IActionResult>> _entitySearchFunction =
Helpers.CurrySkillFunction(CustomEntitySearch.RunCustomEntitySearch);

public static string BuildInput(string text, string[] words)
=> Helpers.BuildPayload(new
{
Text = text,
Words = words
});

public static string BuildInput(string text, string[] words, Dictionary<string, string[]> synonyms, string[] exactMatches, int offset)
public static string BuildInput(
string text)
=> Helpers.BuildPayload(new
{
Text = text,
Words = words,
Synonyms = synonyms,
ExactMatches = exactMatches,
FuzzyMatchOffset = offset
});

public static string BuildOutput(string[] entities, string[] matches, int[] matchIndices)
public static string BuildOutput(
string[] entities,
string[] matches,
int[] matchIndices)
=> Helpers.BuildPayload(new
{
Entities = matches.Select((entity, i) => new
Expand All @@ -48,7 +47,11 @@ public static string BuildOutput(string[] entities, string[] matches, int[] matc
EntitiesFound = entities
});

public static string BuildOutput(string[] entities, string[] matches, int[] matchIndices, double[] confidence)
public static string BuildOutput(
string[] entities,
string[] matches,
int[] matchIndices,
double[] confidence)
=> Helpers.BuildPayload(new
{
Entities = matches.Select((entity, i) => new
Expand All @@ -62,11 +65,20 @@ public static string BuildOutput(string[] entities, string[] matches, int[] matc
});

public static async Task CallEntitySearchFunctionAndCheckResults(
string[] expectedFoundEntities, string[] expectedMatches, int[] expectedMatchIndices, double[] confidence,
string text, string[] words, Dictionary<string, string[]> synonyms, string[] exactMatches, int offset,
string warningMessage = "", string errorMessage = "")
string[] expectedFoundEntities,
string[] expectedMatches,
int[] expectedMatchIndices,
double[] confidence,
string text,
string[] words,
Dictionary<string, string[]> synonyms,
string[] exactMatches,
int offset,
string warningMessage = "",
string errorMessage = "")
{
string input = BuildInput(text, words, synonyms, exactMatches, offset);
string input = BuildInput(text);
ReplaceWordsJsonFile(words, synonyms, exactMatches, offset);
string expectedOutput = BuildOutput(expectedFoundEntities, expectedMatches, expectedMatchIndices, confidence);
string actualOutput = await QueryEntitySearchFunctionAndSerialize(input);
if (warningMessage != "")
Expand All @@ -76,14 +88,60 @@ public static async Task CallEntitySearchFunctionAndCheckResults(
expectedOutput = expectedOutput.Replace(@"""errors"":[]", errorMessage);
expectedOutput = expectedOutput.Remove(35, 32);
}
Assert.AreEqual(expectedOutput, actualOutput);

Helpers.AssertJsonEquals(expectedOutput, actualOutput);
}

public static async Task CallEntitySearchFunctionAndCheckResults(
string text,
string[] words,
string expectedOutput,
Dictionary<string, string[]> synonyms = null,
string[] exactMatches = null,
int offset = 0)
{
string input = BuildInput(text);
ReplaceWordsJsonFile(words, synonyms, exactMatches, offset);
string actualOutput = await QueryEntitySearchFunctionAndSerialize(input);

Helpers.AssertJsonEquals(expectedOutput, actualOutput);
}

public static void ReplaceWordsJsonFile(
string[] words,
Dictionary<string, string[]> synonyms = null,
string[] exactMatches = null,
int offset = 0)
{
exactMatches = exactMatches ?? new string[0];
synonyms = synonyms ?? new Dictionary<string, string[]>();

JObject config = new JObject();
config["words"] = JArray.FromObject(words);
config["synonyms"] = JObject.FromObject(synonyms);
config["exactMatch"] = JArray.FromObject(exactMatches);
config["fuzzyEditDistance"] = offset;
config["caseSensitive"] = true;

var executingLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var path = Path.Combine(executingLocation, TestJsonFileName);
CustomEntitySearch.EntityDefinitionLocation = TestJsonFileName;

var serializedConfig = config.ToString();
File.WriteAllText(path, serializedConfig);
}

public static async Task CallEntitySearchFunctionAndCheckResults(
string[] expectedFoundEntities, string[] expectedMatches, int[] expectedMatchIndices,
string text, string[] words, string warningMessage = "", string errorMessage = "")
string[] expectedFoundEntities,
string[] expectedMatches,
int[] expectedMatchIndices,
string text,
string[] words,
string warningMessage = "",
string errorMessage = "")
{
string input = BuildInput(text, words);
string input = BuildInput(text);
ReplaceWordsJsonFile(words);
string expectedOutput = BuildOutput(expectedFoundEntities, expectedMatches, expectedMatchIndices);
string actualOutput = await QueryEntitySearchFunctionAndSerialize(input);
if (warningMessage != "")
Expand All @@ -93,7 +151,18 @@ public static async Task CallEntitySearchFunctionAndCheckResults(
expectedOutput = expectedOutput.Replace(@"""errors"":[]", errorMessage);
expectedOutput = expectedOutput.Remove(35, 32);
}
Assert.AreEqual(expectedOutput, actualOutput);

Helpers.AssertJsonEquals(expectedOutput, actualOutput);
}

private static void ReplaceWordsCsvFile(string[] words)
{
var executingLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var path = Path.Combine(executingLocation, TestCsvFileName);
CustomEntitySearch.EntityDefinitionLocation = TestCsvFileName;

var serializedConfig = string.Join(Environment.NewLine, words);
File.WriteAllText(path, serializedConfig);
}

public static async Task<WebApiSkillResponse> QueryEntitySearchFunction(string inputText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,7 @@ namespace AzureCognitiveSearch.PowerSkills.Tests.CustomEntitySearchTests

[TestClass]
public class CustomEntitySearchTests
{
[TestMethod]
public async Task MissingWordsBadRequest()
{
// tests against incorrect input (missing words)
WebApiSkillResponse outputContent = await CustomEntitySearchHelpers.QueryEntitySearchFunction(TestData.MissingWordsBadRequestInput);
Assert.IsTrue(outputContent.Values[0].Warnings[0].Message.Contains(TestData.MissingWordsExpectedResponse));
}

{
[TestMethod]
public async Task MissingTextBadRequest()
{
Expand All @@ -39,15 +31,6 @@ await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
"", TestData.EmptyTextWordsNotFoundInput);
}

[TestMethod]
public async Task EmptyWordsEmptyEntities()
{
//tests against empty string words
await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
Array.Empty<string>(), Array.Empty<string>(), Array.Empty<int>(),
"", Array.Empty<string>(), "", TestData.EmptyWordsEmptyEntitiesErrorMessage);
}

[TestMethod]
public async Task LargeTextQuickResult()
{
Expand All @@ -69,7 +52,7 @@ await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
[TestMethod]
public async Task LargeDatasetQuickResult()
{
//tests against a large number of documents inputted (loadtest)
//tests against a large input document
await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
TestData.LargeTextOutputFound, TestData.LargeTextOutputNames, TestData.LargeTextOutputMatchIndex,
TestData.LargestText, TestData.LargeTextQuickResultInputWords);
Expand All @@ -81,8 +64,9 @@ public async Task LargeNumWordsQuickResult()
{
// tests against a large number of patterns in words array
await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
TestData.LargeNumWordsOutputFound, TestData.LargeNumWordsOutputNames, TestData.LargeNumWordsOutputMatchIndex,
TestData.LargestText, TestData.LargestWords);
TestData.LargestText,
TestData.LargestWords,
TestData.LargeNumWordsQuickResultExpectedResponse);
}

[TestMethod]
Expand Down Expand Up @@ -168,6 +152,8 @@ await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(TestData
[TestMethod]
public async Task WordSmallerThanLeniency()
{
CustomEntitySearchHelpers.ReplaceWordsJsonFile(words: new string[] { "i" }, offset: 2);

WebApiSkillResponse outputContent = await CustomEntitySearchHelpers.QueryEntitySearchFunction(TestData.WordSmallerThanLeniencyInput);
Assert.IsTrue(outputContent.Values[0].Warnings[0].Message.Contains(TestData.WordSmallerThanLeniencyWarning));
}
Expand All @@ -191,9 +177,11 @@ await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(TestData
[TestMethod]
public async Task LargestLeniencyCheck()
{
await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(TestData.LargestLeniencyCheckMatchesFound, TestData.LargestLeniencyCheckMatches,
TestData.LargestLeniencyCheckIndices, TestData.LargestLeniencyCheckConfidence, TestData.LargestLeniencyCheckText,
TestData.LargestLeniencyCheckWords, new Dictionary<string, string[]>(), Array.Empty<string>(), 10, TestData.LargestLeniencyCheckWarning);
await CustomEntitySearchHelpers.CallEntitySearchFunctionAndCheckResults(
TestData.LargestLeniencyCheckText,
TestData.LargestLeniencyCheckWords,
TestData.LargestLeniencyCheckExpectedResponse,
offset: 10);
}

[TestMethod]
Expand Down
Loading

0 comments on commit 68e98f3

Please sign in to comment.