Skip to content

Commit 458b10c

Browse files
committed
Add more integration tests with better validation
1 parent 25776c5 commit 458b10c

File tree

3 files changed

+102
-52
lines changed

3 files changed

+102
-52
lines changed

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Documents/text-3properties-1536dimensions-100documents.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<IsTestProject>true</IsTestProject>
44
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -343,6 +343,10 @@
343343
<Link>Documents\MillionSong1KDocuments.json</Link>
344344
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
345345
</None>
346+
<None Include="Documents\text-3properties-1536dimensions-100documents.json">
347+
<Link>Documents\text-3properties-1536dimensions-100documents.json</Link>
348+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
349+
</None>
346350
</ItemGroup>
347351
<ItemGroup>
348352
<ProjectReference Include="..\..\src\Microsoft.Azure.Cosmos.csproj" />

Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/HybridSearchQueryTests.cs

Lines changed: 96 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,85 +18,110 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Query
1818
[TestCategory("Query")]
1919
public sealed class HybridSearchQueryTests : QueryTestsBase
2020
{
21-
private const string CollectionDataPath = "D:\\cosmosdb\\Product\\Backend\\native\\Test\\resources\\TestInput\\FullText\\text-3properties-1536dimensions-100documents.json";
21+
private const string CollectionDataPath = "Documents\\text-3properties-1536dimensions-100documents.json";
2222

2323
private static readonly IndexingPolicy CompositeIndexPolicy = CreateIndexingPolicy();
2424

2525
[TestMethod]
26-
public async Task AllTests()
26+
public async Task SanityTests()
2727
{
28-
Trace.WriteLine("Started HybridSearchQueryTests.AllTests...");
28+
Trace.WriteLine("Started HybridSearchQueryTests.SanityTests...");
2929
Trace.AutoFlush = true;
3030

31-
IReadOnlyList<string> documents = await LoadDocuments();
31+
CosmosArray documentsArray = await LoadDocuments();
32+
IEnumerable<string> documents = documentsArray.Select(document => document.ToString());
3233

3334
await this.CreateIngestQueryDeleteAsync(
3435
connectionModes: ConnectionModes.Direct, // | ConnectionModes.Gateway,
3536
collectionTypes: CollectionTypes.MultiPartition, // | CollectionTypes.SinglePartition,
3637
documents: documents,
37-
query: RunTests,
38+
query: RunSanityTests,
3839
indexingPolicy: CompositeIndexPolicy);
3940
}
4041

41-
private static async Task RunTests(Container container, IReadOnlyList<CosmosObject> _)
42+
private static async Task RunSanityTests(Container container, IReadOnlyList<CosmosObject> _)
4243
{
43-
List<string> queryText = new List<string>
44+
List<SanityTest> testCases = new List<SanityTest>
4445
{
45-
//@"
46-
//SELECT c.title AS Title, c.text AS Text
47-
//FROM c
48-
//WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John')
49-
//ORDER BY RANK FullTextScore(c.title, ['John'])",
50-
@"
51-
SELECT c.title AS Title, c.text AS Text
52-
FROM c
53-
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John') OR FullTextContains(c.text, 'United States')
54-
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))",
46+
MakeSanityTest(@"
47+
SELECT c.index AS Index, c.title AS Title, c.text AS Text
48+
FROM c
49+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John')
50+
ORDER BY RANK FullTextScore(c.title, ['John'])",
51+
new List<int>{ 2, 57, 85 }),
52+
MakeSanityTest(@"
53+
SELECT TOP 10 c.index AS Index, c.title AS Title, c.text AS Text
54+
FROM c
55+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John')
56+
ORDER BY RANK FullTextScore(c.title, ['John'])",
57+
new List<int>{ 2, 57, 85 }),
58+
MakeSanityTest(@"
59+
SELECT c.index AS Index, c.title AS Title, c.text AS Text
60+
FROM c
61+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John')
62+
ORDER BY RANK FullTextScore(c.title, ['John'])
63+
OFFSET 1 LIMIT 5",
64+
new List<int>{ 57, 85 }),
65+
MakeSanityTest(@"
66+
SELECT c.index AS Index, c.title AS Title, c.text AS Text
67+
FROM c
68+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John') OR FullTextContains(c.text, 'United States')
69+
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))",
70+
new List<int>{ 61, 51, 49, 54, 75, 24, 77, 76, 80, 25, 22, 2, 66, 57, 85 }),
71+
MakeSanityTest(@"
72+
SELECT TOP 10 c.index AS Index, c.title AS Title, c.text AS Text
73+
FROM c
74+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John') OR FullTextContains(c.text, 'United States')
75+
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))",
76+
new List<int>{ 61, 51, 49, 54, 75, 24, 77, 76, 80, 25 }),
77+
MakeSanityTest(@"
78+
SELECT c.index AS Index, c.title AS Title, c.text AS Text
79+
FROM c
80+
WHERE FullTextContains(c.title, 'John') OR FullTextContains(c.text, 'John') OR FullTextContains(c.text, 'United States')
81+
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))
82+
OFFSET 5 LIMIT 10",
83+
new List<int>{ 24, 77, 76, 80, 25, 22, 2, 66, 57, 85 }),
84+
MakeSanityTest(@"
85+
SELECT TOP 10 c.index AS Index, c.title AS Title, c.text AS Text
86+
FROM c
87+
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))",
88+
new List<int>{ 61, 51, 49, 54, 75, 24, 77, 76, 80, 25 }),
89+
MakeSanityTest(@"
90+
SELECT c.index AS Index, c.title AS Title, c.text AS Text
91+
FROM c
92+
ORDER BY RANK RRF(FullTextScore(c.title, ['John']), FullTextScore(c.text, ['United States']))
93+
OFFSET 0 LIMIT 13",
94+
new List<int>{ 61, 51, 49, 54, 75, 24, 77, 76, 80, 25, 22, 2, 66 }),
5595
};
5696

