Reorg SQLite tests

This commit is contained in:
Daniel J. Summers 2024-08-16 22:54:27 -04:00
parent fba8ec7bc5
commit d993f71788
2 changed files with 1348 additions and 1257 deletions

View File

@ -1,6 +1,5 @@
using Expecto.CSharp; using Expecto.CSharp;
using Expecto; using Expecto;
using Microsoft.Data.Sqlite;
using Microsoft.FSharp.Core; using Microsoft.FSharp.Core;
using BitBadger.Documents.Sqlite; using BitBadger.Documents.Sqlite;
@ -14,19 +13,16 @@ using static Runner;
public static class SqliteCSharpTests public static class SqliteCSharpTests
{ {
/// <summary> /// <summary>
/// Unit tests for the SQLite library /// Unit tests for the Query module of the SQLite library
/// </summary> /// </summary>
private static readonly Test Unit = TestList("Unit", private static readonly Test QueryTests = TestList("Query",
[
TestList("Query",
[ [
TestList("WhereByFields", TestList("WhereByFields",
[ [
TestCase("succeeds for a single field when a logical operator is passed", () => TestCase("succeeds for a single field when a logical operator is passed", () =>
{ {
Expect.equal( Expect.equal(
Sqlite.Query.WhereByFields(FieldMatch.Any, Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.GT("theField", 0).WithParameterName("@test")]),
[Field.GT("theField", 0).WithParameterName("@test")]),
"data->>'theField' > @test", "WHERE clause not correct"); "data->>'theField' > @test", "WHERE clause not correct");
}), }),
TestCase("succeeds for a single field when an existence operator is passed", () => TestCase("succeeds for a single field when an existence operator is passed", () =>
@ -44,8 +40,7 @@ public static class SqliteCSharpTests
TestCase("succeeds for all multiple fields with logical operators", () => TestCase("succeeds for all multiple fields with logical operators", () =>
{ {
Expect.equal( Expect.equal(
Sqlite.Query.WhereByFields(FieldMatch.All, Sqlite.Query.WhereByFields(FieldMatch.All, [Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]),
[Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]),
"data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct"); "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct");
}), }),
TestCase("succeeds for any multiple fields with an existence operator", () => TestCase("succeeds for any multiple fields with an existence operator", () =>
@ -80,8 +75,7 @@ public static class SqliteCSharpTests
}), }),
TestCase("ById succeeds", () => TestCase("ById succeeds", () =>
{ {
Expect.equal(Sqlite.Query.ById("test", "14"), "test WHERE data->>'Id' = @id", Expect.equal(Sqlite.Query.ById("test", "14"), "test WHERE data->>'Id' = @id", "By-ID query not correct");
"By-ID query not correct");
}), }),
TestCase("ByFields succeeds", () => TestCase("ByFields succeeds", () =>
{ {
@ -93,8 +87,12 @@ public static class SqliteCSharpTests
Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"), Expect.equal(Sqlite.Query.Definition.EnsureTable("tbl"),
"CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct"); "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)", "CREATE TABLE statement not correct");
}) })
]), ]);
TestList("Parameters",
/// <summary>
/// Unit tests for the Parameters module of the SQLite library
/// </summary>
private static readonly Test ParametersTests = TestList("Parameters",
[ [
TestCase("Id succeeds", () => TestCase("Id succeeds", () =>
{ {
@ -127,10 +125,13 @@ public static class SqliteCSharpTests
{ {
Expect.isEmpty(Parameters.None, "The parameter list should have been empty"); Expect.isEmpty(Parameters.None, "The parameter list should have been empty");
}) })
])
// Results are exhaustively executed in the context of other tests
]); ]);
// Results are exhaustively executed in the context of other tests
/// <summary>
/// Documents used for integration tests
/// </summary>
private static readonly List<JsonDocument> TestDocuments = private static readonly List<JsonDocument> TestDocuments =
[ [
new() { Id = "one", Value = "FIRST!", NumValue = 0 }, new() { Id = "one", Value = "FIRST!", NumValue = 0 },
@ -148,9 +149,10 @@ public static class SqliteCSharpTests
foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc); foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
} }
private static readonly Test Integration = TestList("Integration", /// <summary>
[ /// Integration tests for the Configuration module of the SQLite library
TestCase("Configuration.UseConnectionString succeeds", () => /// </summary>
private static readonly Test ConfigurationTests = TestCase("Configuration.UseConnectionString succeeds", () =>
{ {
try try
{ {
@ -162,8 +164,12 @@ public static class SqliteCSharpTests
{ {
Sqlite.Configuration.UseConnectionString("Data Source=:memory:"); Sqlite.Configuration.UseConnectionString("Data Source=:memory:");
} }
}), });
TestList("Custom",
/// <summary>
/// Integration tests for the Custom module of the SQLite library
/// </summary>
private static readonly Test CustomTests = TestList("Custom",
[ [
TestList("Single", TestList("Single",
[ [
@ -173,7 +179,7 @@ public static class SqliteCSharpTests
await LoadDocs(); await LoadDocs();
var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id", var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("one") }, Results.FromData<JsonDocument>); [Parameters.Id("one")], Results.FromData<JsonDocument>);
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc!.Id, "one", "The incorrect document was returned"); Expect.equal(doc!.Id, "one", "The incorrect document was returned");
}), }),
@ -183,7 +189,7 @@ public static class SqliteCSharpTests
await LoadDocs(); await LoadDocs();
var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id", var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>); [Parameters.Id("eighty")], Results.FromData<JsonDocument>);
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
]), ]),
@ -204,8 +210,8 @@ public static class SqliteCSharpTests
await LoadDocs(); await LoadDocs();
var docs = await Custom.List( var docs = await Custom.List(
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", $"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", [new("@value", 100)],
new[] { new SqliteParameter("@value", 100) }, Results.FromData<JsonDocument>); Results.FromData<JsonDocument>);
Expect.isEmpty(docs, "There should have been no documents returned"); Expect.isEmpty(docs, "There should have been no documents returned");
}) })
]), ]),
@ -227,7 +233,7 @@ public static class SqliteCSharpTests
await LoadDocs(); await LoadDocs();
await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
new[] { new SqliteParameter("@value", 100) }); [new("@value", 100)]);
var remaining = await Count.All(SqliteDb.TableName); var remaining = await Count.All(SqliteDb.TableName);
Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table"); Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table");
@ -240,8 +246,12 @@ public static class SqliteCSharpTests
var nbr = await Custom.Scalar("SELECT 5 AS test_value", Parameters.None, rdr => rdr.GetInt32(0)); var nbr = await Custom.Scalar("SELECT 5 AS test_value", Parameters.None, rdr => rdr.GetInt32(0));
Expect.equal(nbr, 5, "The query should have returned the number 5"); Expect.equal(nbr, 5, "The query should have returned the number 5");
}) })
]), ]);
TestList("Definition",
/// <summary>
/// Integration tests for the Definition module of the SQLite library
/// </summary>
private static readonly Test DefinitionTests = TestList("Definition",
[ [
TestCase("EnsureTable succeeds", async () => TestCase("EnsureTable succeeds", async () =>
{ {
@ -262,9 +272,8 @@ public static class SqliteCSharpTests
async ValueTask<bool> ItExists(string name) async ValueTask<bool> ItExists(string name)
{ {
return await Custom.Scalar( return await Custom.Scalar($"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it",
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it", [new("@name", name)], Results.ToExists);
new SqliteParameter[] { new("@name", name) }, Results.ToExists);
} }
}), }),
TestCase("EnsureFieldIndex succeeds", async () => TestCase("EnsureFieldIndex succeeds", async () =>
@ -275,7 +284,7 @@ public static class SqliteCSharpTests
Expect.isFalse(exists, "The index should not exist already"); Expect.isFalse(exists, "The index should not exist already");
await Definition.EnsureTable("ensured"); await Definition.EnsureTable("ensured");
await Definition.EnsureFieldIndex("ensured", "test", new[] { "Id", "Category" }); await Definition.EnsureFieldIndex("ensured", "test", ["Id", "Category"]);
exists = await IndexExists(); exists = await IndexExists();
Expect.isTrue(exists, "The index should now exist"); Expect.isTrue(exists, "The index should now exist");
return; return;
@ -284,8 +293,14 @@ public static class SqliteCSharpTests
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it", $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it",
Parameters.None, Results.ToExists); Parameters.None, Results.ToExists);
}) })
]), ]);
TestList("Document.Insert",
/// <summary>
/// Integration tests for the Document module of the SQLite library
/// </summary>
private static readonly Test DocumentTests = TestList("Document",
[
TestList("Insert",
[ [
TestCase("succeeds", async () => TestCase("succeeds", async () =>
{ {
@ -344,8 +359,13 @@ public static class SqliteCSharpTests
Expect.equal(after!.Id, "test", "The updated document is not correct"); Expect.equal(after!.Id, "test", "The updated document is not correct");
Expect.isNull(after.Sub, "There should not have been a sub-document in the updated document"); Expect.isNull(after.Sub, "There should not have been a sub-document in the updated document");
}) })
]), ])
TestList("Count", ]);
/// <summary>
/// Integration tests for the Count module of the SQLite library
/// </summary>
private static readonly Test CountTests = TestList("Count",
[ [
TestCase("All succeeds", async () => TestCase("All succeeds", async () =>
{ {
@ -362,8 +382,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.BT("NumValue", 10, 20)]);
[Field.BT("NumValue", 10, 20)]);
Expect.equal(theCount, 3L, "There should have been 3 matching documents"); Expect.equal(theCount, 3L, "There should have been 3 matching documents");
}), }),
TestCase("succeeds for non-numeric range", async () => TestCase("succeeds for non-numeric range", async () =>
@ -376,8 +395,12 @@ public static class SqliteCSharpTests
Expect.equal(theCount, 1L, "There should have been 1 matching document"); Expect.equal(theCount, 1L, "There should have been 1 matching document");
}) })
]) ])
]), ]);
TestList("Exists",
/// <summary>
/// Integration tests for the Exists module of the SQLite library
/// </summary>
private static readonly Test ExistsTests = TestList("Exists",
[ [
TestList("ById", TestList("ById",
[ [
@ -413,13 +436,16 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Nothing", "none")]);
[Field.EQ("Nothing", "none")]);
Expect.isFalse(exists, "There should not have been any existing documents"); Expect.isFalse(exists, "There should not have been any existing documents");
}) })
]) ])
]), ]);
TestList("Find",
/// <summary>
/// Integration tests for the Find module of the SQLite library
/// </summary>
private static readonly Test FindTests = TestList("Find",
[ [
TestList("All", TestList("All",
[ [
@ -502,7 +528,7 @@ public static class SqliteCSharpTests
var doc = await Find.FirstByFields<JsonDocument>(SqliteDb.TableName, FieldMatch.Any, var doc = await Find.FirstByFields<JsonDocument>(SqliteDb.TableName, FieldMatch.Any,
[Field.EQ("Sub.Foo", "green")]); [Field.EQ("Sub.Foo", "green")]);
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "two", "four" }, doc!.Id, "An incorrect document was returned"); Expect.contains(["two", "four"], doc!.Id, "An incorrect document was returned");
}), }),
TestCase("succeeds when a document is not found", async () => TestCase("succeeds when a document is not found", async () =>
{ {
@ -514,8 +540,12 @@ public static class SqliteCSharpTests
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
]) ])
]), ]);
TestList("Update",
/// <summary>
/// Integration tests for the Update module of the SQLite library
/// </summary>
private static readonly Test UpdateTests = TestList("Update",
[ [
TestList("ById", TestList("ById",
[ [
@ -573,8 +603,12 @@ public static class SqliteCSharpTests
new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
}) })
]), ]),
]), ]);
TestList("Patch",
/// <summary>
/// Integration tests for the Patch module of the SQLite library
/// </summary>
private static readonly Test PatchTests = TestList("Patch",
[ [
TestList("ById", TestList("ById",
[ [
@ -624,8 +658,12 @@ public static class SqliteCSharpTests
new { Foo = "green" }); new { Foo = "green" });
}) })
]) ])
]), ]);
TestList("RemoveFields",
/// <summary>
/// Integration tests for the RemoveFields module of the SQLite library
/// </summary>
private static readonly Test RemoveFieldsTests = TestList("RemoveFields",
[ [
TestList("ById", TestList("ById",
[ [
@ -634,7 +672,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Sub", "Value" }); await RemoveFields.ById(SqliteDb.TableName, "two", ["Sub", "Value"]);
var updated = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "two"); var updated = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "two");
Expect.isNotNull(updated, "The updated document should have been retrieved"); Expect.isNotNull(updated, "The updated document should have been retrieved");
Expect.equal(updated.Value, "", "The string value should have been removed"); Expect.equal(updated.Value, "", "The string value should have been removed");
@ -646,14 +684,14 @@ public static class SqliteCSharpTests
await LoadDocs(); await LoadDocs();
// This not raising an exception is the test // This not raising an exception is the test
await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "AFieldThatIsNotThere" }); await RemoveFields.ById(SqliteDb.TableName, "two", ["AFieldThatIsNotThere"]);
}), }),
TestCase("succeeds when no document is matched", async () => TestCase("succeeds when no document is matched", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
// This not raising an exception is the test // This not raising an exception is the test
await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Value" }); await RemoveFields.ById(SqliteDb.TableName, "two", ["Value"]);
}) })
]), ]),
TestList("ByFields", TestList("ByFields",
@ -663,8 +701,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], ["Sub"]);
new[] { "Sub" });
var updated = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "four"); var updated = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "four");
Expect.isNotNull(updated, "The updated document should have been retrieved"); Expect.isNotNull(updated, "The updated document should have been retrieved");
Expect.isNull(updated.Sub, "The sub-document should have been removed"); Expect.isNull(updated.Sub, "The sub-document should have been removed");
@ -676,7 +713,7 @@ public static class SqliteCSharpTests
// This not raising an exception is the test // This not raising an exception is the test
await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)],
new[] { "Nothing" }); ["Nothing"]);
}), }),
TestCase("succeeds when no document is matched", async () => TestCase("succeeds when no document is matched", async () =>
{ {
@ -684,11 +721,15 @@ public static class SqliteCSharpTests
// This not raising an exception is the test // This not raising an exception is the test
await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")], await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")],
new[] { "Value" }); ["Value"]);
}) })
]) ])
]), ]);
TestList("Delete",
/// <summary>
/// Integration tests for the Delete module of the SQLite library
/// </summary>
private static readonly Test DeleteTests = TestList("Delete",
[ [
TestList("ById", TestList("ById",
[ [
@ -732,13 +773,29 @@ public static class SqliteCSharpTests
Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
}) })
]) ])
]),
TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
]); ]);
/// <summary> /// <summary>
/// All tests for SQLite C# functions and methods /// All tests for SQLite C# functions and methods
/// </summary> /// </summary>
[Tests] [Tests]
public static readonly Test All = TestList("Sqlite.C#", [Unit, TestSequenced(Integration)]); public static readonly Test All = TestList("Sqlite.C#",
[
TestList("Unit", [QueryTests, ParametersTests]),
TestSequenced(TestList("Integration",
[
ConfigurationTests,
CustomTests,
DefinitionTests,
DocumentTests,
CountTests,
ExistsTests,
FindTests,
UpdateTests,
PatchTests,
RemoveFieldsTests,
DeleteTests,
TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
]))
]);
} }

