第1关:Junit参数化测试
100
- 任务要求
- 参考答案
- 评论11
任务描述
根据所学内容,要求用户补全Junit的参数化测试代码。
相关知识
Junit参数化测试
如果测试代码大同小异,代码结构都是相同的,不同的只是测试的数据和预期值,那么Junit的参数化测试可以派上用场了:Junit的参数化测试允许开发人员使用不同的参数反复运行同一个测试。你将遵循以下 5 个步骤来创建参数化测试。
- 用
@RunWith(Parameterized.class)
来注释 test 类。 - 创建一个由 @Parameters 注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合。
- 创建一个公共的构造函数,它接受和一行测试数据相等同的东西。
- 为每一列测试数据创建一个实例变量。
- 用实例变量作为测试数据的来源来创建你的测试用例。
在JUnit中,可以使用@RunWith
和@parameter
这两个注解来为单元测试传递参数。
@RunWith注解:当类被@RunWith注解修饰,或者类继承了一个被该注解修饰的类,JUnit将会使用这个注解所指明的运行器(runner)来运行测试。
@Parameters注解:然后在该类提供数据的方法上加上一个@Parameters注解,这个方法必须是静态static的,不能带参数,并且返回一个集合Collection。
在测试类的构造方法中为各个参数赋值,(构造方法是由JUnit调用的),最后编写测试类,它会根据参数的组数来运行测试多次。
注意:必须要为类的所有字段赋值,不管你是不是都用到!否则,Junit会出错。
代码示例
我们现在来看一个简单的 add 方法。
//MathUtils.java
package com.trustie.junittest;
public class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}
接下来我们创建一个为上面的JUnit测试类 MathUtilsTest.java
//MathUtilsTest.java
package com.trustie.junittest;
import java.util.Arrays;
import java.util.Collection;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import com.trustie.junittest.MathUtils;
/**
* 参数化测试的类必须有Parameterized测试运行器修饰
*
*/
@RunWith(Parameterized.class)
public class MathUtilsTest {
private int input1;
private int input2;
private int expected;
/**
* 准备数据。数据的准备需要在一个方法中进行,该方法需要满足一定的要求:
1)该方法必须由Parameters注解修饰
2)该方法必须为public static的
3)该方法必须返回Collection类型
4)该方法的名字不做要求
5)该方法没有参数
* @return
这里设置了四组参数,只有当四组参数都通过测试,才代表测试通过
*/
@Parameters
public static Collection prepareData(){
Object [][] bject = {{-1,-2,-3},{0,2,2},{-1,1,0},{1,2,3}};
return Arrays.asList(bject);
}
public MathUtilsTest(int input1,int input2,int expected){
this.input1 = input1;
this.input2 = input2;
this.expected = expected;
}
@Test
public void testAdd(){
MathUtils add = new MathUtils();
int result = add.add(input1, input2);
Assert.assertEquals(expected,result);
}
}
/********************【测试执行流程】************************************************************************/
// 首先会执行prepareData()方法,将准备好的数据作为一个Collection返回;
// 接下来根据准备好的数据调用构造方法。Collection中有几个元素,该构造方法就会被调用几次;
// 我们这里Collection中有4个元素,所以MathUtilsTest()构造方法会被调用4次,于是会产生4个该测试类的对象;
// 对于每一个测试类的对象,都会去执行testAdd()方法;
// Collection中的数据是来自于JUnit传给MathUtilsTest(int input1,int input2,int expected)构造方法的
// 于是testAdd()用到的三个私有参数,就被MathUtilsTest()构造方法设置好值了,而它们三个的值就来自于Collection。
/************************************************************************************************************/
编程要求
给定一个减法函数Calculator.java如下:
Calculator.java
/**
* 数学计算-->减法
*/
public class Calculator {
public int sub(int a, int b) {
return a - b;
}
}
请按照上面索索的知识,补全题目中参数化测试 ParameterTest.java
的prepareData()
函数。
本关涉及的代码文件ParameterTest.java
的代码如下:
package step1;
import static org.junit.Assert.assertEquals; //静态导入
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import step1.Calculator;
/**
* JUnit4的参数化测试
*/
@RunWith(Parameterized.class)
public class ParameterTest {
private int input11;
private int input22;
private int expected;
public ParameterTest(int input11, int input22, int expected){
this.input11 = input11;
this.input22 = input22;
this.expected = expected;
}
@Parameters
public static Collection prepareData(){
/**
*该二维数组的类型必须是Object类型的
*该二维数组中的数据是为测试Calculator中的sub()方法而准备的
*该二维数组中的每一个元素中的数据都对应着构造方法ParameterTest()中的参数的位置
*所以依据构造方法的参数位置判断,该二维数组中的第一个数减去第二个数等于第三个数
*请在Begin/End内补全代码,要求为单元测试传递4组参数,来验证Calculator中的sub函数编写是否正确
*提示:只需要补2行代码
*/
/*********************************Begin*************************************************/
/**********************************End**************************************************/
}
@Test
public void testSub(){
Calculator cal = new Calculator();
assertEquals(cal.sub(input11, input22), expected);
}
}
评测说明
本关卡的测试文件是TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。
具体测试过程如下:
1.平台自动编译生成TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。
预期输入: 预期输出:true
友情提示
1.请不要直接println
最终输出,否则平台发现此类情况后,将一律扣掉本关经验值,并且追加处罚措施。
2.学员答题时请尽量手敲代码,请勿从实训讲解代码片段中复制代码段粘贴到答题区域作答,复制的内容会保留一些格式和字符,导致编译失败。
开始你的任务吧,祝你成功!
package step1;
import static org.junit.Assert.assertEquals; //静态导入
import java.util.Arrays;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import step1.Calculator;
/**
* JUnit4的参数化测试
*/
@RunWith(Parameterized.class)
public class ParameterTest {
private int input11;
private int input22;
private int expected;
public ParameterTest(int input11, int input22, int expected){
this.input11 = input11;
this.input22 = input22;
this.expected = expected;
}
@Parameters
public static Collection prepareData(){
/**
*该二维数组的类型必须是Object类型的
*该二维数组中的数据是为测试Calculator中的sub()方法而准备的
*该二维数组中的每一个元素中的数据都对应着构造方法ParameterTest()中的参数的位置
*所以依据构造方法的参数位置判断,该二维数组中的第一个数减去第二个数等于第三个数
*请在Begin/End内补全代码,要求为单元测试传递4组参数,来验证Calculator中的sub函数编写是否正确
*提示:只需要补2行代码
*/
/*********************************Begin*************************************************/
Object[][] bject ={{-1,-2,1},{0,2,-2},{-1,1,-2},{1,2,-1}};
return Arrays.asList(bject);
/**********************************End**************************************************/
}
@Test
public void testSub(){
Calculator cal = new Calculator();
assertEquals(cal.sub(input11, input22), expected);
}
}
第2关:Junit异常测试
100
- 任务要求
- 参考答案
- 评论11
任务描述
学员写一个Junit异常测试,用来判断实例化的对象数据是否合法。
相关知识
Junit异常测试
Junit 用代码处理提供了一个追踪异常的选项。你可以测试代码是否它抛出了想要得到的异常。通过@Test
元数据中的expected
属性验证是否抛出期望的异常,expected
属性的值是一个异常的类型,如果抛出了期望的异常,则测试通过,否则不通过。
现在让我们看下 @Test(expected=* .class)
注解的具体使用。
代码示例
//ExceptionTest.java
public class ExceptionTest {
@Test(expected = ArithmeticException.class)
public void divisionWithException() {
int i = 1/0;
}
}
在上述例子中,divisionWithException()
方法将抛出ArithmeticExceptio
n异常,因为这是一个预期的异常,因此单元测试会通过。其实,Junit
的异常测试我们追踪到了预期的异常信息,所以代码会执行成功而不是中断。
编程要求
本关的任务是写一个Junit异常测试,用来判断实例化的对象数据是否合法。具体在JunitException.java
中补全异常测试代码:要求判断Person
类中实例化的对象年龄是否合法,如果不合法则抛出IllegalArgumentException
异常。
Person类代码如下:
//Person.java
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0 ) {
throw new IllegalArgumentException("age is invalid");
}
this.age = age;
}
}
测试类JunitException.java
的代码如下:
package step2;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import step2.Person;
public class JunitException {
/**
*请在Begin/End内加一行注解,要求检查Person对象的年龄是否合法,不合法则
*抛出IllegalArgumentException异常
*/
/************************************Begin**********************************************/
/************************************End************************************************/
public void checkage() {
Person person = new Person();
person.setAge(-1);
}
}
评测说明
本关卡的测试文件是TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。
具体测试过程如下:
1.平台自动编译生成TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。
预期输入: 预期输出:true
友情提示
1.请不要直接println
最终输出,否则平台发现此类情况后,将一律扣掉本关经验值,并且追加处罚措施。
2.学员答题时请尽量手敲代码,请勿从实训讲解代码片段中复制代码段粘贴到答题区域作答,复制的内容会保留一些格式和字符,导致编译失败。
开始你的任务吧,祝你成功!
package step2;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import step2.Person;
public class JunitException {
/**
*请在Begin/End内加一行注解,要求检查Person对象的年龄是否合法,不合法则
*抛出IllegalArgumentException异常
*/
/************************************Begin**********************************************/
@Test(expected = IllegalArgumentException.class)
/************************************End************************************************/
public void checkage() {
Person person = new Person();
person.setAge(-1);
}
}
第3关:Junit套件测试
100
- 任务要求
- 参考答案
- 评论11
任务描述
根据所学内容,要求用户补全Junit的套件测试代码。 ####相关知识 #####本关必读
测试套件意味着捆绑几个单元测试用例并且一起执行他们。在 JUnit 中,@RunWith 和 @Suite 注释用来运行套件测试。
代码示例
对下面两个类进行单元测试 ,组成套件测试。
类代码:
//Car.java
public class Car {
public int getWheels() {
return 4;
}
}
//Rectangle.java
public class Rectangle{
public int getArea(int width,int height){
return width*height;
}
}
测试类代码:
//CarTest.java
public class CarTest {
Car car;
@Before
public void setUp() throws Exception {
car = new Car();
}
@Test
public void testGetWheels() {
int result = car.getWheels();
assertEquals(4, result);
}
}
//RectangleTest.java
public class RectangleTest {
Rectangle rectangle;
@Before
public void setUp() throws Exception {
rectangle=new Rectangle();
}
@Test
public void testGetArea() {
int result = rectangle.getArea(12, 2);
assertEquals(24, result);
}
}
测试套件代码:
@RunWith(Suite.class)
@Suite.SuiteClasses({ CalculateTest.class, CarTest.class, RectangleTest.class })
public class AllTests {
}
注意:套件测试代码需要紧靠测试类,不能有换行!
编程要求
本关卡的要求是让学员补全Junit的套件测试代码。具体要求如下:
给定一个类Calculate.java
和对应的测试类CalculateTest.java
,如下:
//Calculate.java
public class Calculate {
public int add(int a, int b) {
return a + b;
}
}
//CalculateTest.java
public class CalculateTest {
Calculate calculate;
@Before
public void setUp() throws Exception {
calculate = new Calculate();
}
@Test
public void testAdd() {
int result = calculate.add(12, 12);
assertEquals(24, result);
}
请在SuiteTest.java
内补全CalculateTest和CarTest的套件测试代码。
本关涉及到的SuiteTest.java
代码如下:
package step3;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import step3.Calculate;
import step3.CalculateTest;
import step3.Car;
import step3.CarTest;
/*
请在星号后加两行注解,要求实现CalculateTest类和CarTest类的套件测试
套件测试代码需要紧靠SuiteTest这个类,不能有换行
*/
//**************************************************************
public class SuiteTest {
}
评测说明
本关卡的测试文件是TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。
具体测试过程如下:
1.平台自动编译生成TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。
预期输入: 预期输出:true
友情提示
1.请不要直接println
最终输出,否则平台发现此类情况后,将一律扣掉本关经验值,并且追加处罚措施。
2.学员答题时请尽量手敲代码,请勿从实训讲解代码片段中复制代码段粘贴到答题区域作答,复制的内容会保留一些格式和字符,导致编译失败。
开始你的任务吧,祝你成功!
package step3;
import static org.junit.Assert.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import step3.Calculate;
import step3.CalculateTest;
import step3.Car;
import step3.CarTest;
/*
请在星号后加两行注解,要求实现CalculateTest类和CarTest类的套件测试
套件测试代码需要紧靠SuiteTest这个类,不能有换行
*/
//**************************************************************
@RunWith(Suite.class)
@Suite.SuiteClasses({ CalculateTest.class, CarTest.class, RectangleTest.class })
public class SuiteTest {
}
第4关:命令行下进行Junit测试
100
- 任务要求
- 参考答案
- 评论11
任务描述
补全TestRunner.java
中的代码,如果测试类JunitSubTest.java
中的测试都通过,则main
函数会打印true。
环境配置
环境配置:Linux主机+JDK 1.8+Junit 4.12。
首先确保自己在linux主机装好了java环境,配置好环境变量。
然后下载两个jar包:
junit 4.12 :Release JUnit 4.12 · junit-team/junit4 · GitHub
hamcrest-core-1.3.jar : http://central.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
让后把这两个包放到jdk安装的lib目录下,本机的JDK安装目录如下:
/home/soft/jdk1.8.0_111/lib# ls
amd64 hamcrest-core-1.3.jar jexec packager.jar
ant-javafx.jar ir.idl junit-4.12.jar sa-jdi.jar
ct.sym javafx-mx.jar missioncontrol tools.jar
dt.jar jconsole.jar orb.idl
然后修改本机环境变量,
vim ~/.bashrc
修改成如下:
export JAVA_HOME=/home/soft/jdk1.8.0_111
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/junit-4.12.jar:$JAVA_HOME/lib/hamcrest-core-1.3.jar:$CLASSPATH
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
这里着重看下CLASSPATH,JAVA_HOME和PATH如果设置过,就不用修改了。
然后source ~/.bashrc
让环境变量生效。
新建两个java文件:Calculate.java和CalculateTest.java。
//Calculate.java
package com.trustie.junitest;
public class Calculate {
public int sum(int var1, int var2) {
System.out.println("相加的值是: " + var1 + " + " + var2);
return var1 + var2;
}
public static void main(String[] args) {
System.out.println("hh");
}
}
//CalculateTest.java
package com.trustie.test;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import com.trustie.junitest.Calculate;
public class CalculateTest {
Calculate calculation = new Calculate();
int sum = calculation.sum(2, 5);
int testSum = 7;
@Test
public void testSum() {
System.out.println("@Test sum(): " + sum + " = " + testSum);
assertEquals(sum, testSum);
}
}
然后编译执行:
javac -d . Calculate.java
javac -d . CalculateTest.java
java org.junit.runner.JUnitCore com.trustie.test.CalculateTest
就可以看到如下打印:
JUnit version 4.12
相加的值是: 2 + 5
.@Test sum(): 7 = 7
Time: 0.003
OK (1 test)
至此,Junit环境配置成功,可以在本机命令行下运行Junit测试。
其实在命令行中运行JUnit测试,使用了org.junit.runner.JUnitCore类。 这个类提供了runClasses()方法,它允许运行一个或多个测试类。runClasses()方法返回类型是org.junit.runner.Result对象类型。 这个对象可以被用来收集关于测试信息。此外,如果有一个失败的测试,可以用org.junit.runner.notification.Failure对象保存失败测试的描述。
代码示例
之前各个关卡中的TestRunner.java
我们现在揭开谜底吧:
//TestRunner.java
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(Test.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
如果你的测试类Test.java
中所有测试都通过,以上代码会打印true。
本关任务
补全TestRunner.java
中的代码,如果测试类JunitSubTest.java
中的测试都通过,则main
函数会打印true。
本关涉及的代码文件TestRunner.java
的代码如下:
package step4;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
//请在Begin/End内加一行代码,要求如果测试类JunitSubTest.java中的测试都通过,则main函数会打印true
/******************************Begin**************************************************/
/******************************End****************************************************/
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
评测说明
本关卡的测试文件是TestRunner.java
,用于验证学员的Junit测试代码是否正确。
具体测试过程如下:
1.平台自动编译生成TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。
预期输入: 预期输出:true
友情提示
1.请不要直接println
最终输出,否则平台发现此类情况后,将一律扣掉本关经验值,并且追加处罚措施。
2.学员答题时请尽量手敲代码,请勿从实训讲解代码片段中复制代码段粘贴到答题区域作答,复制的内容会保留一些格式和字符,导致编译失败。
开始你的任务吧,祝你成功!
package step4;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
//请在Begin/End内加一行代码,要求如果测试类JunitSubTest.java中的测试都通过,则main函数会打印true
/******************************Begin**************************************************/
Result result = JUnitCore.runClasses(JunitSubTest.class);
/******************************End****************************************************/
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}