57-
foreach (string query in queryText)
97+
foreach (SanityTest testCase in testCases)
5898
{
59-
await RunTestAsync(container, query);
60-
}
61-
}
99+
List<TextDocument> result = await RunQueryCombinationsAsync<TextDocument>(
100+
container,
101+
testCase.Query,
102+
queryRequestOptions: null,
103+
queryDrainingMode: QueryDrainingMode.HoldState);
62104

63-
private static async Task RunTestAsync(Container container, string queryText)
64-
{
65-
List<TextDocument> result = await RunQueryCombinationsAsync<TextDocument>(
66-
container,
67-
queryText,
68-
queryRequestOptions: null,
69-
queryDrainingMode: QueryDrainingMode.HoldState);
70-
Assert.IsTrue(result.Count > 0);
105+
IEnumerable<int> actual = result.Select(document => document.Index);
106+
if (!testCase.ExpectedIndices.SequenceEqual(actual))
107+
{
108+
Trace.WriteLine($"Query: {testCase.Query}");
109+
Trace.WriteLine($"Expected: {string.Join(", ", testCase.ExpectedIndices)}");
110+
Trace.WriteLine($"Actual: {string.Join(", ", actual)}");
111+
Assert.Fail("The query results did not match the expected results.");
112+
}
113+
}
71114
}
72115

73-
private static async Task<IReadOnlyList<string>> LoadDocuments()
116+
private static async Task<CosmosArray> LoadDocuments()
74117
{
75118
// read the json file
76119
string json = await File.ReadAllTextAsync(CollectionDataPath);
77120
byte[] jsonBuffer = Encoding.UTF8.GetBytes(json);
78121
ReadOnlyMemory<byte> readOnlyMemory = new ReadOnlyMemory<byte>(jsonBuffer);
79122
CosmosObject rootObject = CosmosObject.CreateFromBuffer(readOnlyMemory);
80-
if (!rootObject.TryGetValue(FieldNames.Items, out CosmosArray items))
81-
{
82-
throw new InvalidOperationException("Failed to find items in the json file.");
83-
}
84-
85-
int index = 0;
86-
List<string> documents = new List<string>();
87-
foreach (CosmosElement item in items)
88-
{
89-
CosmosObject itemObject = item as CosmosObject;
90-
Dictionary<string, CosmosElement> itemDictionary = new(itemObject)
91-
{
92-
{ "index", CosmosNumber.Parse(index.ToString()) }
93-
};
94-
95-
CosmosObject rewrittenItem = CosmosObject.Create(itemDictionary);
96-
documents.Add(rewrittenItem.ToString());
97-
}
98-
99-
return documents;
123+
Assert.IsTrue(rootObject.TryGetValue(FieldNames.Items, out CosmosArray items), "Failed to find items in the json file.");
124+
return items;
100125
}
101126

102127
private static IndexingPolicy CreateIndexingPolicy()
@@ -113,8 +138,26 @@ private static IndexingPolicy CreateIndexingPolicy()
113138
return policy;
114139
}
115140

141+
private static SanityTest MakeSanityTest(string query, IReadOnlyList<int> expectedIndices)
142+
{
143+
return new SanityTest
144+
{
145+
Query = query,
146+
ExpectedIndices = expectedIndices,
147+
};
148+
}
149+
150+
private sealed class SanityTest
151+
{
152+
public string Query { get; init; }
153+
154+
public IReadOnlyList<int> ExpectedIndices { get; init; }
155+
}
156+
116157
private sealed class TextDocument
117158
{
159+
public int Index { get; set; }
160+
118161
public string Title { get; set; }
119162

120163
public string Text { get; set; }
@@ -123,6 +166,8 @@ private sealed class TextDocument
123166
private static class FieldNames
124167
{
125168
public const string Items = "items";
169+
public const string Title = "title";
170+
public const string Text = "text";
126171
}
127172
}
128-
}
173+
}

0 commit comments

Comments
 (0)