So I’m back from the Percona dev team’s recent meeting. While there, we spent a fair bit of time discussing Xtrabackup development. One of our challenges is that as we add richer features to the tool, we need equivalent testing capabilities. However, it seems a constant in the MySQL world that available QA tools often leave something to be desired. The randgen is a literal wonder-tool for database testing, but it is also occasionally frustrating / doesn’t scratch every testing itch. It is based on technology SQL Server was using in 1998 (MySQL began using it in ~2007, IIRC). So this is no knock, it is merely meant to be an example of a poor QA engineer’s frustrations ; ) While the current Xtrabackup test suite is commendable, it also has its limitations. Enter the flexible, adaptable, and expressive answer: dbqp.
One of my demos at the dev meeting was showing how we can set up tests for Xtrabackup using the unittest paradigm. While this sounds fancy, basically, we take advantage of Python’s unittest and write classes that use their code. The biggest bit dbqp does is search the specified server code (to make sure we have everything we should), allocate and manage servers as requested by the test cases, and do some reporting and management of the test cases. As the tool matures, I will be striving to let more of the work be done by unittest code rather than things I have written : )
To return to my main point, we now have two basic tests of xtrabackup:
Basic test of backup + restore:
- Populate server
- Take a validation snapshot (mysqldump)
- Take the backup (via innobackupex)
- Clean datadir
- Restore from backup
- Take restored state snapshot and compare to original state
- Similar to our basic test except we create a slave from the backup, replicating from the backed up server.
- After the initial setup, we ensure replication is set up ok, then we do additional work on the master and compare master and slave states
One of the great things about this is that we have the magic of assertions. We can insert them at any point of the test we feel like validating and the test will fail with useful output at that stage. The backup didn’t take correctly? No point going through any other steps — FAIL! : ) The assertion methods just make it easy to express what behavior we are looking for. We want the innobackupex prepare call to run without error?
Boom goes the dynamite!:
# prepare our backup
cmd = ("%s --apply-log --no-timestamp --use-memory=500M "
"--ibbackup=%s %s" %( innobackupex
retcode, output = execute_cmd(cmd, output_path, exec_path, True)
self.assertEqual(retcode, 0, msg = output)
From these basic tests, it will be easy to craft more complex test cases. Creating the slave test was simply matter of adapting the initial basic test case slightly. Our plans include: *heavy* crash testing of both xtrabackup and the server, enhancing / expanding replication tests by creating heavy randgen loads against the master during backup and slave setup, and other assorted crimes against database software. We will also be porting the existing test suite to use dbqp entirely…who knows, we may even start working on Windows one day ; )
These tests are by no means the be-all-end-all, but I think they do represent an interesting step forward. We can now write actual, honest-to-goodness Python code to test the server. On top of that, we can make use of the included unittest module to give us all sorts of assertive goodness to express what we are looking for. We will need to and plan to refine things as time moves forward, but at the moment, we are able to do some cool testing tricks that weren’t easily do-able before.
If you’d like to try these tests out, you will need the following:
* dbqp (bzr branch lp:dbqp)
* DBD:mysql installed (test tests use the randgen and this is required…hey, it is a WONDER-tool!) : )
* Innobackupex, a MySQL / Percona server and the appropriate xtrabackup binary.
The tests live in dbqp/percona_tests/xtrabackup_basic and are named basic_test.py and slave_test.py, respectively.
To run them:
$./dbqp.py –suite=xtrabackup_basic –basedir=/path/to/mysql –xtrabackup-path=/mah/path –innobackupex-path=/mah/other/path –default-server-type=mysql –no-shm
Some next steps for dbqp include:
1) Improved docs
2) Merging into the Percona Server trees
3) Setting up test jobs in Jenkins (crashme / sqlbench / randgen)
4) Other assorted awesomeness
Naturally, this testing goodness will also find its way into Drizzle (which currently has a 7.1 beta out). We definitely need to see some Xtrabackup test cases for Drizzle’s version of the tool (mwa ha ha!) >: )