JUnit 是一个简单易用的单元测试框架。随着敏捷开发和TDD的风行,它的重要性也日益显现。
介绍:
1、Test接口包含实现类TestSuite和实现抽象类TestCase,同时TestSuite拥有对Test的集合引用(Composite模式)。如图所示:
2、包含两类测试:TestCase和TestSuite。TestCase一个测试用例,而多个测试用例可以组合成一个TestSuite测试套件。
3、TestCase在实现Test接口的同时也实现了Assert断言接口,Assert这个接口中提供了许多方便断言判断的静态方法,如Assert.assertEquals(), Assert.assertNotNull(), Assert.assertTrue()等,这些在我们的测试用例都可以方便应用。
4、TestCase提供了setUp()和tearDown()方法。setUp()在测试用例执行之前调用,tearDown()在测试用例执行之后调用,TestCase中默认空实现,我们可以在setUp()中执行一些例如打开文件,建立数据库连接的操作,而在tearDown()中执行一些相应的如关闭文件,关闭数据库连接的操作。
使用:
1、编写我们自己的测试用例,需要继承TestCase,我们需要运行的测试方法必须以test开头。
2、为了实现自动化测试,我们可能需要同时运行多个测试用例,这时候我们可以借助TestSuite来实现,有两种方式:
a. 继承自TestSuite,举例如下:
public class AllImportsTests extends TestSuite {
public static Test suite () {
TestSuite suite = new TestSuite ("Test for pet.test");
suite.addTestSuite (ImportATest.class );
suite.addTestSuite (ImportBTest.class );
return suite;
}
}
b. 继承自TestCase,举例如下:
public class AllGetListTests extends TestCase {
public static Test suite () {
TestSuite suite = new TestSuite ("Test for pet.test");
suite.addTestSuite (NewATest.class );
suite.addTestSuite (NewBTest.class );
return suite;
}
public void testAllGetList(){
TestRunner .run (suite ());
}
}
衍生:
通过JUnit衍生了用于性能测试的JUnitPerf ,用于数据库隔离测试的DBUnit 等。
1、JUnitPerf:
JUnitPerf 提供了两个测试基类,LoadTest 和TimedTest, 这两种类型都基于 Decorator 设计模式并利用 JUnit 的 suite
机制。LoadTest 和计时器一起运行,它通过运行所需的次数(时间间隔由配置的计时器控制),在一个特定的测试用例上创建一个人工负载。TimedTest
为测试样例创建一个(时间)上限 —— 如果超过这个时间,那么测试失败。
LoadTest的用法:
//自定义测试类
public class MyTest extends TestCase {
Logger log = Logger.getLogger(MyTest.class );
public MyTest(String name){
super(name);
}
public void testCircle () throws java.lang.Exception{
int len = 1000;
for(int i = 0; i < len; i++){
log.info("Number: " + i);
}
Assert.assertTrue(true);
}
}
int userCount = 10; //并发访问数
int delaySeconds = 100; //延迟时间,单位毫秒
int repeatCount = 10; //重复次数
Test myTestCase = new MyTest("testCircle");
1. 并发测试
Test normalTest = new LoadTest(myTestCase, userCount);
2. 延时测试
Timer timer = new ConstantTimer(delaySeconds);
//double seed = 0.001;
//Timer timer = new RandomTimer(delaySeconds, seed);
Test delayTest = new LoadTest(myTestCase, timer);
3. 重复测试
Timer timer = new ConstantTimer(delaySeconds);
Test decorTestCase = new RepeatedTest(myTestCase, repeatCount);
Test repeatTest = new LoadTest(decorTestCase, userCount, timer);
4. 本地线程测试 (?)
Test factory1 = new TestFactory(MyTestCase.class);
Test localTest1 = new LoadTest(factory1, userCount);
Test factory2 = new TestMethodFactory(MyTest.class, "testCircle");
Test loadTest2 = new LoadTest(factory2, userCount);
TimedTest的用法:
long timeElapsed = 2000;
//不论是否超时都会运行完程序,是否失败由运行时间决定。
Test timedTest = new TimedTest(testCase, timeElapsed);
//不等待方法完成,如果超时就测试失败退出程序。
Test timedTest = new TimedTest(testCase, timeElapsed, false);
代码示例:
/**
* 时限测试
* @author xiaowei
*
*/
public class MyTimedTest {
public static Test suite(){
long timeElapsed = 2000;
Test testCase = new MyTest("testCircle");
/**
* 创建一个计时测试,它等待MyTest.testCircle方法完成之后
* 如果耗时超过2秒就测试失败
* create a timed test that waits for the completion of the
* MyTest.testCircle method and
* then fails if the elapsed time exceeded 2 second
*/
Test timedTest = new TimedTest(testCase, timeElapsed);
/**
* 创建一个计时测试,它当MyTest.testCircle方法执行时计算
* 如果已经耗时超过2秒就立即结束,测试失败
* create a timed test that fails immediately when the elapsed time
* of the MyTest.testCircle test method exceeds 2 second
* Test timedTest = new TimedTest(testCase, timeElapsed, false);
*/
return timedTest;
}
public static void main(String[] args){
TestRunner.run(MyTimedTest.suite());
}
}
/**
* 负载测试
* @author xiaowei
*
*/
public class MyLoadTest {
public static Test normalSuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法,
* 并且所有用户都是同时开始
* create a load test of 10 concurrent users with each user
* running the MyTest.testCircle method once
* and all users starting simultaneously
*/
int users = 10;
Test testCase = new MyTest("testCircle");
Test loadTest = new LoadTest(testCase, users);
return loadTest;
}
public static Test delaySuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法,
* 并且这些用户访问间隔为0.1秒
* create a load test of 10 concurrent users with each user
* running the MyTest.testCircle method once
* and with a 0.1 second delay between the addition of users
*/
int users = 10;
int delay = 100;
Timer timer = new ConstantTimer(delay);
// double seed = 0.001;
// Timer randomTimer = new RandomTimer(delay, seed);
Test testCase = new MyTest("testCircle");
Test loadTest = new LoadTest(testCase, users, timer);
return loadTest;
}
public static Test repeatedSuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法10次
* create a load test of 10 concurrent users with each user running
* the MyTest.testCircle method for 20 iterations
*/
int users = 10;
int iterations = 5;
Timer timer = new ConstantTimer(10);
Test testCase = new MyTest("testCircle");
Test repeatedTest = new RepeatedTest(testCase, iterations);
Test loadTest = new LoadTest(repeatedTest, users, timer);
return loadTest;
}
public static Test threadLocalSuite(int which){
/**
* If a test case intended to be decorated as a LoadTest contains
* test-specific state in the setUp() method, then the TestFactory
* should be used to ensure that each concurrent user thread
* uses a thread-local instance of the test. For example,
* to create a load test of 10 concurrent users with each user
* running a thread-local instance of MyTest
*/
int users = 10;
Test factory = new TestFactory(MyTest.class);
Test loadTest = new LoadTest(factory, users);
/**
* or, to load test a single test method
*/
Test factory2 = new TestMethodFactory(MyTest.class, "testCircle");
Test loadTest2 = new LoadTest(factory2, users);
if(which == 1){
return loadTest;
}else{
return loadTest2;
}
}
public static void main(String[] args){
TestRunner.run(MyLoadTest.normalSuite());
System.out.println();
TestRunner.run(MyLoadTest.delaySuite());
System.out.println();
TestRunner.run(MyLoadTest.repeatedSuite());
System.out.println();
TestRunner.run(MyLoadTest.threadLocalSuite(1));
System.out.println();
TestRunner.run(MyLoadTest.threadLocalSuite(2));
}
}
2、DBUnit:
DBUnit 扩展自JUnit,它的用途是为了保证涉及数据库操作的测试进行之前数据库处于一种以至状态。
DBUnit提供了几个实用的操作接口:
IDatabaseConnection 代表DBUnit到数据库的一个连接。
IDataSet 代表一个数据表的集合,它可能来源一个数据库表,XML文件或者Excel文件。它的实现很多,最常用的有FlatXmlDataSet、XmlDataSet、QueryDataSet、DatabaseDataSet等。
DatabaseOperation 代表对于数据集的一项操作,可选值包括:
DatabaseOperation.UPDATE :这个操作假定表数据已经存在于目标数据库,否则失败。
DatabaseOperation.INSERT :这个操作假定表数据不存在于目标数据库,否则失败。涉及外键操作时,注意数据集中必须按照适当的顺序排列。
DatabaseOperation.DELETE :这个操作删除表数据,只是删除存在于数据集中的数据而非表中的所有数据。
DatabaseOperation.DELETE_ALL :这个操作删除所有表数据。
DatabaseOperation.TRUNCATE :这个操作等同于DatabaseOperation.DELETE_ALL,但它不记录日志,操作更快,无法实现回滚,而且有些数据库不支持。
DatabaseOperation.REFRESH :这个操作强制提交数据集到目标数据库。
DatabaseOperation.CLEAN_INSERT :这个操作结合了DELETE_ALL和INSERT操作,为了实现测试前的数据集处于一个已知的状态。
使用:
1、创建数据集,可以从数据库、XML文件和Excel等途径创建IDataSet;
2、继承DatabaseTestCase,实现它的getConnection()和getDataSet()方法,分别用于获取数据库连接和数据集。例如:
public class BaseDBUnitTestCase extends DatabaseTestCase {
@Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSet("employee.xml");
}
@Override
protected IDatabaseConnection getConnection() throws Exception {
IDatabaseTester databaseTester = new JdbcDatabaseTester(
"com.mysql.jdbc.Driver",
"jdbc:mysql://127.0.0.1/mydb",
"root",
"root");
return databaseTester.getConnection();
}
}
3、(可选)实现getSetUpOperation()和getTearDownOperation()方法
例如:
protected DatabaseOperation getSetUpOperation() throws Exception
{
return DatabaseOperation.REFRESH;
}
protected DatabaseOperation getTearDownOperation() throws Exception
{
return DatabaseOperation.NONE;
}
4、添加测试方法。
5、利用DBUnit提供的断言判断数据集和数据表是否相同,Assert提供了两个静态断言方法。public class Assertion
{ public static void assertEquals
(ITable expected, ITable actual) public static void assertEquals
(IDataSet expected, IDataSet actual)}
例如:// Fetch database data after executing your codeIDataSet databaseDataSet = getConnection().createDataSet();ITable actualTable = databaseDataSet.getTable("TABLE_NAME");// Load expected data from an XML datasetIDataSet expectedDataSet = new FlatXmlDataSet(new File("expectedDataSet.xml"));ITable expectedTable = expectedDataSet.getTable("TABLE_NAME");// Assert actual database table match expected tableAssertion.assertEquals(expectedTable, actualTable);
DBUnit补充
:
1、使用查询获取数据库快照:
ITable actualJoinData = getConnection().createQueryTable("RESULT_NAME",
"SELECT * FROM TABLE1, TABLE2 WHERE ...");
2、对比时忽略某些列:
DefaultColumnFilter columnFilter = new DefaultColumnFilter();
columnFilter.excludeColumn("PK*");
columnFilter.excludeColumn("*TIME");
FilteredTableMetaData metaData = new FilteredTableMetaData(
originalTable.getTableMetaData(), columnFilter);
3、行排序:
默认情况下DBUnit对于数据库表会按照主键进行排序。如果缺少主键或者由数据库产生,并且行排序没有指定,
assertEquals就会失败。又必须手动在使用IDatabaseConnection.createQueryTableshi指定order by子句,
或者使用下面的方式:
Assertion.assertEquals(new SortedTable(expected),
new SortedTable(actual, expected.getTableMetaData()));
其他测试框架:
TestNG:
TestNG 是跟JUnit并列的另外一个测试框架,它偏向于高级应用,以JDK5的注解为主要编程手段。尽管JUnit4中也提供了类似的注解语法,但是TestNG仍然具有许多JUnit不具有的高级特性。
1、更多灵活性。 TestNG比JUnit4具有更多的灵活性,JUnit4中由@BeforeClass标记的方法必须是static的,当然其中引用的变量也必须是static类型的。
2、依赖性测试。 在TestNG中通过使用 Test
注释的 dependsOnMethods =
{"dependMethodName"}可以实现依赖性测试,即被依赖的方法测试失败后,这个方法就会被跳过。
3、失败和重运行。
在JUnit4中,如果测试套件包括1000项测试,其中3项失败,很可能就会迫使您重新运行整个测试套件(修改错误以后)。一旦
TestNG 中出现失败,它就会创建一个XML配置文件,对失败的测试加以说明。如果利用这个文件执行 TestNG 运行程序,TestNG
就只运行失败的测试。所以,在前面的例子里,您只需重新运行那三个失败的测试,而不是整个测试套件。
4、参数化测试。 TestNG可以为测试方法指定参数,并且支持高级参数特性(由Test注解的dataProvider指定),而JUnit4不行。
5、定义测试组。 TestNG 可以定义测试组的能力。每个测试方法都可以与一个或多个组相关联,但可以选择只运行某个测试组。要把测试加入测试组,只要把组指定为 @Test
标注的groups参数。
6、更简单的异常检测。 使用 TestNG 的 @ExpectedExceptions
标注可以使代码编写惊人地容易和简单。
Junit4和TestNG的比较见这里:http://www.ibm.com/developerworks/cn/java/j-cq08296/
TestNG如何使单元测试轻而易举见这里:http://www.ibm.com/developerworks/cn/java/j-testng/
Selenium:
Selenium 是 ThoughtWorks 专门为 Web 应用程序编写的一个验收测试工具。据 Selenium 主页所说,与其他测试工具相比,使用 Selenium 的最大好处是:
Selenium 测试直接在浏览器中运行,就像真实用户所做的一样。Selenium 测试可以在 Windows、Linux 和 MacintoshAnd 上的 Internet Explorer、Mozilla 和 Firefox 中运行。其他测试工具都不能覆盖如此多的平台。
使用 Selenium 和在浏览器中运行测试还有很多其他好处。下面是主要的两大好处:
通过编写模仿用户操作的 Selenium 测试脚本,可以从终端用户的角度来测试应用程序。
通过在不同浏览器中运行测试,更容易发现浏览器的不兼容性。
Selenium包括两种模式:TestRunner和Driven。
TestRunner的测试脚本是用 HTML 语言通过一个简单的表布局编写的,包括命令(断言)、目标和值三部分。其中断言通常使用的是组件的 ID 或名称,但 XPath 和 DOM 定位符也是受支持的。
例如:
<table> <tr> <td>open</td> <td>/change_address_form.html</td> <td></td> </tr> <tr> <td>type</td> <td>address_field</td> <td>Betelgeuse state prison</td> </tr> <tr> <td>clickAndWait</td> <td>//input[@name='Submit']</td> <td></td> </tr> <tr> <td>verifyTextPresent</td> <td>Address change successful</td> <td></td> </tr> </table>
测试套件要达到对应用程序的完全测试覆盖,通常需要不止一个测试用例。这就是 Selenium 使用测试套件的原因。测试套件用于将具有类似功能的一些测试用例编成一组,以便让它们按顺序运行。
测试套件和测试用例一样,都是用简单的 HTML 表编写的。Selenium 执行的缺省测试套件的名称是 TestSuite.html。下面的例子展示了一个测试套件,该套件像通常的用户一样测试应用程序。
注意,测试套件使用一个只包含一列的表,表中的每一行指向一个包含某个测试用例的文件。
例如:
<table>
<tr>
<td>Test suite for the whole application</td>
</tr>
<tr>
<td><a href="test_main_page.html">Access _fcksavedurl="test_main_page.html">Access main page</a></td>
</tr>
<tr>
<td><a href="test_login.html">Login to application</a></td>
</tr>
<tr>
<td><a href="test_address_change.html">Change address</a></td>
</tr>
<tr>
<td><a href="test_logout.html">Logout from application</a></td>
</tr>
</table>
Driven Selenium 脚本是用多种受支持的编程语言中的一种编写的 —— 目前可用的有 Java、Ruby 和 Python 驱动程序。这些脚本在浏览器之外的一个单独的进程中运行。驱动程序的任务是执行测试脚本,并通过与运行在浏览器中的 browser bot 进行通信来驱动浏览器。驱动程序与 browser bot 之间的通信使用一种简单的特定于 Selenium 的连接语言 Selenese。driven 脚本比 test runner 脚本更强大、更灵活,可以将它们与 xUnit 框架集成。driven 脚本的缺点(与 test runner 脚本相比)是,这种脚本编写和部署起来更复杂。这是因为驱动程序必须执行以下任务:启动服务器。
部署所测试的应用程序(AUT)。
部署测试脚本。
启动浏览器。
发送命令到 browser bot。
验证 browser bot 执行的命令的结果。
参考见这里:http://www.ibm.com/developerworks/cn/java/wa-selenium-ajax/
介绍:
1、Test接口包含实现类TestSuite和实现抽象类TestCase,同时TestSuite拥有对Test的集合引用(Composite模式)。如图所示:
2、包含两类测试:TestCase和TestSuite。TestCase一个测试用例,而多个测试用例可以组合成一个TestSuite测试套件。
3、TestCase在实现Test接口的同时也实现了Assert断言接口,Assert这个接口中提供了许多方便断言判断的静态方法,如Assert.assertEquals(), Assert.assertNotNull(), Assert.assertTrue()等,这些在我们的测试用例都可以方便应用。
4、TestCase提供了setUp()和tearDown()方法。setUp()在测试用例执行之前调用,tearDown()在测试用例执行之后调用,TestCase中默认空实现,我们可以在setUp()中执行一些例如打开文件,建立数据库连接的操作,而在tearDown()中执行一些相应的如关闭文件,关闭数据库连接的操作。
使用:
1、编写我们自己的测试用例,需要继承TestCase,我们需要运行的测试方法必须以test开头。
2、为了实现自动化测试,我们可能需要同时运行多个测试用例,这时候我们可以借助TestSuite来实现,有两种方式:
a. 继承自TestSuite,举例如下:
public class AllImportsTests extends TestSuite {
public static Test suite () {
TestSuite suite = new TestSuite ("Test for pet.test");
suite.addTestSuite (ImportATest.class );
suite.addTestSuite (ImportBTest.class );
return suite;
}
}
b. 继承自TestCase,举例如下:
public class AllGetListTests extends TestCase {
public static Test suite () {
TestSuite suite = new TestSuite ("Test for pet.test");
suite.addTestSuite (NewATest.class );
suite.addTestSuite (NewBTest.class );
return suite;
}
public void testAllGetList(){
TestRunner .run (suite ());
}
}
衍生:
通过JUnit衍生了用于性能测试的JUnitPerf ,用于数据库隔离测试的DBUnit 等。
1、JUnitPerf:
JUnitPerf 提供了两个测试基类,LoadTest 和TimedTest, 这两种类型都基于 Decorator 设计模式并利用 JUnit 的 suite
机制。LoadTest 和计时器一起运行,它通过运行所需的次数(时间间隔由配置的计时器控制),在一个特定的测试用例上创建一个人工负载。TimedTest
为测试样例创建一个(时间)上限 —— 如果超过这个时间,那么测试失败。
LoadTest的用法:
//自定义测试类
public class MyTest extends TestCase {
Logger log = Logger.getLogger(MyTest.class );
public MyTest(String name){
super(name);
}
public void testCircle () throws java.lang.Exception{
int len = 1000;
for(int i = 0; i < len; i++){
log.info("Number: " + i);
}
Assert.assertTrue(true);
}
}
int userCount = 10; //并发访问数
int delaySeconds = 100; //延迟时间,单位毫秒
int repeatCount = 10; //重复次数
Test myTestCase = new MyTest("testCircle");
1. 并发测试
Test normalTest = new LoadTest(myTestCase, userCount);
2. 延时测试
Timer timer = new ConstantTimer(delaySeconds);
//double seed = 0.001;
//Timer timer = new RandomTimer(delaySeconds, seed);
Test delayTest = new LoadTest(myTestCase, timer);
3. 重复测试
Timer timer = new ConstantTimer(delaySeconds);
Test decorTestCase = new RepeatedTest(myTestCase, repeatCount);
Test repeatTest = new LoadTest(decorTestCase, userCount, timer);
4. 本地线程测试 (?)
Test factory1 = new TestFactory(MyTestCase.class);
Test localTest1 = new LoadTest(factory1, userCount);
Test factory2 = new TestMethodFactory(MyTest.class, "testCircle");
Test loadTest2 = new LoadTest(factory2, userCount);
TimedTest的用法:
long timeElapsed = 2000;
//不论是否超时都会运行完程序,是否失败由运行时间决定。
Test timedTest = new TimedTest(testCase, timeElapsed);
//不等待方法完成,如果超时就测试失败退出程序。
Test timedTest = new TimedTest(testCase, timeElapsed, false);
代码示例:
/**
* 时限测试
* @author xiaowei
*
*/
public class MyTimedTest {
public static Test suite(){
long timeElapsed = 2000;
Test testCase = new MyTest("testCircle");
/**
* 创建一个计时测试,它等待MyTest.testCircle方法完成之后
* 如果耗时超过2秒就测试失败
* create a timed test that waits for the completion of the
* MyTest.testCircle method and
* then fails if the elapsed time exceeded 2 second
*/
Test timedTest = new TimedTest(testCase, timeElapsed);
/**
* 创建一个计时测试,它当MyTest.testCircle方法执行时计算
* 如果已经耗时超过2秒就立即结束,测试失败
* create a timed test that fails immediately when the elapsed time
* of the MyTest.testCircle test method exceeds 2 second
* Test timedTest = new TimedTest(testCase, timeElapsed, false);
*/
return timedTest;
}
public static void main(String[] args){
TestRunner.run(MyTimedTest.suite());
}
}
/**
* 负载测试
* @author xiaowei
*
*/
public class MyLoadTest {
public static Test normalSuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法,
* 并且所有用户都是同时开始
* create a load test of 10 concurrent users with each user
* running the MyTest.testCircle method once
* and all users starting simultaneously
*/
int users = 10;
Test testCase = new MyTest("testCircle");
Test loadTest = new LoadTest(testCase, users);
return loadTest;
}
public static Test delaySuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法,
* 并且这些用户访问间隔为0.1秒
* create a load test of 10 concurrent users with each user
* running the MyTest.testCircle method once
* and with a 0.1 second delay between the addition of users
*/
int users = 10;
int delay = 100;
Timer timer = new ConstantTimer(delay);
// double seed = 0.001;
// Timer randomTimer = new RandomTimer(delay, seed);
Test testCase = new MyTest("testCircle");
Test loadTest = new LoadTest(testCase, users, timer);
return loadTest;
}
public static Test repeatedSuite(){
/**
* 创建一个装载测试,它利用10个并发用户分别访问MyTest.testCircle方法10次
* create a load test of 10 concurrent users with each user running
* the MyTest.testCircle method for 20 iterations
*/
int users = 10;
int iterations = 5;
Timer timer = new ConstantTimer(10);
Test testCase = new MyTest("testCircle");
Test repeatedTest = new RepeatedTest(testCase, iterations);
Test loadTest = new LoadTest(repeatedTest, users, timer);
return loadTest;
}
public static Test threadLocalSuite(int which){
/**
* If a test case intended to be decorated as a LoadTest contains
* test-specific state in the setUp() method, then the TestFactory
* should be used to ensure that each concurrent user thread
* uses a thread-local instance of the test. For example,
* to create a load test of 10 concurrent users with each user
* running a thread-local instance of MyTest
*/
int users = 10;
Test factory = new TestFactory(MyTest.class);
Test loadTest = new LoadTest(factory, users);
/**
* or, to load test a single test method
*/
Test factory2 = new TestMethodFactory(MyTest.class, "testCircle");
Test loadTest2 = new LoadTest(factory2, users);
if(which == 1){
return loadTest;
}else{
return loadTest2;
}
}
public static void main(String[] args){
TestRunner.run(MyLoadTest.normalSuite());
System.out.println();
TestRunner.run(MyLoadTest.delaySuite());
System.out.println();
TestRunner.run(MyLoadTest.repeatedSuite());
System.out.println();
TestRunner.run(MyLoadTest.threadLocalSuite(1));
System.out.println();
TestRunner.run(MyLoadTest.threadLocalSuite(2));
}
}
2、DBUnit:
DBUnit 扩展自JUnit,它的用途是为了保证涉及数据库操作的测试进行之前数据库处于一种以至状态。
DBUnit提供了几个实用的操作接口:
IDatabaseConnection 代表DBUnit到数据库的一个连接。
IDataSet 代表一个数据表的集合,它可能来源一个数据库表,XML文件或者Excel文件。它的实现很多,最常用的有FlatXmlDataSet、XmlDataSet、QueryDataSet、DatabaseDataSet等。
DatabaseOperation 代表对于数据集的一项操作,可选值包括:
DatabaseOperation.UPDATE :这个操作假定表数据已经存在于目标数据库,否则失败。
DatabaseOperation.INSERT :这个操作假定表数据不存在于目标数据库,否则失败。涉及外键操作时,注意数据集中必须按照适当的顺序排列。
DatabaseOperation.DELETE :这个操作删除表数据,只是删除存在于数据集中的数据而非表中的所有数据。
DatabaseOperation.DELETE_ALL :这个操作删除所有表数据。
DatabaseOperation.TRUNCATE :这个操作等同于DatabaseOperation.DELETE_ALL,但它不记录日志,操作更快,无法实现回滚,而且有些数据库不支持。
DatabaseOperation.REFRESH :这个操作强制提交数据集到目标数据库。
DatabaseOperation.CLEAN_INSERT :这个操作结合了DELETE_ALL和INSERT操作,为了实现测试前的数据集处于一个已知的状态。
使用:
1、创建数据集,可以从数据库、XML文件和Excel等途径创建IDataSet;
2、继承DatabaseTestCase,实现它的getConnection()和getDataSet()方法,分别用于获取数据库连接和数据集。例如:
public class BaseDBUnitTestCase extends DatabaseTestCase {
@Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSet("employee.xml");
}
@Override
protected IDatabaseConnection getConnection() throws Exception {
IDatabaseTester databaseTester = new JdbcDatabaseTester(
"com.mysql.jdbc.Driver",
"jdbc:mysql://127.0.0.1/mydb",
"root",
"root");
return databaseTester.getConnection();
}
}
3、(可选)实现getSetUpOperation()和getTearDownOperation()方法
例如:
protected DatabaseOperation getSetUpOperation() throws Exception
{
return DatabaseOperation.REFRESH;
}
protected DatabaseOperation getTearDownOperation() throws Exception
{
return DatabaseOperation.NONE;
}
4、添加测试方法。
5、利用DBUnit提供的断言判断数据集和数据表是否相同,Assert提供了两个静态断言方法。public class Assertion
{ public static void assertEquals
(ITable expected, ITable actual) public static void assertEquals
(IDataSet expected, IDataSet actual)}
例如:// Fetch database data after executing your codeIDataSet databaseDataSet = getConnection().createDataSet();ITable actualTable = databaseDataSet.getTable("TABLE_NAME");// Load expected data from an XML datasetIDataSet expectedDataSet = new FlatXmlDataSet(new File("expectedDataSet.xml"));ITable expectedTable = expectedDataSet.getTable("TABLE_NAME");// Assert actual database table match expected tableAssertion.assertEquals(expectedTable, actualTable);
DBUnit补充
:
1、使用查询获取数据库快照:
ITable actualJoinData = getConnection().createQueryTable("RESULT_NAME",
"SELECT * FROM TABLE1, TABLE2 WHERE ...");
2、对比时忽略某些列:
DefaultColumnFilter columnFilter = new DefaultColumnFilter();
columnFilter.excludeColumn("PK*");
columnFilter.excludeColumn("*TIME");
FilteredTableMetaData metaData = new FilteredTableMetaData(
originalTable.getTableMetaData(), columnFilter);
3、行排序:
默认情况下DBUnit对于数据库表会按照主键进行排序。如果缺少主键或者由数据库产生,并且行排序没有指定,
assertEquals就会失败。又必须手动在使用IDatabaseConnection.createQueryTableshi指定order by子句,
或者使用下面的方式:
Assertion.assertEquals(new SortedTable(expected),
new SortedTable(actual, expected.getTableMetaData()));
其他测试框架:
TestNG:
TestNG 是跟JUnit并列的另外一个测试框架,它偏向于高级应用,以JDK5的注解为主要编程手段。尽管JUnit4中也提供了类似的注解语法,但是TestNG仍然具有许多JUnit不具有的高级特性。
1、更多灵活性。 TestNG比JUnit4具有更多的灵活性,JUnit4中由@BeforeClass标记的方法必须是static的,当然其中引用的变量也必须是static类型的。
2、依赖性测试。 在TestNG中通过使用 Test
注释的 dependsOnMethods =
{"dependMethodName"}可以实现依赖性测试,即被依赖的方法测试失败后,这个方法就会被跳过。
3、失败和重运行。
在JUnit4中,如果测试套件包括1000项测试,其中3项失败,很可能就会迫使您重新运行整个测试套件(修改错误以后)。一旦
TestNG 中出现失败,它就会创建一个XML配置文件,对失败的测试加以说明。如果利用这个文件执行 TestNG 运行程序,TestNG
就只运行失败的测试。所以,在前面的例子里,您只需重新运行那三个失败的测试,而不是整个测试套件。
4、参数化测试。 TestNG可以为测试方法指定参数,并且支持高级参数特性(由Test注解的dataProvider指定),而JUnit4不行。
5、定义测试组。 TestNG 可以定义测试组的能力。每个测试方法都可以与一个或多个组相关联,但可以选择只运行某个测试组。要把测试加入测试组,只要把组指定为 @Test
标注的groups参数。
6、更简单的异常检测。 使用 TestNG 的 @ExpectedExceptions
标注可以使代码编写惊人地容易和简单。
Junit4和TestNG的比较见这里:http://www.ibm.com/developerworks/cn/java/j-cq08296/
TestNG如何使单元测试轻而易举见这里:http://www.ibm.com/developerworks/cn/java/j-testng/
Selenium:
Selenium 是 ThoughtWorks 专门为 Web 应用程序编写的一个验收测试工具。据 Selenium 主页所说,与其他测试工具相比,使用 Selenium 的最大好处是:
Selenium 测试直接在浏览器中运行,就像真实用户所做的一样。Selenium 测试可以在 Windows、Linux 和 MacintoshAnd 上的 Internet Explorer、Mozilla 和 Firefox 中运行。其他测试工具都不能覆盖如此多的平台。
使用 Selenium 和在浏览器中运行测试还有很多其他好处。下面是主要的两大好处:
通过编写模仿用户操作的 Selenium 测试脚本,可以从终端用户的角度来测试应用程序。
通过在不同浏览器中运行测试,更容易发现浏览器的不兼容性。
Selenium包括两种模式:TestRunner和Driven。
TestRunner的测试脚本是用 HTML 语言通过一个简单的表布局编写的,包括命令(断言)、目标和值三部分。其中断言通常使用的是组件的 ID 或名称,但 XPath 和 DOM 定位符也是受支持的。
例如:
<table> <tr> <td>open</td> <td>/change_address_form.html</td> <td></td> </tr> <tr> <td>type</td> <td>address_field</td> <td>Betelgeuse state prison</td> </tr> <tr> <td>clickAndWait</td> <td>//input[@name='Submit']</td> <td></td> </tr> <tr> <td>verifyTextPresent</td> <td>Address change successful</td> <td></td> </tr> </table>
测试套件要达到对应用程序的完全测试覆盖,通常需要不止一个测试用例。这就是 Selenium 使用测试套件的原因。测试套件用于将具有类似功能的一些测试用例编成一组,以便让它们按顺序运行。
测试套件和测试用例一样,都是用简单的 HTML 表编写的。Selenium 执行的缺省测试套件的名称是 TestSuite.html。下面的例子展示了一个测试套件,该套件像通常的用户一样测试应用程序。
注意,测试套件使用一个只包含一列的表,表中的每一行指向一个包含某个测试用例的文件。
例如:
<table>
<tr>
<td>Test suite for the whole application</td>
</tr>
<tr>
<td><a href="test_main_page.html">Access _fcksavedurl="test_main_page.html">Access main page</a></td>
</tr>
<tr>
<td><a href="test_login.html">Login to application</a></td>
</tr>
<tr>
<td><a href="test_address_change.html">Change address</a></td>
</tr>
<tr>
<td><a href="test_logout.html">Logout from application</a></td>
</tr>
</table>
Driven Selenium 脚本是用多种受支持的编程语言中的一种编写的 —— 目前可用的有 Java、Ruby 和 Python 驱动程序。这些脚本在浏览器之外的一个单独的进程中运行。驱动程序的任务是执行测试脚本,并通过与运行在浏览器中的 browser bot 进行通信来驱动浏览器。驱动程序与 browser bot 之间的通信使用一种简单的特定于 Selenium 的连接语言 Selenese。driven 脚本比 test runner 脚本更强大、更灵活,可以将它们与 xUnit 框架集成。driven 脚本的缺点(与 test runner 脚本相比)是,这种脚本编写和部署起来更复杂。这是因为驱动程序必须执行以下任务:启动服务器。
部署所测试的应用程序(AUT)。
部署测试脚本。
启动浏览器。
发送命令到 browser bot。
验证 browser bot 执行的命令的结果。
参考见这里:http://www.ibm.com/developerworks/cn/java/wa-selenium-ajax/
发表评论
-
9个最佳的大数据处理编程语言
2017-07-31 14:01 284大数据的浪潮仍在继续 ... -
fckeditor编辑器使用方法
2008-12-05 14:02 1667javascript获取FCKeditor内容: // ... -
fckeditor编辑器配置
2008-12-05 14:00 1523FCKeditor在线编辑器 FCKeditor 这个开源的 ... -
一位软件工程师的6年总结
2008-12-04 10:15 685“又是一年毕业时 ”, ... -
中国程序员哪些缺点或是不足需要改进的
2008-08-14 09:23 2056一定要严谨、规范,思维要活跃,要按流程来操作。二是严密性 ... -
你是合格的程序员吗?—合格程序员应该具备的12种能力
2008-08-12 11:32 980毕业四年来,感觉自己 ... -
美国高级工程师谈Struts 走向
2008-08-12 11:30 815自从2000年Apache Struts出 ...
相关推荐
此外,JUnit的流行也催生了其他语言的类似测试框架,如NUnit(针对.NET),CppUnit(针对C++),形成了一套跨平台的"xUnit"测试家族。 JUnit5是JUnit的最新版本,进一步扩展了其功能,引入了如参数化测试、条件测试...
在“数据库框架ORMLite和单元测试框架junit的使用”这个模块中,首先,你需要了解ORMLite的核心概念: 1. **实体类(Entity Class)**:ORMLite中的实体类对应于数据库表,每个实体类的实例代表数据库中的一行记录...
Junit是Java领域中最广泛使用的自动化测试框架,它简化了编写和执行测试用例的过程,从而提升了软件质量并减少了回归错误的可能性。 首先,Junit的基础概念是理解其核心功能的关键。它允许开发者创建可重复运行的...
JUnit测试框架是Java开发者进行单元测试的首选工具,它的出现极大地简化了软件测试的过程,确保代码的质量和稳定性。本文将详细介绍JUnit的使用方法、核心概念以及它在软件开发中的重要性。 首先,JUnit是一个开源...
JUnit4是Java编程语言中最广泛使用的单元测试框架之一,它为开发者提供了一种方便、高效的方式来验证代码的正确性。这个“junit4 jar包 Java单元测试框架绿色免费版.zip”文件包含的是JUnit4框架的可执行jar包,用于...
Junit是Java编程语言的一个单元测试框架,它极大地简化了测试过程。通过使用Junit,开发者可以编写易于理解和维护的测试代码,快速定位和修复程序中的问题。Junit支持断言(assertions)来验证预期结果,提供注解...
JUnit 是一个广泛使用的Java编程语言的开源测试框架,它的主要目标是支持单元测试。作为xUnit家族的一员,JUnit提供了一套简洁而强大的工具,帮助开发者编写可重复执行的测试用例,确保代码的质量和功能的正确性。 ...
`JUnit` 是一个广泛使用的Java编程语言的单元测试框架,它极大地简化了测试过程,并提高了代码的可靠性和可维护性。本资源"软件测试与Junit实践.rar"显然是为了帮助开发者理解和应用Junit进行软件测试。 软件测试的...
1. **JUnit Platform**:JUnit 5基于平台的设计允许其他测试框架在其上构建,增强了测试生态的互操作性。 2. **Lambda支持**:JUnit 5引入了Java 8的Lambda表达式,使测试代码更加简洁。 3. **条件测试**:`@...
JUnit是Java编程语言中最常用的单元测试框架之一,它为开发者提供了编写、运行和组织测试用例的便捷工具。本文将深入解析JUnit的核心概念、主要功能以及如何使用它来进行单元测试。 1. **JUnit简介** JUnit是由...
Junit是Java领域广泛使用的单元测试框架,它提供了一套简洁易用的API,便于开发者编写和执行测试。 **Junit测试框架** Junit是开源项目,由Eclipse基金会维护,广泛应用于Java开发环境。它为每个测试用例提供了...
Junit作为Java编程语言中最广泛使用的单元测试框架,对于软件测试起到了至关重要的作用。本文将深入探讨软件测试的基本概念、Junit的使用方法及其在实际项目中的实践应用。 软件测试是验证和确认软件是否满足既定...
Junit是Java编程语言中最广泛使用的单元测试框架,它提供了丰富的API和注解,使得编写和执行测试变得简单易行。本文将针对"Junit计算器测试"这一主题,详细讲解如何使用Junit来测试一个简单的计算器应用。 首先,让...
JUnit框架是Java编程语言中最广泛使用的单元测试框架,它为开发者提供了一种便捷的方式来编写可重复执行的测试用例,确保代码的质量和稳定性。在JavaScript的开发环境中,虽然JUnit主要用于Java,但通过一些工具和库...
JUnit 4测试框架是Java开发中的一个重要工具,用于编写和执行单元测试。单元测试是对软件中的最小可测试单元进行检查,通常是一个函数或方法。它的重要性在于能够确保代码的正确性和稳定性,特别是在软件开发的早期...
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。 2 单元测试概念 单元:在Java中,一个类就是一个单元 单元测试:...