In the previous post I briefly mentioned the new feature of the PackageLoader that went into the development version of GNU Smalltalk. Today I am going show a usage of it.
GNU Smalltalk has a database abstraction called DBI and multiple backends (MySQL, SQLite and PostgreSQL). In general I am using the SQLite backend to develop my application and depending on the users (e.g. do I need concurrent access) I will move to PostgreSQL. When moving my new application to PostgreSQL the import of data failed and this was due some issues with the conversion of Smalltalk types to PostgreSQL.
After some exploring to understand the issue I started to develop a unit test. The first thing I did was to create a test entry in the package description of DBD-PostgreSQL, fileIn a file and name a SUnit TestCase or TestSuite.
<test> <sunit>DBI.PostgreSQL.PostgresTestCase<sunit> <filein>Tests.st</filein> </test>
The next thing is to start GNU Smalltalk and load the package and get the test. I cheated a bit and directly constructed a Kernel.DirPackage instance.
st> package := Kernel.DirPackage file: 'package.xml'
st> package fileIn.
st> test := package test.
st> test fileIn.
The above code has loaded the main package (and dependencies) and the test package as well. I went ahead and manually invoked the tests I have. This can be done by sending the >>#buildSuite message to my TestCase and then calling run on the result.
st> DBI.PostgreSQL.PostgresTestCase buildSuite run
0 run, 0 passes
Now I can start to write the actual testcases. I decided to write one test per datatype. I created a >>#setUp selector that opens the database connection and creates a table that contains every built-in type of PostgreSQL as column and a >>#tearDown to close the database connection. Then I decided to write one test per datatype and started with the ones I knew that were broken. I could incrementally create tests and type the following commands to execute them.
st> test fileIn. DBI.PostgreSQL.PostgresTestCase buildSuite run
As expected my first tests were failing. I decided to use the open classes feature of Smalltalk and put the fixes to the tests into the Tests.st file and re-executed the above and my test started to pass, then I wrote another test, executed the suite, created a fix, re-loaded and ran the tests. This has worked nicely but then there was a fix that manipulated a lookup table owned by a singleton. This means that my changes to the code were not picked up as the instance was already initialized. There are multiple ways to overcome this. I could have called the initialize function of the singleton again, I could have manipulated the lookup table inside the singleton or I could have re-set the singleton. I decided to do the later using the reflection facilities of Smalltalk. I put a nil into the instanceVariable called uniqueInstance of the PGFieldConverter class.
st> DBI.PostgreSQL.PGFieldConverter instVarNamed: #uniqueInstance put: nil
After re-executing the testsuite the singleton was re-created and the next testcase was fixed. The only thing left to do was to move the fixes from the Tests.st to the right place in the original files and run make check on the entire codebase to check that everything works as expected.