Fix `validateDatabaseSchema` in schema tests

This commit is contained in:
Simon Binder 2023-03-23 17:56:50 +01:00
parent 954de410a9
commit d6e074e704
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
10 changed files with 78 additions and 13 deletions

View File

@ -1,3 +1,7 @@
## 2.7.0-dev
- Make `validateDatabaseSchema()` work in migration tests.
## 2.6.0
- Fix invalid schema verification code being generated for columns with a

View File

@ -91,10 +91,20 @@ extension VerifySelf on GeneratedDatabase {
final schemaOfThisDatabase = await collectSchemaInput(virtualTables);
// Collect the schema how it would be if we just called `createAll` on a
// clean database.
final referenceDb = _GenerateFromScratch(this, NativeDatabase.memory());
final referenceSchema = await referenceDb.collectSchemaInput(virtualTables);
// The expectedSchema expando will store the expected schema for this
// database when it's opened in a migration test. This allows this method
// to be used in migration tests -- otherwise, this would always compare the
// runtime schema to the latest schema from generated code.
var referenceSchema = expectedSchema[this];
if (referenceSchema == null) {
// Collect the schema how it would be if we just called `createAll` on a
// clean database.
final referenceDb = _GenerateFromScratch(this, NativeDatabase.memory());
referenceSchema = expectedSchema[this] ??
await referenceDb.collectSchemaInput(virtualTables);
await referenceDb.close();
}
verify(referenceSchema, schemaOfThisDatabase, validateDropped);
}

View File

@ -7,6 +7,8 @@ import 'package:sqlite3/sqlite3.dart';
import 'find_differences.dart';
Expando<List<Input>> expectedSchema = Expando();
class VerifierImplementation implements SchemaVerifier {
final SchemaInstantiationHelper helper;
final Random _random = Random();
@ -21,18 +23,22 @@ class VerifierImplementation implements SchemaVerifier {
if (table is VirtualTableInfo) table.entityName,
];
// Open the database to collect its schema. Put a delegate in between
// claiming that the actual version is what we expect.
await db.executor.ensureOpen(_DelegatingUser(expectedVersion, db));
final actualSchema = await db.executor.collectSchemaInput(virtualTables);
// Open another connection to instantiate and extract the reference schema.
// Open a connection to instantiate and extract the reference schema.
final otherConnection = await startAt(expectedVersion);
await otherConnection.executor.ensureOpen(_DelegatingUser(expectedVersion));
final referenceSchema =
await otherConnection.executor.collectSchemaInput(virtualTables);
await otherConnection.executor.close();
// Attach the reference schema to the database so that VerifySelf.validateDatabaseSchema
// works
expectedSchema[db] = referenceSchema;
// Open the database to collect its schema. Put a delegate in between
// claiming that the actual version is what we expect.
await db.executor.ensureOpen(_DelegatingUser(expectedVersion, db));
final actualSchema = await db.executor.collectSchemaInput(virtualTables);
verify(referenceSchema, actualSchema, validateDropped);
}

View File

@ -2,6 +2,8 @@ import 'dart:io';
import 'package:drift/drift.dart';
import 'package:drift/native.dart';
import 'package:drift_dev/api/migrations.dart';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
@ -18,3 +20,17 @@ DatabaseConnection connect() {
return NativeDatabase.createBackgroundConnection(await databaseFile);
}));
}
Future<void> validateDatabaseSchema(GeneratedDatabase database) async {
// This method validates that the actual schema of the opened database matches
// the tables, views, triggers and indices for which drift_dev has generated
// code.
// Validating the database's schema after opening it is generally a good idea,
// since it allows us to get an early warning if we change a table definition
// without writing a schema migration for it.
//
// For details, see: https://drift.simonbinder.eu/docs/advanced-features/migrations/#verifying-a-database-schema-at-runtime
if (kDebugMode) {
await VerifySelf(database).validateDatabaseSchema();
}
}

View File

@ -1,6 +1,17 @@
import 'package:drift/drift.dart';
DatabaseConnection connect() {
Never _unsupported() {
throw UnsupportedError(
'No suitable database implementation was found on this platform.');
}
// Depending on the platform the app is compiled to, the following stubs will
// be replaced with the methods in native.dart or web.dart
DatabaseConnection connect() {
_unsupported();
}
Future<void> validateDatabaseSchema(GeneratedDatabase database) async {
_unsupported();
}

View File

@ -36,3 +36,10 @@ DatabaseConnection connect({bool isInWebWorker = false}) {
}));
}
}
Future<void> validateDatabaseSchema(GeneratedDatabase database) async {
// Unfortunately, validating database schemas only works for native platforms
// right now.
// As we also have migration tests (see the `Testing migrations` section in
// the readme of this example), this is not a huge issue.
}

View File

@ -63,6 +63,11 @@ class AppDatabase extends _$AppDatabase {
]);
});
}
// This follows the recommendation to validate that the database schema
// matches what drift expects (https://drift.simonbinder.eu/docs/advanced-features/migrations/#verifying-a-database-schema-at-runtime).
// It allows catching bugs in the migration logic early.
await impl.validateDatabaseSchema(this);
},
);
}

View File

@ -11,6 +11,7 @@ dependencies:
flutter:
sdk: flutter
drift:
drift_dev:
file_picker: ^5.2.5
flutter_colorpicker: ^1.0.3
flutter_riverpod: ^2.3.0
@ -35,7 +36,6 @@ dev_dependencies:
# `build.yaml`.
build_web_compilers: ^3.2.2
build: ^2.2.1
drift_dev:
flutter:
uses-material-design: true

View File

@ -1,4 +1,5 @@
import 'package:drift/drift.dart';
import 'package:drift_dev/api/migrations.dart';
import 'tables.dart';
import 'src/generated/schema_v2.dart' as v2;
@ -72,6 +73,11 @@ class Database extends _$Database {
}
}
},
beforeOpen: (details) async {
// For Flutter apps, this should be wrapped in an if (kDebugMode) as
// suggested here: https://drift.simonbinder.eu/docs/advanced-features/migrations/#verifying-a-database-schema-at-runtime
await validateDatabaseSchema();
},
);
}
}

View File

@ -7,9 +7,9 @@ environment:
dependencies:
drift:
drift_dev:
dev_dependencies:
lints: ^2.0.0
drift_dev:
build_runner: ^2.0.0
test: ^1.15.4