Agent Skills
› tekartik/sqflite
› sqflite-common-ffi-async-test-suite
sqflite-common-ffi-async-test-suite
GitHub提供 sqflite_common_ffi_async 包的共享测试套件运行指南,包括依赖配置、上下文构建及用例执行策略。
Trigger Scenarios
需要测试 sqflite_common_ffi_async 兼容性
运行共享测试套件
Install
npx skills add tekartik/sqflite --skill sqflite-common-ffi-async-test-suite -g -y
SKILL.md
Frontmatter
{
"name": "sqflite-common-ffi-async-test-suite",
"description": "Use when testing package:sqflite_common_ffi_async (the sqlite_async based sqflite DatabaseFactory) against the shared sqflite suite with sqflite_common_ffi_async_test: runFfiAsyncTests(context), the all: true full-suite switch, building the SqfliteTestContext (SqfliteLocalTestContext, supportsConcurrentRead, supportsUri), databaseFactoryFfiAsync \/ databaseFactoryFfiAsyncTest, which sqflite_common_test suites are known to pass or fail, and @TestOn('vm')."
}
Shared test suite for the ffi async factory (sqflite_common_ffi_async_test)
sqflite_common_ffi_async_test is a thin runner over sqflite_common_test: it
knows which parts of the shared sqflite suite sqflite_common_ffi_async
currently passes and exposes them as a single call,
runFfiAsyncTests(context).
Guidelines
- Dependency (not on pub.dev,
publish_to: none), indev_dependencies:dev_dependencies: sqflite_common_ffi_async_test: git: url: https://github.com/tekartik/sqflite path: packages/sqflite_common_ffi_async_test sqflite_common_test: git: url: https://github.com/tekartik/sqflite path: sqflite_common_test version: '>=0.3.0'sqflite_common_testis needed forSqfliteTestContext/SqfliteLocalTestContext;sqflite_common_ffi_asyncfor the factory. - Single entry point:
package:sqflite_common_ffi_async_test/all_test.dartexportsrunFfiAsyncTests(SqfliteTestContext context, {bool all = false}). Call it atmain()level, never insidetest()orsetUp(). Everything it defines lands in agroup('all', ...). - Default run (
allleft tofalse) declares the suites known to pass:doc_test(withnoLoggerTest: true),batch_test(noManualTransactionTest: true),exp_test(noMultipleStatement: true),slow_test,type_test,statement_test,raw_test,issue_testandwalTests. This is the CI run. runFfiAsyncTests(context, all: true)additionally declares the whole shared suite (protocol_test,service_impl_test,open_test,open_flutter_test,exception_test,database_factory_test,transaction_test, the unrestricteddoc_test/batch_test/exp_test...). Those still have known failures (logger, protocol, exception parsing, delete/exists edge cases): use it in a separate*_alltest file to investigate, not as the gate.- Build the context with
SqfliteLocalTestContextfrompackage:sqflite_common_test/sqflite_test.dart, and set the two flags that differ for this implementation:supportsConcurrentRead => true(it is the only sqflite factory with a read pool) andsupportsUri => false(nofile:uri paths, unlikedatabaseFactoryFfi). - Factory:
databaseFactoryFfiAsyncfrompackage:sqflite_common_ffi_async/sqflite_ffi_async.dart;databaseFactoryFfiAsyncTestis the same implementation with a separate tag when a test must not share state with application code. NosqfliteFfiInit()call is needed, contrary tosqflite_common_ffi. - VM only: put
@TestOn('vm')beforelibrary;. Run withdart test(orflutter testin a Flutter package). The suite is file based, so it writes under the factory's databases path; give a parallel second suite file its own path withsetDatabasesPathin anasyncmain(). - Single shared suites can also be run straight from
sqflite_common_test(raw_test.run(context),walTests(context)...) when narrowing down a failure; see thesqflite-common-test-suiteskill for the full list. - Debugging a failing test: wrap the factory in
databaseFactoryFfiAsync.debugQuickLoggerWrapper()(deprecated, dev only, needs an// ignore: deprecated_member_use) to print every invoked method.
Examples
Standard suite run (CI)
@TestOn('vm')
library;
import 'package:sqflite_common_ffi_async/sqflite_ffi_async.dart';
import 'package:sqflite_common_ffi_async_test/all_test.dart';
import 'package:sqflite_common_test/sqflite_test.dart';
import 'package:test/test.dart';
class SqfliteFfiAsyncTestContext extends SqfliteLocalTestContext {
SqfliteFfiAsyncTestContext()
: super(databaseFactory: databaseFactoryFfiAsync);
@override
bool get supportsConcurrentRead => true;
@override
bool get supportsUri => false;
}
void main() {
runFfiAsyncTests(SqfliteFfiAsyncTestContext());
}
Full suite, with known failures, in its own file and databases path
@TestOn('vm')
library;
import 'package:sqflite_common_ffi_async/sqflite_ffi_async.dart';
import 'package:sqflite_common_ffi_async_test/all_test.dart';
import 'package:sqflite_common_test/sqflite_test.dart';
import 'package:test/test.dart';
final _factory = databaseFactoryFfiAsyncTest;
Future<void> main() async {
var dbsPath = await _factory.getDatabasesPath();
await _factory.setDatabasesPath('${dbsPath}_ffi_async_all');
runFfiAsyncTests(
SqfliteLocalTestContext(databaseFactory: _factory),
all: true,
);
}
Narrowing down: one shared suite only
@TestOn('vm')
library;
import 'package:sqflite_common_ffi_async/sqflite_ffi_async.dart';
import 'package:sqflite_common_test/raw_test.dart' as raw_test;
import 'package:sqflite_common_test/sqflite_test.dart';
import 'package:sqflite_common_test/transaction_test.dart' as transaction_test;
import 'package:test/test.dart';
void main() {
var context = SqfliteLocalTestContext(
databaseFactory: databaseFactoryFfiAsync,
);
raw_test.run(context);
transaction_test.run(context);
}
Own concurrency test on top of the same context
@TestOn('vm')
library;
import 'dart:async';
import 'package:sqflite_common_ffi_async/sqflite_ffi_async.dart';
import 'package:sqflite_common_test/sqflite_test.dart';
import 'package:test/test.dart';
void main() {
var context = SqfliteLocalTestContext(
databaseFactory: databaseFactoryFfiAsync,
);
test('two read transactions overlap', () async {
var path = await context.initDeleteDb('concurrent_read.db');
var db = await context.databaseFactory.openDatabase(path);
try {
await db.execute('CREATE TABLE Item (id INTEGER PRIMARY KEY, name TEXT)');
var first = Completer<void>();
var second = Completer<void>();
unawaited(
db.readTransaction((txn) async {
first.complete();
await second.future; // held open while the second one runs
}),
);
await first.future;
await db.readTransaction((txn) async {
expect(await txn.query('Item'), isEmpty);
second.complete();
});
} finally {
await db.close();
}
});
}
Version History
- aaabf90 Current 2026-09-22 03:38


