JUnit单元测试
JUnit单元测试
JUnit使用
①测试方法上必须使用@Test进行修饰
②测试方法必须使用public void 进行修饰,不能带任何的参数
③新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开
④测试类所在的包名应该和被测试类所在的包名保持一致
⑤测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖
⑥测试类使用Test作为类名的后缀(不是必须)
⑦测试方法使用test作为方法名的前缀(不是必须)
Runner只是一个抽象类,表示用于运行Junit测试用例的工具,通过它可以运行测试并通知Notifier运行的结果。
①测试方法上必须使用@Test进行修饰
②测试方法必须使用public void 进行修饰,不能带任何的参数
③新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开
④测试类所在的包名应该和被测试类所在的包名保持一致
⑤测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖
⑥测试类使用Test作为类名的后缀(不是必须)
⑦测试方法使用test作为方法名的前缀(不是必须)
Runner只是一个抽象类,表示用于运行Junit测试用例的工具,通过它可以运行测试并通知Notifier运行的结果。
一、Suit
@RunWith(Suite.class)
@SuiteClasses({Person.class, People.class})
public class TestSuitMain{
}
@RunWith(Suite.class)
@SuiteClasses({Person.class, People.class})
public class TestSuitMain{
}
二、Parameterized
而这时常会给我们造成困扰,因为有时候我们需要为测试方法输入参数,甚至是批量指定多个待测参数。这时Parameterized这个Runner就能满足我们的要求,用法如下:
而这时常会给我们造成困扰,因为有时候我们需要为测试方法输入参数,甚至是批量指定多个待测参数。这时Parameterized这个Runner就能满足我们的要求,用法如下:
@RunWith(Parameterized.class)
public class TestGenerateParams{
private String greeting;
public TestGenerateParams(String greeting){
super();
this.greeting = greeting;
}
@Test
public void testParams(){ System.out.println(greeting);
}
public class TestGenerateParams{
private String greeting;
public TestGenerateParams(String greeting){
super();
this.greeting = greeting;
}
@Test
public void testParams(){ System.out.println(greeting);
}
/**
* 这里的返回的应该是一个可迭代数组,且方法必须是public static
* @return
*/
@Parameters
public static List getParams(){
return Arrays.asList(new String[][]{{"hello"},{"hi"},{"good morning"},{"how are you"}});
}
}
* 这里的返回的应该是一个可迭代数组,且方法必须是public static
* @return
*/
@Parameters
public static List getParams(){
return Arrays.asList(new String[][]{{"hello"},{"hi"},{"good morning"},{"how are you"}});
}
}
三、Category------继承自Suit,更强大,它可以让我们对测试类中被测试的方法进行分类执行
public class PersonTest{
@Category(AttributeFun.class)
@Test
public void testGetAge(){
int age = person.getAge();
assertEquals(3, age);
}
@Category(AttributeFun.class)
@Test
public void testGetName(){
String name = person.getName();
assertEquals("Willard", name);
}
@Category(BehaviorFun.class)
@Test
public void testTalk(){
String message = person.talkTo("Jimy");
assertNotNull(message);
}
@Category(BehaviorFun.class)
@Test(timeout=200)
public void testWalk(){
person.walk();
}
}
//对应的测试执行代码如下:
@RunWith(Categories.class)
@SuiteClasses(PersonTest.class)
@IncludeCategory(AttributeFun.class)
public class CategoryTest{
//注意,如果不加@IncludeCategory注解,那么就和使用Suit具有一样的效果了。
}
四、Theories------虽意为原理或推测的意思,但我在这里以更直观的方式表述它:提供一组参数的排列组合值作为待没方法的输入参数。
同时注意到在使用Theories这个Runner的时候,我们的待测方法可以拥有输入参数,而这在其它的Runner中的测试方法是不成的
同时注意到在使用Theories这个Runner的时候,我们的待测方法可以拥有输入参数,而这在其它的Runner中的测试方法是不成的
@RunWith(Theories.class)public class TheoriesTest{
@DataPoint
public static String nameValue1 = "Tony";
@DataPoint
public static String nameValue2 = "Jim";
@DataPoint public static int ageValue1 = 10;
@DataPoint
public static int ageValue2 = 20;
@Theory
public void testMethod(String name, int age){
System.out.println(String.format("%s's age is %s", name, age));
}
}
@DataPoint
public static String nameValue1 = "Tony";
@DataPoint
public static String nameValue2 = "Jim";
@DataPoint public static int ageValue1 = 10;
@DataPoint
public static int ageValue2 = 20;
@Theory
public void testMethod(String name, int age){
System.out.println(String.format("%s's age is %s", name, age));
}
}
上面的代码的意思是,将”Tony”、”Jim”、10、20四个参数以类型合法的排列组合传给待没方法。因此输出的结果必然也有2x2=4种:
Tony's age is 10
Tony's age is 20
Jim's age is 10
Jim's age is 20
不过,为了简单,我们除了可以使用@DataPoint注解来提供参数之外,还可以通过@DataPoints注解来提供参数,
参照上述代码,只需要将@DataPoint注解标注的四个字段参数替换为如下的两个即可:
参照上述代码,只需要将@DataPoint注解标注的四个字段参数替换为如下的两个即可:
@DataPoints
public static String[] names = {"Tony", "Jim"};
@DataPoints
public static int[] ageValue1 = {10, 20};
public static String[] names = {"Tony", "Jim"};
@DataPoints
public static int[] ageValue1 = {10, 20};
上展示了四个Junit运行器的使用示例,有这个四个运行器的支持,基本上大部分的测试需求得可以得到解决。
当然Junit提供的功能远不止这些。除此之外,我们还可以使用Junit4提供的Rule/Assume/Assert等。
当然Junit提供的功能远不止这些。除此之外,我们还可以使用Junit4提供的Rule/Assume/Assert等。
其中使用Rule可以为单元测试指定测试规则,下面展示了这些可用的Rule:
Verifier: 验证测试执行结果的正确性。
ErrorCollector: 收集测试方法中出现的错误信息,测试不会中断,如果有错误发生测试结束后会标记失败。
ExpectedException: 提供灵活的异常验证功能。
Timeout: 用于测试超时的Rule。
ExternalResource: 外部资源管理。
TemporaryFolder: 在JUnit的测试执行前后,创建和删除新的临时目录。
TestWatcher: 监视测试方法生命周期的各个阶段。
TestName: 在测试方法执行过程中提供获取测试名字的能力。
此外,Assume表示假设,但它实际是对待没方法的参数进行合法性校验的,如果校验不合格则直接抛异常,而不执行测试。
这和Guava中的Predictions类似。Assume提供的校验规则如下:
这和Guava中的Predictions类似。Assume提供的校验规则如下:
assumeTrue/assumeFalse、 assumeNotNull、 assumeThat、 assumeNoException
例如:(通过下述代码也可以看到,要使用参数,则应使用@Theory注解)
@Theory
public void printAge(String name, int age){
Assume.assumeTrue(age > 0);//如果参数age<=0,会抛AssumptionViolatedException异常
System.out.println(String.format("%s's Name is %s.", name, age));
}
public void printAge(String name, int age){
Assume.assumeTrue(age > 0);//如果参数age<=0,会抛AssumptionViolatedException异常
System.out.println(String.format("%s's Name is %s.", name, age));
}
Assert是Junit提供的断言,与Assume不同,Assert是对测试结果的校验,它提供的检验规则如下:
AssertTrue、AssertFalse:结果的true、false。
AssertThat:使用Matcher做自定义的校验。
AssertEquals、AssertNotEquals:判断两个对象是否相等。
AssertNull、AssertNotNull:判断对象是否为空。
AssertSame:判断两个对象是否为同一个,不同于equals这里是使用“==”判断。
AssertArrayEquals:判断两个数组是否相等。
五、在Android项目里面使用JUnit
在Android项目里面使用JUnit是很简单的,你只需要将JUnit这个library加到你的dependencies里面。
testCompile 'junit:junit:4.12'
如果你通过AndroidStudio创建一个项目,这个dependency默认是加上了的,所以你甚至这步都可以省略。
此外,你需要把测试代码放到src/test/java 目录下面。
testCompile 'junit:junit:4.12'
如果你通过AndroidStudio创建一个项目,这个dependency默认是加上了的,所以你甚至这步都可以省略。
此外,你需要把测试代码放到src/test/java 目录下面。
说明
①Failure一般由单元测试使用的断言方法判断失败所引起的,这经表示测试点发现了问题,就是说程序输出的结果和我们预期的不一样。
②Error是由代码异常引起的,它可以产生于测试代码本身的错误,也可以是被测试代码中的一个隐藏的bug。
①Failure一般由单元测试使用的断言方法判断失败所引起的,这经表示测试点发现了问题,就是说程序输出的结果和我们预期的不一样。
②Error是由代码异常引起的,它可以产生于测试代码本身的错误,也可以是被测试代码中的一个隐藏的bug。
总结
JUnit带给我们的不仅是开发效率、代码质量的提高,更是一种思想的提高,现在都在讲测试驱动开发、回归质量大概就是这种思想。
JUnit使用起来不仅简单方便,其源码更是短小精悍,Erich Gamma 是著名的 GoF 之一,在JUnit中设计模式的使用堪称经典,有优良的扩展性和可重用性。值得细细品味。
JUnit带给我们的不仅是开发效率、代码质量的提高,更是一种思想的提高,现在都在讲测试驱动开发、回归质量大概就是这种思想。
JUnit使用起来不仅简单方便,其源码更是短小精悍,Erich Gamma 是著名的 GoF 之一,在JUnit中设计模式的使用堪称经典,有优良的扩展性和可重用性。值得细细品味。
原文链接:http://www.jxszl.com/biancheng/JAVA/446458.html