View File

@ -10,10 +10,10 @@ open Types
#nowarn "0044" #nowarn "0044"
/// Unit tests for the SQLite library (** UNIT TESTS **)
let unitTests =
testList "Unit" [ /// Unit tests for the Query module of the SQLite library
testList "Query" [ let queryTests = testList "Query" [
testList "whereByFields" [ testList "whereByFields" [
test "succeeds for a single field when a logical operator is passed" { test "succeeds for a single field when a logical operator is passed" {
Expect.equal Expect.equal
@ -82,8 +82,10 @@ let unitTests =
"CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)" "CREATE TABLE IF NOT EXISTS tbl (data TEXT NOT NULL)"
"CREATE TABLE statement not correct" "CREATE TABLE statement not correct"
} }
] ]
testList "Parameters" [
/// Unit tests for the Parameters module of the SQLite library
let parametersTests = testList "Parameters" [
test "idParam succeeds" { test "idParam succeeds" {
let theParam = idParam 7 let theParam = idParam 7
Expect.equal theParam.ParameterName "@id" "The parameter name is incorrect" Expect.equal theParam.ParameterName "@id" "The parameter name is incorrect"
@ -110,24 +112,28 @@ let unitTests =
test "noParams succeeds" { test "noParams succeeds" {
Expect.isEmpty noParams "The parameter list should have been empty" Expect.isEmpty noParams "The parameter list should have been empty"
} }
] ]
// Results are exhaustively executed in the context of other tests // Results are exhaustively executed in the context of other tests
]
/// These tests each use a fresh copy of a SQLite database
let integrationTests = (** INTEGRATION TESTS **)
let documents = [
/// Documents used for integration tests
let documents = [
{ Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None } { Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None }
{ Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } } { Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } }
{ Id = "three"; Value = ""; NumValue = 4; Sub = None } { Id = "three"; Value = ""; NumValue = 4; Sub = None }
{ Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } } { Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } }
{ Id = "five"; Value = "purple"; NumValue = 18; Sub = None } { Id = "five"; Value = "purple"; NumValue = 18; Sub = None }
] ]
let loadDocs () = backgroundTask {
/// Load a table with the test documents
let loadDocs () = backgroundTask {
for doc in documents do do! insert SqliteDb.TableName doc for doc in documents do do! insert SqliteDb.TableName doc
} }
testList "Integration" [
testList "Configuration" [ /// Integration tests for the Configuration module of the SQLite library
let configurationTests = testList "Configuration" [
test "useConnectionString / connectionString succeed" { test "useConnectionString / connectionString succeed" {
try try
Configuration.useConnectionString "Data Source=test.db" Configuration.useConnectionString "Data Source=test.db"
@ -164,8 +170,10 @@ let integrationTests =
Expect.equal (Configuration.idField ()) "id" "useIdField did not set the ID field" Expect.equal (Configuration.idField ()) "id" "useIdField did not set the ID field"
Configuration.useIdField "Id" Configuration.useIdField "Id"
} }
] ]
testList "Custom" [
/// Integration tests for the Custom module of the SQLite library
let customTests = testList "Custom" [
testList "single" [ testList "single" [
testTask "succeeds when a row is found" { testTask "succeeds when a row is found" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -196,7 +204,7 @@ let integrationTests =
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! docs = Custom.list (Query.selectFromTable SqliteDb.TableName) [] fromData<JsonDocument> let! docs = Custom.list (Query.find SqliteDb.TableName) [] fromData<JsonDocument>
Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned" Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned"
} }
testTask "succeeds when data is not found" { testTask "succeeds when data is not found" {
@ -239,8 +247,10 @@ let integrationTests =
let! nbr = Custom.scalar "SELECT 5 AS test_value" [] _.GetInt32(0) let! nbr = Custom.scalar "SELECT 5 AS test_value" [] _.GetInt32(0)
Expect.equal nbr 5 "The query should have returned the number 5" Expect.equal nbr 5 "The query should have returned the number 5"
} }
] ]
testList "Definition" [
/// Integration tests for the Definition module of the SQLite library
let definitionTests = testList "Definition" [
testTask "ensureTable succeeds" { testTask "ensureTable succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
let itExists (name: string) = let itExists (name: string) =
@ -276,7 +286,10 @@ let integrationTests =
let! exists' = indexExists () let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist" Expect.isTrue exists' "The index should now exist"
} }
] ]
/// Integration tests for the (auto-opened) Document module of the SQLite library
let documentTests = testList "Document" [
testList "insert" [ testList "insert" [
testTask "succeeds" { testTask "succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -324,7 +337,10 @@ let integrationTests =
Expect.equal after.Value upd8Doc "The updated document is not correct" Expect.equal after.Value upd8Doc "The updated document is not correct"
} }
] ]
testList "Count" [ ]
/// Integration tests for the Count module of the SQLite library
let countTests = testList "Count" [
testTask "all succeeds" { testTask "all succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
do! loadDocs () do! loadDocs ()
@ -348,8 +364,10 @@ let integrationTests =
Expect.equal theCount 1L "There should have been 1 matching document" Expect.equal theCount 1L "There should have been 1 matching document"
} }
] ]
] ]
testList "Exists" [
/// Integration tests for the Exists module of the SQLite library
let existsTests = testList "Exists" [
testList "byId" [ testList "byId" [
testTask "succeeds when a document exists" { testTask "succeeds when a document exists" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -382,8 +400,10 @@ let integrationTests =
Expect.isFalse exists "There should not have been any existing documents" Expect.isFalse exists "There should not have been any existing documents"
} }
] ]
] ]
testList "Find" [
/// Integration tests for the Find module of the SQLite library
let findTests = testList "Find" [
testList "all" [ testList "all" [
testTask "succeeds when there is data" { testTask "succeeds when there is data" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -393,12 +413,10 @@ let integrationTests =
do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" } do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" }
let! results = Find.all<SubDocument> SqliteDb.TableName let! results = Find.all<SubDocument> SqliteDb.TableName
let expected = [ Expect.equal
{ Foo = "one"; Bar = "two" } results
{ Foo = "three"; Bar = "four" } [ { Foo = "one"; Bar = "two" }; { Foo = "three"; Bar = "four" }; { Foo = "five"; Bar = "six" } ]
{ Foo = "five"; Bar = "six" } "There should have been 3 documents returned"
]
Expect.equal results expected "There should have been 3 documents returned"
} }
testTask "succeeds when there is no data" { testTask "succeeds when there is no data" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -464,8 +482,10 @@ let integrationTests =
Expect.isFalse (Option.isSome doc) "There should not have been a document returned" Expect.isFalse (Option.isSome doc) "There should not have been a document returned"
} }
] ]
] ]
testList "Update" [
/// Integration tests for the Update module of the SQLite library
let updateTests = testList "Update" [
testList "byId" [ testList "byId" [
testTask "succeeds when a document is updated" { testTask "succeeds when a document is updated" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -485,9 +505,7 @@ let integrationTests =
// This not raising an exception is the test // This not raising an exception is the test
do! Update.byId do! Update.byId
SqliteDb.TableName SqliteDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } }
"test"
{ emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } }
} }
] ]
testList "byFunc" [ testList "byFunc" [
@ -495,8 +513,7 @@ let integrationTests =
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
do! loadDocs () do! loadDocs ()
do! Update.byFunc do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
let! after = Find.byId<string, JsonDocument> SqliteDb.TableName "one" let! after = Find.byId<string, JsonDocument> SqliteDb.TableName "one"
Expect.isSome after "There should have been a document returned post-update" Expect.isSome after "There should have been a document returned post-update"
Expect.equal Expect.equal
@ -511,12 +528,13 @@ let integrationTests =
Expect.isEmpty before "There should have been no documents returned" Expect.isEmpty before "There should have been no documents returned"
// This not raising an exception is the test // This not raising an exception is the test
do! Update.byFunc do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
} }
] ]
] ]
testList "Patch" [
/// Integration tests for the Patch module of the SQLite library
let patchTests = testList "Patch" [
testList "byId" [ testList "byId" [
testTask "succeeds when a document is updated" { testTask "succeeds when a document is updated" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -556,8 +574,10 @@ let integrationTests =
do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |} do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |}
} }
] ]
] ]
testList "RemoveFields" [
/// Integration tests for the RemoveFields module of the SQLite library
let removeFieldsTests = testList "RemoveFields" [
testList "byId" [ testList "byId" [
testTask "succeeds when fields is removed" { testTask "succeeds when fields is removed" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -612,8 +632,10 @@ let integrationTests =
do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ] do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ]
} }
] ]
] ]
testList "Delete" [
/// Integration tests for the Delete module of the SQLite library
let deleteTests = testList "Delete" [
testList "byId" [ testList "byId" [
testTask "succeeds when a document is deleted" { testTask "succeeds when a document is deleted" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
@ -650,11 +672,23 @@ let integrationTests =
Expect.equal remaining 5L "There should have been 5 documents remaining" Expect.equal remaining 5L "There should have been 5 documents remaining"
} }
] ]
] ]
test "clean up database" {
Configuration.useConnectionString "data source=:memory:"
}
]
|> testSequenced
let all = testList "Sqlite" [ unitTests; integrationTests ] /// All tests for the SQLite library
let all = testList "Sqlite" [
testList "Unit" [ queryTests; parametersTests ]
testSequenced <| testList "Integration" [
configurationTests
customTests
definitionTests
documentTests
countTests
existsTests
findTests
updateTests
patchTests
removeFieldsTests
deleteTests
test "clean up database" { Configuration.useConnectionString "data source=:memory:" }
]
]