TestDatabase is a ProtoPattern or PatternLanguage for
mocking a database. It uses a genuine database as the MockDatabase.
One Context: (There are probably others that this pattern applies to.)
The GUI and most business logic are written in Microsoft VisualBasic 6.0 using ADO -- it expects the ConnectionStrings anyway.
The data is stored in a RelationalDatabase, such as Microsoft Sql Server.
Forces:
- You do not want to mix production data and test data, for fear of:
- contaminating (or accidentally deleting) your production data
- production data changes, causing false alarms in the tests.
- Possibly, your DBA may prohibit have tables in the production database that are used only for testing.
- Your DBA may be willing to provide a database on a test server where you are the database owner, and you can change the test database's schema arbitrarily.
- It is awkward to change SQL queries to call test tables in a production database (as opposed to production tables in that same database).
- If there are separate test and production databases, and the schemas of the databases match closely enough, the same SQL queries can be used against both databases.
- Visual Basic 6.0 does not support ImplementationInheritance, so it is easier to call a real database for testing purposes than to call a set of objects that pretend to be a database.
Possible Solution:
- Build 2 relational databases.
- One is the production database, and contains production data.
- The other is the test database. Its contents can be changed arbitrarily, and the users will never need to know.
- The program has 2 modes: testing and production.
- Write a single function, such as TestAll.IsInTestMode(), that returns the mode.
- Optionally, the TestAll.TestAllModules() subroutine sets the mode to test mode at the beginning of the tests, and restores the mode to production mode at the end of the tests.
- Optionally, the program executable can have a /testdb flag that sets the mode to test mode.
- By default, the released program is in production mode.
- All code that calls the database makes its connections based on a ConnectionString.
- There is a single function that returns the ConnectionString. It calls TestAll.IsInTestMode() to choose which ConnectionString to return.
- The only code that hard codes or constructs a ConnectionString is in this function.
- Any code that calls the database must (via program convention) use this function.
- Build the following schema verification code into your test harness:
- Does every (tested) table or query in the production database exist in the test database? And vice versa.
- Does every (tested) field in the production database exist in the test database? And vice versa.
- Does every (tested) field in the production database have the same / close-enough data type in the test database?
- Does every (tested) view in the production database have the same / close-enough SQL code as the corresponding view in the test database? And vice versa.
- When needed, the test harness can delete all data in the test database table(s).
- Small amounts of test data can be replaced using hard-coded queries.
- Large amounts of test data can be loaded from text files. The text files can be (excerpts of) snapshots of the production database.
Resulting Context:
- HighRisk?: Maintenance programmers need to know not to hard-code ConnectionStrings to the production database. If an insert or delete query is made to the production database using a hard-coded ConnectionString, there is a HighRisk? that calling the test code will modify the production database.
- Duplication: Parts of the database schema are stored in three places:
- The production database.
- The TestDatabase.
- The files and hard-codings used to store the test data.
- Repeatable Demo Data: Optionally, the test data can be left in the TestDatabase after the test run is completed. This allows the developers to demo the software, either using the /testdb flag, or in the debugger with the mode set to test mode. At any time, the demo data can be reset to standard values by running the tests.
Discussion:
Is TestDatabase a pattern - or is it an anti-pattern? Time will tell.
This may be a PatternLanguage, not just a single pattern.
' Large amounts of test data can be loaded from text files. The text files can be (excerpts of) snapshots of the production database. '
Or you can generate it even before you have the production to take a snapshot of. For that you need a TestDataGenerator tool.
See also: TestingPatterns, RelationalPatterns, MockObject, MockDatabase
CategoryPattern,
CategoryPatternLanguage
CategoryVisualBasic
CategoryMockObjects