ch03-mastering
测试遵循的模式:
1.通过把环境设置成已知状态(如创建对象,获取资源)来创建测试。测试前的状态通常称为Test Fixture
2.调用待测试的方法
3.确认测试结果,通常通过调用一个或更多的assert方法来实现
建议把测试类作为测试用例类的内部类
建议用testXXXYYY的命名模式命名测试方法。其中XXX是待测的领域方法的名字,YYY说明了测试之间的不同。
@Before执行在每个@Test方法之前,用它来设置初始环境。
建议使用assert方法时确保第一个参数为String类型的签名。这个参数可以让你提供一个有意义的描述,这样有利于找出测试失败的原因和地点
public class TestDefaultController
{
[...]
@Before
public void initialize()
throws Exception
{
controller = new DefaultController();
request = new SampleRequest();
handler = new SampleHandler();
controller.addHandler( request, handler );
}
@Test
public void testAddHandler()
{
RequestHandler handler2 = controller.getHandler( request );
assertSame( "Controller.getHandler must return the samplehandler", handler2, handler );
}
private class SampleHandler
implements RequestHandler
{
public Response process( Request request )
throws Exception
{
return new SampleResponse();
}
}
}
测试异常遵循的模式:
1.插入应当抛出异常的语句
2.向@Test注释添加expected参数,来指定你所预料的异常类型
3.一切正常进行
建议给测试去一个清晰的名字。因为这个测试代表了一种异常情况。这样就可以把所有的测试放在一起,并说明每种变体的目的
public class TestDefaultController
{
[...]
@Test( expected = RuntimeException.class )
public void testGetHandlerNotDefined()
{
SampleRequest request = new SampleRequest( "testNotDefined" );
controller.getHandler( request );
}
@Test( expected = RuntimeException.class )
public void testAddRequestDuplicateName()
{
SampleRequest request = new SampleRequest();
SampleHandler handler = new SampleHandler();
controller.addHandler( request, handler );
}
}
以毫秒为单位向@Test注释添加timeout参数,该参数就是我们所预计的运行时间
通过@Ignore来忽视某个测试,并在它的value参数中添加忽视的原因
public class TestDefaultController
{
[...]
@Test( timeout = 130)
@Ignore( value = "Skip for now" )
public void testProcessMultipleRequestsTimeout()
{
Request request;
Response response = new SampleResponse();
RequestHandler handler = new SampleHandler();
for ( int i = 0; i < 99999; i++ )
{
request = new SampleRequest( String.valueOf( i ) );
controller.addHandler( request, handler );
response = controller.processRequest( request );
assertNotNull( response );
assertNotSame( ErrorResponse.class, response.getClass() );
}
}
}
ch05-cobertura
使用cobertura来得出测试覆盖率
首先下载cobertura-1.9.4.1-bin.tar.gz 解压
添加%COBERTURA_HOME%变量,并将它添加到PATH中
测试用例类的文件结构
首先先编译测试用例类
java -cp .;junit-4.11.jar;hamcrest-core-1.3.jar;$COBERTURA_HOME\cobertura.jar -d uninstrumented src\*.java
其中java -d ==> the directory you want to put your class files in(javac will create directory if the java files defined packages)
然后将编译好的类instrument化
cobertura-instrument --destination instrumented uninstrumented\Calculator.class
这个--destination 参数定义了将instrument后的类保存到什么地方。然后指定了预编译类的路径,这里是uninstrumented\Calculator.class
接下来针对instrument后的代码运行单元测试
为了运行测试,需要在CLASSPATH中放置以下资源:Cobertura.jar 包含了instrument后的类的目录要在包含了尚未instrument的类的目录之前
java -cp .;junit-4.11.jar;hamcrest-core-1.3.jar;$COBERTURA_HOME\cobertura.jar;instrumented;uninstrumented
-Dnet.sourceforge.cobertura.datafile=cobertura.ser org.junit.runner.JUnitCore uninstrumented\TestCalculator
其中java -D设置系统的参数
其中Dnet.sourceforge.cobertura.datafile属性指向一个文件,Cobertura会把代码覆盖率结果存储在这个文件中。如果没有指定这个属性,Cobertura会在当前目录下创建一个名为cobertura.ser的文件
最后生成测试覆盖率的报告
在运行以上脚本之后,instrumented文件夹中可以看到instrumen后的类,以及一个针对给定测试运行的代码覆盖文件
使用cobertura-report脚本可以生成HTML格式的报告
cobertura-report --format html --datafile cobertura.ser --destination reports src
其中--destination 参数来指定报告的输出目录和测试类java源文件目录,如果不指定源文件目录,那么无法显示某个类的代码覆盖率,在报告中无法查看某个特定的类被测试到何种程度
最后,建议在创建测试目录时使用“分离但等同”的结构
把所有测试类和待测试类都放在同一个包中,但采用平行目录结构
为了可以访问受保护和默认的方法,你需要把测试和待测试类放到同一包中
为了简化文件管理,并让人明确区分测试类和领域类,你就需要把测试类放在一个单独的目录中