测试用例
测试用例是可以确保另一段代码(方法)按预期工作一部分代码,而一个良好的单元测试用例的特点是:已知输入和预期输出,每一项需求至少需要两个单元测试用例:一个正检验,一个负检验。如果一个需求有子需求,每一个子需求必须至少有正检验和负检验两个测试用例。
业务对象
前面的过程描述了使用注解的方式,接下来我们尝试下通过继承类来构建测试用例的方式,另外这里针对待测试类做了些简单的抽象,考虑到无论是教职工还是学生都具有姓名和年龄这两个属性,并且都具备用餐与运动两种行为,故此创建了接口及抽象类供继承使用,以及消除冗余代码
Step 1: 创建接口 Person.java
public interface Person {
/**
* 用餐
* @return
*/
public abstract String eat();
/**
* 运动
* @return
*/
public abstract String sport();
}
Step 2: 创建抽象类 BasePerson.java
public abstract class BasePerson implements Person {
private String name;
private int weight;
public BasePerson() {
}
public BasePerson(String name, int weight) {
this.name = name;
this.weight = weight;
}
@Override
public void eat() {
System.out.println("民以食为天!");
setWeight(weight + 1);
System.out.println("体重增加了=====>" + weight);
}
@Override
public void sport() {
System.out.println("生命在于运动!");
setWeight(weight - 1);
System.out.println("体重减轻了=====>" + weight);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "BasePerson{" +
"name='" + name + '\'' +
", weight=" + weight +
'}';
}
}
Step 3: 创建待测试类 Teacher.java
public class Teacher extends BasePerson {
public Teacher() {
}
public Teacher(String name, int weight) {
super(name, weight);
}
public void work() {
System.out.println("春风化雨,桃李天下!");
}
}
测试工具
------------
junit.framework.TestCase
setUp()
tearDown()
assertTrue(Boolean bool)
1 int countTestCases()
为被run(TestResult result) 执行的测试案例计数
2 TestResult createResult()
创建一个默认的 TestResult 对象
3 String getName()
获取 TestCase 的名称
4 TestResult run()
一个运行这个测试的方便的方法,收集由TestResult 对象产生的结果
5 void run(TestResult result)
在 TestResult 中运行测试案例并收集结果
6 void setName(String name)
设置 TestCase 的名称
7 void setUp()
创建固定装置,例如,打开一个网络连接
8 void tearDown()
拆除固定装置,例如,关闭一个网络连接
9 String toString()
返回测试案例的一个字符串表示
Step 4: 创建测试类 TeacherTest.java
public class TeacherTest extends TestCase {
private Teacher teacher;
protected void setUp(){
System.out.println("setUp...");
teacher = new Teacher("Joyce", 67);
}
public void testEat(){
teacher.eat();
assertEquals(68,teacher.getWeight() );
}
public void testSport(){
teacher.sport();
assertTrue(66 == teacher.getWeight());
}
public void testWork(){
teacher.work();
}
public void tearDown(){
System.out.println("tearDown...");
}
}
测试运行器
public class RunnerTest {
@Test
public void testJUnitCore() {
Result result = JUnitCore.runClasses(TeacherTest.class);
for (Failure failure :
result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qywh8n46-1603536448641)(D:\blog\0-图说百态\assets\01-JUnit单元测试\image-20200904004711214.png)]
测试用例是使用 JUnitCore 类来执行的。JUnitCore 是运行测试的外观类。要从命令行运行测试,可以运行java org.junit.runner.JUnitCore。对于只有一次的测试运行,可以使用静态方法 runClasses(Class[])。
测试用例是使用 JUnitCore 类来执行的。JUnitCore 是运行测试的外观类。它支持运行 JUnit 4 测试, JUnit 3.8.x 测试,或者他们的混合。 要从命令行运行测试,可以运行 java org.junit.runner.JUnitCore 。对于只有一次的测试运行,可以使用静态方法 runClasses(Class[])。
org.junit.runner.JUnitCore
runClasses(Class clazz);
org.junit.runner.Result
getFailures()
wasSuccessful()
org.junit.runner.notification.Failure
toString()
TestResult 类收集所有执行测试案例的结果。它是收集参数层面的一个实例。这个实验框架区分失败和错误。失败是可以预料的并且可以通过假设来检查。错误是不可预料的问题就像 ArrayIndexOutOfBoundsException。TestResult 类的一些重要方法列式如下
1 void addError(Test test, Throwable t)
在错误列表中加入一个错误
2 void addFailure(Test test, AssertionFailedError t)
在失败列表中加入一个失败
3 void endTest(Test test)
显示测试被编译的这个结果
4 int errorCount()
获取被检测出错误的数量
5 Enumeration errors()
返回错误的详细信息
6 int failureCount()
获取被检测出的失败的数量
7 void run(TestCase test) 运行 TestCase
8 int int runCount()
获得运行测试的数量
9 void startTest(Test test)
声明一个测试即将开始
10 void stop()
标明测试必须停止
测试套件
@RunWith(Suite.class)
@Suite.SuiteClasses({StudentTest.class, TeacherTest.class})
public class SuiteTest {
}
随着项目进度的开展,单元测试类会越来越多,可是直到现在我们还只会一个一个的单独运行测试类,这在实际项目实践中肯定是不可行的。为了解决这个问题,JUnit 提供了一种批量运行测试类的方法,叫做测试套件。
测试套件意味着捆绑几个单元测试用例并且一起执行他们。在 JUnit 中,@RunWith和@Suite注释用来运行套件测试。
每次需要验证系统功能正确性时,只执行一个或几个测试套件便可以了。测试套件的写法非常简单,我们需要遵循以下规则:
创建一个空类作为测试套件的入口。
使用注解 org.junit.runner.RunWith 和 org.junit.runners.Suite.SuiteClasses 修饰这个空类。
将 org.junit.runners.Suite 作为参数传入注解 RunWith,以提示 JUnit 为此类使用套件运行器执行。
将需要放入此测试套件的测试类组成数组作为注解 SuiteClasses 的参数。
保证这个空类使用 public 修饰,而且存在公开的不带有任何参数的构造函数。
测试套件中不仅可以包含基本的测试类,而且可以包含其它的测试套件,这样可以很方便的分层管理不同模块的单元测试代码。
注意:一定要保证测试套件之间没有循环包含关系,否则无尽的循环就会出现在我们的面前。
org.junit.runner.RunWith;
org.junit.runner.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
Class clazz1,Class clazz2...
})
public class JunitTestSuite{}
TestSuite 类是测试的组成部分。它运行了很多的测试案例。TestSuite 类的一些重要方法列式如下:
1 void addTest(Test test)
在套中加入测试。
2 void addTestSuite(Class<? extends TestCase> testClass)
将已经给定的类中的测试加到套中。
3 int countTestCases()
对这个测试即将运行的测试案例进行计数。
4 String getName()
返回套的名称。
5 void run(TestResult result)
在 TestResult 中运行测试并收集结果。
6 void setName(String name)
设置套的名称。
7 Test testAt(int index)
在给定的目录中返回测试。
8 int testCount()
返回套中测试的数量。
9 static Test warning(String message)
返回会失败的测试并且记录警告信息。
Student
Teacher
StudentTest
TeacherTest
TestRunner
SuiteTest
SuiteGroupTest
JUnit 测试框架具有以下重要特性:
测试工具
测试套件
测试运行器
测试分类
测试工具是一整套固定的工具用于基线测试。测试工具的目的是为了确保测试能够在共享且固定的环境中运行,因此保证测试结果的可重复性。它包括:
在所有测试调用指令发起前的 setUp() 方法。
在测试方法运行后的 tearDown() 方法。
测试套件
测试套件意味捆绑几个测试案例并且同时运行。在 JUnit 中,@RunWith 和 @Suite 都被用作运行测试套件。以下为使用 TestJunit1 和 TestJunit2 的测试分类:
测试运行器
测试运行器 用于执行测试案例。以下为假定测试分类成立的情况下的例子:
org.junit.runner.JUnitCore
org.junit.runner.Result
org.junit.runner.notificaition.Failure
JUnit 测试分类
测试分类是在编写和测试 JUnit 的重要分类。几种重要的分类如下:
包含一套断言方法的测试断言
包含规定运行多重测试工具的测试用例
包含收集执行测试用例结果的方法的测试结果
更多特性
忽略测试
有时可能会发生我们的代码还没有准备好的情况,这时测试用例去测试这个方法或代码的时候会造成失败。@Ignore 注释会在这种情况时帮助我们。
一个含有 @Ignore 注释的测试方法将不会被执行。
如果一个测试类有 @Ignore 注释,则它的测试方法将不会执行。
在类级别上使用 @Ignore 来忽略所有的测试用例
JUnit 参数化测试
Junit 4 引入了一个新的功能参数化测试。参数化测试允许开发人员使用不同的值反复运行同一个测试。你将遵循 5 个步骤来创建参数化测试。
- 用
@RunWith(Parameterized.class)来注释 test 类。 - 创建一个由
@Parameters注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。 - 创建一个公共的构造函数,它接受和一行测试数据相等同的东西。
- 为每一列测试数据创建一个实例变量。
- 用实例变量作为测试数据的来源来创建你的测试用例。
一旦每一行数据出现测试用例将被调用。
建议
①测试方法上必须使用@Test进行修饰
②测试方法必须使用public void 进行修饰,不能带任何的参数
③新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开
④测试类所在的包名应该和被测试类所在的包名保持一致
⑤测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖
⑥测试类使用Test作为类名的后缀(不是必须)
⑦测试方法使用test作为方法名的前缀(不是必须)
参考资料
https://blog.csdn.net/u012085824/article/details/80254434
5.JUnit测试框架目前大体分为两种(JUnit 3.8 和 JUnit 4.x)
———————————— JUnit 3.8 ———————————————
涉及到的包一般是 import junit.framework.*
6.在 JUnit 3.8 中,测试类要继承TestCast类,而TestCast类又继承于Assert类,测试方法需满足如下原则:
1)修饰符设为 public
2)返回类型 void
3)没有方法参数
4)方法名称必须以test开头
7.不能依赖于测试方法的执行顺序
8.setUp方法和testDown方法都是TestCase类的方法
1)setUp方法是在执行每个测试方法之前执行的
2)testDown方法是在执行每个测试方法之后执行的
———————————— JUnit 4 ———————————————
涉及到的包是 import org.junit.*
9)在junit 4 当中测试类无需继承于 TestCase类,测试方法的名字也无需以test开头,主要以注解的方式来定义,只要在测试方法加上@Test就可以进行测试,但有些原则还是要以junit3 的风格来设计,比如测试方法以test开头,习惯问题吧,
10)
@Test :定义一个测试方法的标志
@Test(timeout=1000) :设置超时时间,如果测试时间超过了你定义的timeout,测试失败
@Test(expected) : 申明出会发生的异常,比如 @Test(expected = Exception.class)
@Before : 跟junit 3.8 上的setUp() 方法同样的效果,方法名最好和setUp()一样,但不强求,在每一个测试方法之前被执行
@After : 跟junit 3.8 上的tearDown() 方法同样的效果,方法名最好和tearDown()一样,但不强求,在每一个测试方法之后被执行
@BeforeClass : 被该注解申明的方法,功能是:在所有的测试方法之前执行,只执行一次
@AfterClass : 被该注解申明的方法,功能是:在所有的测试方法之后执行,只执行一次
@Ignore :让 测试方法 或 测试类 不被执行,让其失去测试的功能
本文介绍了如何使用Java创建测试用例,通过接口Person定义公共行为,抽象类BasePerson实现基础属性和方法,具体展示了Teacher类的继承和测试。使用JUnit框架编写了TeacherTest类,包括setUp(), tearDown(), 和多个测试方法,如eat(), sport(), work()的测试。最后讨论了测试套件和JUnit Core的使用,便于批量执行和组织测试代码。
855

被折叠的 条评论
为什么被折叠?



