Finish unit tests
This commit is contained in:
@@ -4,7 +4,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CritterFolio.DataModels;
|
using CritterFolio.DataModels;
|
||||||
using Microsoft.VisualBasic.FileIO;
|
using System.Reflection;
|
||||||
using SQLite;
|
using SQLite;
|
||||||
|
|
||||||
namespace CritterFolio.Services;
|
namespace CritterFolio.Services;
|
||||||
@@ -32,6 +32,13 @@ public static class DatabaseService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool TestDbConnection()
|
||||||
|
{
|
||||||
|
return _db != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static async Task ClearAllTables()
|
public static async Task ClearAllTables()
|
||||||
{
|
{
|
||||||
await Init();
|
await Init();
|
||||||
@@ -183,4 +190,96 @@ public static class DatabaseService
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#region Tests
|
||||||
|
#if DEBUG
|
||||||
|
|
||||||
|
public class ColumnInfo
|
||||||
|
{
|
||||||
|
public int Cid { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public int NotNull { get; set; }
|
||||||
|
public string Dflt_Value { get; set; }
|
||||||
|
public int Pk { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<bool> VerifySchemaAgainstModel<T>()
|
||||||
|
{
|
||||||
|
if (_db is null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error: Database connection is null.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically determine the table name from the [Table] attribute or the Class name
|
||||||
|
var modelType = typeof(T);
|
||||||
|
var tableAttribute = modelType.GetCustomAttribute<TableAttribute>();
|
||||||
|
string tableName = tableAttribute != null ? tableAttribute.Name : modelType.Name;
|
||||||
|
|
||||||
|
Console.WriteLine($"--- Schema Verification: {tableName} (Class: {modelType.Name}) ---");
|
||||||
|
|
||||||
|
var dbColumns = await _db.QueryAsync<ColumnInfo>($"PRAGMA table_info('{tableName}')");
|
||||||
|
var dbColumnNames = dbColumns.Select(c => c.Name.ToLower()).ToList();
|
||||||
|
|
||||||
|
if (!dbColumns.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Result: Failure. Table '{tableName}' does not exist in the database.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine($"Database columns for table '{tableName}' ({dbColumns.Count}):");
|
||||||
|
foreach (var col in dbColumns)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Column: {col.Name} | Type: {col.Type} | PK: {col.Pk == 1}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelProperties = modelType
|
||||||
|
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||||
|
.Where(p => p.GetCustomAttribute<IgnoreAttribute>() == null)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Console.WriteLine($"Model properties for class '{modelType.Name}' ({modelProperties.Count}):");
|
||||||
|
foreach (var prop in modelProperties)
|
||||||
|
{
|
||||||
|
// Detect if the property has a [Column] attribute name override
|
||||||
|
var colAttr = prop.GetCustomAttribute<ColumnAttribute>();
|
||||||
|
string expectedColName = colAttr != null ? colAttr.Name : prop.Name;
|
||||||
|
Console.WriteLine($" Property: {prop.Name} (Expected Column: {expectedColName}) | Type: {prop.PropertyType.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match based on the expected column name (either property name or [Column] attribute)
|
||||||
|
var expectedColumnNames = modelProperties.Select(p => {
|
||||||
|
var attr = p.GetCustomAttribute<ColumnAttribute>();
|
||||||
|
return (attr != null ? attr.Name : p.Name).ToLower();
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
var missingInDb = expectedColumnNames.Where(p => !dbColumnNames.Contains(p)).ToList();
|
||||||
|
var extraInDb = dbColumnNames.Where(c => !expectedColumnNames.Contains(c)).ToList();
|
||||||
|
|
||||||
|
bool isMatch = !missingInDb.Any();
|
||||||
|
|
||||||
|
if (missingInDb.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Result: Failure. Columns missing in database: {string.Join(", ", missingInDb)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extraInDb.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Note: Database contains extra columns: {string.Join(", ", extraInDb)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMatch)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Result: Success. Class '{modelType.Name}' matches table '{tableName}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("-------------------------------------------\n");
|
||||||
|
return isMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@@ -8,20 +8,24 @@ namespace CritterFolioTests;
|
|||||||
|
|
||||||
public class Tests
|
public class Tests
|
||||||
{
|
{
|
||||||
[SetUp]
|
[Test]
|
||||||
public void Setup()
|
public async Task TestDatabaseCreation()
|
||||||
{
|
{
|
||||||
|
await DatabaseService.Init();
|
||||||
|
|
||||||
|
Assert.That(DatabaseService.TestDbConnection(), Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task TestAddingCritter()
|
public async Task TestDatabaseSchema()
|
||||||
{
|
{
|
||||||
Assert.That(await DatabaseService.AddCritter(new Critter{Name = "Test Critter"}), Is.True);
|
await DatabaseService.Init();
|
||||||
}
|
|
||||||
|
Assert.Multiple(async () =>
|
||||||
[Test]
|
{
|
||||||
public async Task TestGettingCritterThatDoesntExist()
|
Assert.That(await DatabaseService.VerifySchemaAgainstModel<Critter>(), Is.True);
|
||||||
{
|
Assert.That(await DatabaseService.VerifySchemaAgainstModel<Document>(), Is.True);
|
||||||
Assert.That(await DatabaseService.GetCritter(-1), Is.False);
|
Assert.That(await DatabaseService.VerifySchemaAgainstModel<CritterEvent>(), Is.True);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user