dbunit framework joe borosky chris decelles yvonne krashkevich
TRANSCRIPT
DbUnit FrameworkDbUnit FrameworkJoe BoroskyJoe Borosky
Chris DeCellesChris DeCellesYvonne KrashkevichYvonne Krashkevich
DbUnit FrameworkDbUnit Framework
Database Testing with DbUnitDatabase Testing with DbUnit In this presentation, we are going to explain In this presentation, we are going to explain
how to get started with DbUnit.how to get started with DbUnit.
The EnvironmentThe Environment Sample Eclipse project which contains Sample Eclipse project which contains
DbUnit and JUnit.DbUnit and JUnit.
DbUnit FrameworkDbUnit Framework
DbUnit extends the popular JUnit test DbUnit extends the popular JUnit test framework.framework.
JUnitJUnit JUnit is a regression testing framework written JUnit is a regression testing framework written
by Erich Gamma and Kent Beck.by Erich Gamma and Kent Beck. It is used by those who implement unit tests in It is used by those who implement unit tests in
Java.Java. It is open source software.It is open source software. It is an instance of the xUnit architecture for It is an instance of the xUnit architecture for
unit testing frameworks. unit testing frameworks.
DbUnit FrameworkDbUnit Framework
JUnit FeaturesJUnit Features Assertions for testing expected resultsAssertions for testing expected results Text fixtures for sharing common test dataText fixtures for sharing common test data Test suites for easily organizing and running Test suites for easily organizing and running
teststests Graphical and textual test runnersGraphical and textual test runners
DbUnit FrameworkDbUnit Framework
Unit Test FrameworksUnit Test Frameworks Unit Test Frameworks are a key element in eXtreme Unit Test Frameworks are a key element in eXtreme
Programming and Agile Development.Programming and Agile Development. Unit Testing has moved beyond eXtreme ProgrammingUnit Testing has moved beyond eXtreme Programming It is common in many types of application development.It is common in many types of application development. They help ensure low level code correctness, reduce They help ensure low level code correctness, reduce
software development cycle time, improve developer software development cycle time, improve developer
productivity, andproductivity, and produce more robust software.produce more robust software.
DbUnit Best PracticesDbUnit Best Practices
DBUnit Best PracticesDBUnit Best Practices Use one database instance per developerUse one database instance per developer If you setup the tests properly you do not have to cleanup If you setup the tests properly you do not have to cleanup
afterwards.afterwards. Use multiple small datasets instead of using one large Use multiple small datasets instead of using one large
dataset (most tests do not require the entire database to re-dataset (most tests do not require the entire database to re-initialize).initialize).
Perform setup of stale data once for the entire test class or Perform setup of stale data once for the entire test class or test suitetest suite
Connection Management StrategiesConnection Management Strategies Remote Client with Database Test CaseRemote Client with Database Test Case In-container with Cactus or JUnitEEIn-container with Cactus or JUnitEE
DbUnit FrameworkDbUnit Framework Database Testing with DbUnitDatabase Testing with DbUnit
DbUnit is a useful and powerful tool for DbUnit is a useful and powerful tool for simplifying unit testing of database simplifying unit testing of database operations. operations.
It is targeted for Database-driven projects and It is targeted for Database-driven projects and works to put your database into a known state works to put your database into a known state between test runs.between test runs.
With DbUnit, a database can be seeded with With DbUnit, a database can be seeded with a desired data set before a test; moreover, at a desired data set before a test; moreover, at the completion of the test, the database can the completion of the test, the database can be placed back into its pre-test state.be placed back into its pre-test state.
DbUnit FrameworkDbUnit Framework
Database Testing with DbUnitDatabase Testing with DbUnit It is a great tool to use to avoid the problems that It is a great tool to use to avoid the problems that
may occur when one test case corrupts the may occur when one test case corrupts the database and causes subsequent test to fail.database and causes subsequent test to fail.
It can work with very large datasets when used in It can work with very large datasets when used in streaming mode.streaming mode.
It can help verify your data matches an expected It can help verify your data matches an expected set of values.set of values.
DbUnit FrameworkDbUnit Framework
DbUnit Features for Unit Testing Database DbUnit Features for Unit Testing Database OperationsOperations a very simple XML-based mechanism for a very simple XML-based mechanism for loadingloading test test
data data a framework which simplifies operations for each a framework which simplifies operations for each
stage in the stage in the life cyclelife cycle of individual database tests of individual database tests an equally simple mechanism for an equally simple mechanism for exporting existing exporting existing
testtest data into the XML format for subsequent use in data into the XML format for subsequent use in automated tests automated tests
methods for methods for comparing datacomparing data, between flat files, , between flat files, queries and database tablesqueries and database tables
DbUnit FrameworkDbUnit Framework
DbUnit Core ComponentsDbUnit Core Components IDatabaseConnection - interface representing IDatabaseConnection - interface representing
a DbUnit connection to a DBa DbUnit connection to a DB IDataSet - interface representing a collection IDataSet - interface representing a collection
of tablesof tables DatabaseOperation - abstract class DatabaseOperation - abstract class
representing an operation performed on the representing an operation performed on the database before and after each testdatabase before and after each test
DbUnit FrameworkDbUnit Framework
DbUnit IDatabaseConnectionDbUnit IDatabaseConnection DatabaseConnection - wraps a JDBC DatabaseConnection - wraps a JDBC
connectionconnection DatabaseDataSourceConnection - wraps a DatabaseDataSourceConnection - wraps a
JDBC Data SourceJDBC Data Source
DbUnit FrameworkDbUnit Framework
DbUnit IDataSetDbUnit IDataSet This is the primary abstraction used by DbUnit This is the primary abstraction used by DbUnit
to manipulate tabular data.to manipulate tabular data. Commonly used implementationsCommonly used implementations
FlatXmlDataSetFlatXmlDataSet DefaultDataSet DefaultDataSet XmlDataSetXmlDataSet CompositeDataSet CompositeDataSet StreamingDataSetStreamingDataSet FilteredDataSet FilteredDataSet DatabaseDataSetDatabaseDataSet XlsDataSet XlsDataSet QueryDataSetQueryDataSet ReplacementDataSet ReplacementDataSet
DbUnit FrameworkDbUnit Framework
DbUnit DatabaseOperationDbUnit DatabaseOperation Operations (named “DatabaseOperation.”xyz”)Operations (named “DatabaseOperation.”xyz”)
UPDATEUPDATE TRUNCATETRUNCATE INSERTINSERT REFRESHREFRESH DELETEDELETE CLEAN_INSERTCLEAN_INSERT DELETE_ALLDELETE_ALL NONENONE
Other OperationsOther Operations CompositeOperationCompositeOperation TransactionOperationTransactionOperation IdentityInsertOperationIdentityInsertOperation
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case The easiest way to understand how DbUnit is The easiest way to understand how DbUnit is
used is through an example. used is through an example. The first thing to know isThe first thing to know is
Instead of subclassing JUnit's TestCase class directlyInstead of subclassing JUnit's TestCase class directly Subclass DbUnit's DatabaseTestCase, which is itself a Subclass DbUnit's DatabaseTestCase, which is itself a
subclass of TestCase. subclass of TestCase.
DatabaseTestCase is abstract, and requires you to DatabaseTestCase is abstract, and requires you to implement two methods: implement two methods: 1.1. protected IDatabaseConnection getConnection() throws Exceptionprotected IDatabaseConnection getConnection() throws Exception
2.2. protected IDataSet getDataSet() throws Exception.protected IDataSet getDataSet() throws Exception.
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case IDatabaseConnection getConnection() throws Exception. IDatabaseConnection getConnection() throws Exception. The first thing that needed is to specify how to obtain a database The first thing that needed is to specify how to obtain a database
connection. connection.
protected IDatabaseConnection getConnection() throws Exception protected IDatabaseConnection getConnection() throws Exception { {
Class driverClass = Class.forName("com.mysql.jdbc.Driver"); Class driverClass = Class.forName("com.mysql.jdbc.Driver"); Connection jdbcConnection = Connection jdbcConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/FrameworkDriverManager.getConnection("jdbc:mysql://localhost:3306/Framework
Database", "root", “password"); Database", "root", “password"); return new DatabaseConnection(jdbcConnection); return new DatabaseConnection(jdbcConnection);
}}
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case IDataSet getDataSet() throws Exception. IDataSet getDataSet() throws Exception. Here the method returns a data set loaded from an XML file on the Here the method returns a data set loaded from an XML file on the
classpath. classpath.
protected IDataSet getDataSet() throws Exception protected IDataSet getDataSet() throws Exception
{ {
loadedDataSet = new loadedDataSet = new FlatXmlDataSet( this.getClass().getClassLoader().getResourceAsStreFlatXmlDataSet( this.getClass().getClassLoader().getResourceAsStream("input.xml")); return loadedDataSet;am("input.xml")); return loadedDataSet;
} }
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case DbUnit has adopted a very flexible architecture based DbUnit has adopted a very flexible architecture based
on intelligent use of interfaces. IDataSet is one of the on intelligent use of interfaces. IDataSet is one of the key interfaces. The best way to think of IDataSet is key interfaces. The best way to think of IDataSet is that it represents one or more blocks of tabular data. that it represents one or more blocks of tabular data.
This data may be generated from a number of This data may be generated from a number of sources:sources: flat XML files, of which we will see an example very shortly flat XML files, of which we will see an example very shortly tables in the database tables in the database database queries created using SQL database queries created using SQL less obvious sources, such as Microsoft Excel spreadsheetsless obvious sources, such as Microsoft Excel spreadsheets
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case The IDataSet interface is very powerfulThe IDataSet interface is very powerful
First because it defines a common representation First because it defines a common representation which can be used for comparisons between data which can be used for comparisons between data from any of these sourcesfrom any of these sources
Second because it defines methods for reading Second because it defines methods for reading from and writing to its native format. from and writing to its native format.
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case Probably the most widely used mechanism for Probably the most widely used mechanism for
creating a test data set is the flat XML file creating a test data set is the flat XML file format. format.
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<dataset> <dataset>
<MANUFACTURER FIELD_1="1" FIELD_2="IBM" <MANUFACTURER FIELD_1="1" FIELD_2="IBM" FIELD_3="Laptop" FIELD_4="2005-10-08" FIELD_3="Laptop" FIELD_4="2005-10-08" FILED_5="00:00:00"/>FILED_5="00:00:00"/>
<MANUFACTURER FIELD_1="2" FIELD_2="DELL" <MANUFACTURER FIELD_1="2" FIELD_2="DELL" FIELD_3="Desktop" FIELD_4="2005-10-09" FIELD_3="Desktop" FIELD_4="2005-10-09" FILED_5="00:00:00"/>FILED_5="00:00:00"/>
</dataset> </dataset>
DbUnit FrameworkDbUnit Framework
Create a DbUnit Test CaseCreate a DbUnit Test Case The test case contains data from a single table, The test case contains data from a single table, MANUFACTURERMANUFACTURER, with five data columns. , with five data columns.
Our getDataSet() implementation uses the Our getDataSet() implementation uses the FlatXmlDataSet class to load this file.FlatXmlDataSet class to load this file.
The test class is not ready, because we haven't The test class is not ready, because we haven't written any tests yet. Before we can do this, we need written any tests yet. Before we can do this, we need to understand the DbUnit test life cycle. In particular, to understand the DbUnit test life cycle. In particular, we want to know what it does with the IDataSet it has we want to know what it does with the IDataSet it has loaded in the getDataSet() method.loaded in the getDataSet() method.
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle The most typical scenario for running The most typical scenario for running
database tests using DbUnit is as follows:database tests using DbUnit is as follows: remove any old stale data left in the database from remove any old stale data left in the database from
previous tests previous tests load some data from the file system into the load some data from the file system into the
database database run some tests, using DbUnit methods to make run some tests, using DbUnit methods to make
assertionsassertions
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle Both of the first two operations occur during Both of the first two operations occur during
execution of the JUnit setUp() method. Note execution of the JUnit setUp() method. Note that with this scenario, no attempt is made to that with this scenario, no attempt is made to restore database state after running tests. restore database state after running tests. This is the recommended best practice by the This is the recommended best practice by the authors of DbUnit. authors of DbUnit.
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle Cleanup occurs before the test is run, not after. This Cleanup occurs before the test is run, not after. This
approach is more productive when circumstances approach is more productive when circumstances allow it, because you do not need to waste time allow it, because you do not need to waste time writing code to restore state, which can be quite a writing code to restore state, which can be quite a significant task in some situations. significant task in some situations.
The tests may run a little slower, but the idea is that The tests may run a little slower, but the idea is that setup should only load data required for an individual setup should only load data required for an individual test, rather than data required for all tests.test, rather than data required for all tests.
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle Lets take a look at how the setUp() and Lets take a look at how the setUp() and
tearDown() methods are implemented in the tearDown() methods are implemented in the DatabaseTestCase class.DatabaseTestCase class.
DbUnit FrameworkDbUnit Framework
protected void setUp() throws Exception protected void setUp() throws Exception
{ {
super.setUp(); super.setUp();
executeOperation(getSetUpOperation()); executeOperation(getSetUpOperation());
} }
protected void tearDown() throws Exception protected void tearDown() throws Exception
{ {
super.tearDown(); super.tearDown();
executeOperation(getTearDownOperation()); executeOperation(getTearDownOperation());
} }
DbUnit FrameworkDbUnit Framework/** /** * Returns the database operation executed in test setup. * Returns the database operation executed in test setup. */ */ protected DatabaseOperation getSetUpOperation() throws Exception protected DatabaseOperation getSetUpOperation() throws Exception { {
return DatabaseOperation.CLEAN_INSERT; return DatabaseOperation.CLEAN_INSERT; } }
/** /** * Returns the database operation executed in test cleanup. * Returns the database operation executed in test cleanup. */ */ protected DatabaseOperation getTearDownOperation() throws Exceptionprotected DatabaseOperation getTearDownOperation() throws Exception{ {
return DatabaseOperation.NONE; return DatabaseOperation.NONE; } }
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle The setUp() method executes the setup operation, The setUp() method executes the setup operation,
DatabaseOperation.CLEAN_INSERT. DatabaseOperation.CLEAN_INSERT. This operation in fact combines two operations: This operation in fact combines two operations:
DELETE_ALL and INSERT. DELETE_ALL and INSERT. DELETE_ALL removes all data from the database for the DELETE_ALL removes all data from the database for the
tables returned using getDataSet(), then inserts the data tables returned using getDataSet(), then inserts the data loaded using that method. loaded using that method.
This is how the data that we define in our flat XML file is This is how the data that we define in our flat XML file is loaded into the database.loaded into the database.
DbUnit FrameworkDbUnit Framework
The DbUnit Test LifeCycleThe DbUnit Test LifeCycle The operation NONE executed in tearDown(), The operation NONE executed in tearDown(),
does nothing. does nothing. The default setUp() and tearDown() The default setUp() and tearDown()
operations can be overridden if your operations can be overridden if your application requires this. application requires this.
You can even provide your own You can even provide your own implementation of IDatabaseOperation. implementation of IDatabaseOperation.
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests Now that we understand the DbUnit lifecycle Now that we understand the DbUnit lifecycle
and we've set up the necessary infrastructure, and we've set up the necessary infrastructure, we're ready to write some tests. The following we're ready to write some tests. The following tests demonstrate some features of DbUnit, tests demonstrate some features of DbUnit, rather than testing a specific application.rather than testing a specific application.
First Test Example - Demonstrates that the First Test Example - Demonstrates that the setUp() method does indeed load the XML setUp() method does indeed load the XML data into an IDataSet instance, and that this data into an IDataSet instance, and that this data contains the data we expect.data contains the data we expect.
DbUnit FrameworkDbUnit Frameworkprivate FlatXmlDataSet loadedDataSet;private FlatXmlDataSet loadedDataSet;
protected IDataSet getDataSet() throws Exceptionprotected IDataSet getDataSet() throws Exception
{{
loadedDataSet = new loadedDataSet = new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("inFlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("input.xml"));put.xml"));
return loadedDataSet;return loadedDataSet;
}}
public void testCheckDataLoaded() throws Exceptionpublic void testCheckDataLoaded() throws Exception
{{
assertNotNull(loadedDataSet);assertNotNull(loadedDataSet);
int rowCount = loadedDataSet.getTable(TABLE_NAME).getRowCount();int rowCount = loadedDataSet.getTable(TABLE_NAME).getRowCount();
assertEquals(2, rowCount);assertEquals(2, rowCount);
}}
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests Second Test Example - Shows how we can Second Test Example - Shows how we can
create an IDataSet using the create an IDataSet using the IDatabaseConnection for a particular table.IDatabaseConnection for a particular table.
The IDatabaseConnection is created using The IDatabaseConnection is created using the IDatabaseConnection getConnection(). the IDatabaseConnection getConnection().
Notice that this is only using one table, Notice that this is only using one table, although the IDataSet could contain data for although the IDataSet could contain data for multiple tables. multiple tables.
DbUnit FrameworkDbUnit Framework
public void testCompareDataSet() throws Exception public void testCompareDataSet() throws Exception
{ {
IDataSet createdDataSet = getConnection().createDataSet(new String[] IDataSet createdDataSet = getConnection().createDataSet(new String[]
{ {
TABLE_NAME TABLE_NAME
}); });
Assertion.assertEquals(loadedDataSet, createdDataSet); } Assertion.assertEquals(loadedDataSet, createdDataSet); }
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests We mentioned earlier that DbUnit included a We mentioned earlier that DbUnit included a
mechanism for mechanism for comparingcomparing data loaded from data loaded from different sources. You can see this at work in different sources. You can see this at work in this test example: the Assertion.assertEquals() this test example: the Assertion.assertEquals() method compares data obtained from the method compares data obtained from the database with the data loaded from the XML database with the data loaded from the XML file.file.
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests Third Test Example - Takes this idea further. Third Test Example - Takes this idea further.
It shows how we can create an IDataSet It shows how we can create an IDataSet instance using instance using SQL queriesSQL queries, and use this as , and use this as a basis for assertions a basis for assertions
DbUnit FrameworkDbUnit Framework
public void testCompareQuery() throws Exception public void testCompareQuery() throws Exception
{ {
QueryDataSet queryDataSet = new queryDataSet(getConnection()); QueryDataSet queryDataSet = new queryDataSet(getConnection()); queryDataSet.addTable(TABLE_NAME, "SELECT * FROM " + TABLE_NAME); queryDataSet.addTable(TABLE_NAME, "SELECT * FROM " + TABLE_NAME); Assertion.assertEquals(loadedDataSet, queryDataSet);Assertion.assertEquals(loadedDataSet, queryDataSet);
} }
DbUnit FrameworkDbUnit Framework
This is very powerful because it means This is very powerful because it means you can create data sets which represent you can create data sets which represent arbitrary queries, and not simply tables in arbitrary queries, and not simply tables in the database.the database.
Many of the DbUnit test that will be written Many of the DbUnit test that will be written in real application are likely to use this in real application are likely to use this mechanism.mechanism.
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests Final Test Example - Shows how to Final Test Example - Shows how to exportexport a a
data set, either from an existing database data set, either from an existing database table or from a query, into a flat XML file.table or from a query, into a flat XML file.
The FlatXmlDataSet.write() method is used to The FlatXmlDataSet.write() method is used to write the data set to the file output.xml in the write the data set to the file output.xml in the DbUnit XML format.DbUnit XML format.
DbUnit FrameworkDbUnit Framework
public void testExportData() throws Exception public void testExportData() throws Exception { {
IDataSet dataSet = getConnection().createDataSet(new String[] IDataSet dataSet = getConnection().createDataSet(new String[] { {
TABLE_NAME TABLE_NAME }); }); URL url = DatabaseTestCase.class.getResource("/input.xml"); URL url = DatabaseTestCase.class.getResource("/input.xml"); assertNotNull(url); assertNotNull(url); File inputFile = new File(url.getPath()); File inputFile = new File(url.getPath()); File outputFile = new File(inputFile.getParent(), "output.xml"); File outputFile = new File(inputFile.getParent(), "output.xml"); FlatXmlDataSet.write(dataSet, new FileOutputStream(outputFile)); FlatXmlDataSet.write(dataSet, new FileOutputStream(outputFile));
assertEquals(FileUtils.readFileToString(inputFile, "UTF8"), assertEquals(FileUtils.readFileToString(inputFile, "UTF8"), FileUtils.readFileToString(outputFile, "UTF8")); } FileUtils.readFileToString(outputFile, "UTF8")); }
DbUnit FrameworkDbUnit Framework
Writing TestsWriting Tests Our test also asserts that the contents of the Our test also asserts that the contents of the
outputted XML file are identical to the outputted XML file are identical to the input.xml from which the IDataSet was input.xml from which the IDataSet was originally loaded. originally loaded.
DbUnit FrameworkDbUnit Framework
SummarySummary DbUnit is a powerful, simple to use tool for enabling DbUnit is a powerful, simple to use tool for enabling
test driven development of database applications. test driven development of database applications. It is well designed around flexible Java interfaces, It is well designed around flexible Java interfaces,
which make it easy to adapt or extend to application which make it easy to adapt or extend to application requirements. requirements.
It is simple to include DbUnit as a part of your It is simple to include DbUnit as a part of your database application development process and take database application development process and take advantage of its powerful, timesaving features. advantage of its powerful, timesaving features.
DbUnit FrameworkDbUnit Framework
SummarySummary The DbUnit framework's ability to manage the state of The DbUnit framework's ability to manage the state of
a database throughout a test's lifecycle enables rapid a database throughout a test's lifecycle enables rapid test-case creation and adoption; furthermore, by test-case creation and adoption; furthermore, by controlling a major dependency, tests that utilize the controlling a major dependency, tests that utilize the DbUnit framework are easily automated. DbUnit framework are easily automated.
DbUnit's elegant design makes learning how to DbUnit's elegant design makes learning how to properly utilize its features a breeze. Once it's in place properly utilize its features a breeze. Once it's in place as a part of an effective testing strategy, overall code as a part of an effective testing strategy, overall code stability will increase dramatically, along with the stability will increase dramatically, along with the collective confidence of your development team.collective confidence of your development team.
DbUnit FrameworkDbUnit Framework
QUESTIONS?QUESTIONS?
DbUnit FrameworkDbUnit Framework
Sources:Sources:
http://www.realsolve.co.uk/site/tech/dbunit-quickstart.phphttp://www.realsolve.co.uk/site/tech/dbunit-quickstart.php http://www.onjava.com/pub/a/onjava/2004/01/21/dbunit.htmlhttp://www.onjava.com/pub/a/onjava/2004/01/21/dbunit.html http://http://dbunit.sourceforge.netdbunit.sourceforge.net// http://http://www.dbunit.org/apidocs/index.htmlwww.dbunit.org/apidocs/index.html http://http://www.eclipse.orgwww.eclipse.org// http://perl.about.com/od/installandconfiguremysql/l/aa112400b.htmhttp://perl.about.com/od/installandconfiguremysql/l/aa112400b.htm http://dev.mysql.com/doc/mysql/en/create-database.htmlhttp://dev.mysql.com/doc/mysql/en/create-database.html