sqltest
Test SQL compatibility between different implementations.
Running Tests
The tests are run using sqltest which is written in Go.
Each test is a templatized file of SQL
statements run against a particular implementation and the output compared with the expected
output. These files are in testdata/sql, testdata/output, and
testdata/expected.
The files in sqltestdb/testdata/* are for testing the implementation of sqltest.
To control which implementation is run, specify it as an argument to sqltest.
Use the following flags to control the tests:
-update: update the expected output.
-testdata <directory>: specify a different directory for testdata; the default is testdata.
-sqlite3: data source to use for sqlite3; the default is :memory:.
-postgres: data source to use for postgres; there is no default.
-mysql: data source to use for mysql; there is no default.
-aws: use an AWS RDS instance for postgres; one will be started if necessary.
I use dev/test RDS instances in AWS for testing. For example, to run against just postgres, use
the following command:
./sqltest -postgres "host=<host>.rds.amazonaws.com port=5432 dbname=<dbname> user=<user> password=<password>" postgres
or
./sqltest -aws postgres
To update the expected output to be the output from postres, add -update.
./sqltest -update -postgres ...
Finally, to run all of the tests against all of the supported implementations, do the following:
./sqltest -postgres "host=<host>.rds.amazonaws.com port=5432 dbname=<dbname> user=<user> password=<password>" -mysql "<user>:<password>@tcp(<host>.rds.amazonaws.com)/<dbname>" postgres mysql sqlite3
To test against a local postgres instance, I use:
./sqltest -postgres "host=localhost port=5432 dbname=test sslmode=disable" postgres
Writing Tests
Template actions are delimited by {{ and }} in the test files; see the Go
template package for more details.
{{Skip}}: skip the rest of this test; this should go at the top of the file, typically
after testing for a specific implementation.
{{Dialect}}: specifies which implementation is being tested.
{{Fail .Test|.Global [true|false]}}: specify whether the next statement (.Test) or all
following statements (.Global) should succeed or fail. The initial default is that all
statements succeed.
{{Statement .Test|.Global <stmt>}}: specify the kind of next statement (.Test) or all
following statements (.Global). The initial keyword of each SQL statement is used to
determine whether the statement is a SELECT or not. This is necessary to know whether or not to
expect a set of rows as the result. Use this action to override this.
{{Sort .Test|.Global true|false}}: specify whether or not the set of rows from the next
statement (.Test) or all following statements (.Global) are sorted. The default is that they
are not sorted.
{{Types .Test|.Global true|false}}: specify whether or not the columns from the next
statement (.Test) or all following statements (.Global) should include types. The default is
not to.
{{BINARY [<length>]}}: the column type appropriate to the implementation.
{{VARBINARY [<length>]}}: the column type appropriate to the implementation.
{{BLOB [<length>]}}: the column type appropriate to the implementation.
{{TEXT [<length>]}}: the column type appropriate to the implementation.
Examples
Put the following at the top of a test file to skip the file if it is mysql that is being tested.The -- at the start of the line is to keep it from being treated as SQL.
-- {{if eq Dialect "mysql"}}{{Skip}}{{end}}
Indicate that the next statement should fail.
{{Fail .Test}}
INSERT INTO tbl4 VALUES
(1 = 'abc');
See testdata/sql/create.sql and testdata/sql/insert_bool.sql for more examples of
template usage.
Adding SQL Implementations
Package sqltestdb is used to test SQL compatibility between different implementations.
Implementations that have a database driver for Go should be added to ./gosql.go.
Otherwise, RunTests should be called directly.