DbUnit Framework

Download Report

Transcript DbUnit Framework

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