任务描述
请学员写一个名为
testSub()
的测试函数,来测试给定的减法函数是否正确。相关知识
Junit编写原则
1、简化测试的编写,这种简化包括测试框架的学习和实际测试单元的编写。 2、测试单元保持持久性。 3、利用既有的测试来编写相关的测试。
Junit特征
1、使用断言方法判断期望值和实际值差异,返回Boolean值。
2、测试驱动设备使用共同的初始化变量或者实例。
3、测试包结构便于组织和集成运行。
4、支持图形交互模式和文本交互模式。
Junit框架的组成
1、测试用例(
TestCase
):对测试目标进行测试的方法与过程的集合2、测试包(
TestSuite
):测试用例的集合,可容纳多个测试用例(TestCase
)。3、测试结果(
TestResult
):测试结果的描述与记录。4、测试监听(
TestListener
):测试过程中事件的监听者。5、测试失败元素(
TestFailure
):每一个测试方法所发生的与预期不一致状况的描述。6、测试框架出错异常(
AssertionFailedError
):junit
执行测试时所抛出的异常。Junit作用介绍
通常我们写完代码想要测试这段代码的正确性,那么必须新建一个类,然后创建一个
main()
方法,之后再编写测试代码。如果需要测试的代码很多呢?那么要么就会建很多main()
方法来测试,要么将其全部写在一个main()
方法里面。这也会大大的增加测试的复杂度,降低程序员的测试积极性。而 Junit 能很好的解决这个问题,简化单元测试,写一点测一点,在之后的代码改动中如果发现问题可以较快的追踪到问题的原因,减小回归错误的纠错难度。如何编写Junit测试
首先,我们将介绍一个测试类:
Calculate.java
//Calculate.java package com.trustie.junitest; public class Calculate { public int sum(int var1, int var2) { return var1 + var2; } }
在上面的代码中,我们可以看到,
Calculate
类有一个公共的方法sum(), 它接收输入两个整数,将它们相加并返回结果。在这里,我们将测试这个方法。为了这个目的,我们将创建另一个类及其方法,将测试之前的类(在此情况下,我们只有一个方法进行测试)中的方法,这是使用的最常见的方式。当然,如果一个方法非常复杂且要扩展,我们可以用多个试验方法来对其进行测试。创建测试用例的详细信息将显示在下面的部分。下面,有一个类是:CalculateTest.java
,它具有我们的测试类的角色的代码:// CalculateTest.java package com.trustie.test; import org.junit.Test; import static org.junit.Assert.assertEquals; import com.trustie.junitest.Calculate; public class CalculateTest { // 创建一个Calculate对象 Calculate calculation = new Calculate(); // 调用sum方法计算2和5的和,并将结果赋值给变量sum int sum = calculation.sum(2, 5); // 定义一个预期的和值 int testSum = 7; // 使用@Test注解标记测试方法 @Test public void testSum() { // 使用assertEquals方法比较实际计算结果和预期结果是否相等 assertEquals(sum, testSum); } }
先来解释一下上面的代码。首先,我们可以看到,有一个@Test的注解在 testSum()方法的上方。 这个注释指示该方法它所附着的代码可以做为一个测试用例。因此,testSum()方法将用于测试公开方法 sum() 。 我们再观察一个方法 assertEquals(sum, testsum)。assertEquals ([String message], object expected, object actual)
方法持有两个对象作为输入,并断言这两个对象相等。然后在Bash执行:
// 编译Calculate.java文件,生成字节码文件 javac -d . Calculate.java // 编译CalculateTest.java文件,生成字节码文件 javac -d . CalculateTest.java // 运行CalculateTest测试类,使用JUnit框架进行单元测试 java org.junit.runner.JUnitCore com.trustie.test.CalculateTest
就可以看到:
JUnit version 4.12 . Time: 0.003 OK (1 test)
这里首先打印出了JUnit版本号,然后输出了耗时和测试结果。在这里,我们的测试结果是OK,证明测试通过,原函数功能正确。
编程要求
本关的编程任务是在
JunitSubTest.java
中的补全测试函数testSub()
,具体要求:用sub
和testSub
作为参数,来验证JunitSub.java
中sub
函数是否正确的是否正确。本关涉及的代码文件
JunitSub.java
的代码如下:package step1; public class JunitSub { public int sub(int var1, int var2) { return var1 - var2; } }
本关涉及的代码文件JunitSubTest.java的代码如下:package step1; import org.junit.Test; import static org.junit.Assert.assertEquals; import step1.JunitSub; public class JunitSubTest { //引入JunitSub对象 JunitSub js = new JunitSub(); int sub = js.sub(5,2); int testSub = 3; /* 请在下面的Begin/End内写一个测试函数, 来验证JunitSub中的sub函数编写是否正确 */ /***********************Begin**************************/ /************************End***************************/ }
评测说明
本关卡的测试文件是
TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。具体测试过程如下:
1.平台自动编译生成
TestRunner.exe
;2.平台运行
TestRunner.exe
;3.获取
TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。预期输入: 预期输出:
true
友情提示
1.请不要直接
println
最终输出,否则平台发现此类情况后,将一律扣掉本关经验值,并且追加处罚措施。2.学员答题时请尽量手敲代码,请勿从实训讲解代码片段中复制代码段粘贴到答题区域作答,复制的内容会保留一些格式和字符,导致编译失败。
开始你的任务吧,祝你成功!
package step1;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import step1.JunitSub;
public class JunitSubTest {
//引入JunitSub对象
JunitSub js = new JunitSub();
int sub = js.sub(5,2);
int testSub = 3;
/*
请在下面的Begin/End内写一个测试函数,
来验证JunitSub中的sub函数编写是否正确
*/
/***********************Begin**************************/
@Test
public void testSubFunction() {
assertEquals(testSub, sub);
}
/************************End***************************/
}
相关知识
Junit注解
Java注解((Annotation)的使用方法是"@ + 注解名" 。借助注解,我们可以在编程中通过简单的注解来实现一些功能。在junit中常用的注解有
@Test、@Ignore、@BeforeClass、@AfterClass、@Before、@After
下表列出了这些注释的概括:具体解释如下:
1、
@Test
,表明此方法为测试方法。2、
@Before
,用此注解修饰的方法在每个test方法运行前执行3、
@BeforeClass
,用此注解修饰的方法将在所有方法运行前被执行,是一个static方法,只执行一次。4、
@After
,用此注解修饰的方法在每个test方法运行后执行5、
@AfterClass
,用此注解修饰的方法将在所有方法运行后被执行,也是一个static方法,只执行一次。6、
@Ignore
,用此注解修饰的方法会被Junit忽略。代码示例
这里新建一个
JunitAnnotation.java
,把上面所讲的注解全部加到某个测试函数之前,这些注解的作用一目了然:// 导入JUnit相关的类和静态方法 import static org.junit.Assert.*; import java.util.*; import org.junit.*; // 定义一个名为AnnotationsTest的公共类,用于进行单元测试 public class AnnotationsTest { // 定义一个私有的ArrayList变量testList,用于存储测试数据 private ArrayList testList; // 使用@BeforeClass注解标记的方法,在所有的测试方法执行前只执行一次 @BeforeClass public static void onceExecutedBeforeAll() { // 输出提示信息 System.out.println("@BeforeClass: onceExecutedBeforeAll"); } // 使用@Before注解标记的方法,在每个测试方法执行前都会执行一次 @Before public void executedBeforeEach() { // 初始化testList为一个新的ArrayList对象 testList = new ArrayList(); // 输出提示信息 System.out.println("@Before: executedBeforeEach"); } // 使用@AfterClass注解标记的方法,在所有的测试方法执行后只执行一次 @AfterClass public static void onceExecutedAfterAll() { // 输出提示信息 System.out.println("@AfterClass: onceExecutedAfterAll"); } // 使用@After注解标记的方法,在每个测试方法执行后都会执行一次 @After public void executedAfterEach() { // 清空testList中的所有元素 testList.clear(); // 输出提示信息 System.out.println("@After: executedAfterEach"); } // 使用@Test注解标记的方法,表示这是一个测试方法 @Test public void EmptyCollection() { // 断言testList为空,如果为空则测试通过,否则测试失败 assertTrue(testList.isEmpty()); // 输出提示信息 System.out.println("@Test: EmptyArrayList"); } // 使用@Test注解标记的方法,表示这是一个测试方法 @Test public void OneItemCollection() { // 向testList中添加一个元素 testList.add("oneItem"); // 断言testList的大小为1,如果大小为1则测试通过,否则测试失败 assertEquals(1, testList.size()); // 输出提示信息 System.out.println("@Test: OneItemArrayList"); } // 使用@Ignore注解标记的方法,表示这个测试方法被忽略,不会被执行 @Ignore public void executionIgnored() { // 输出提示信息 System.out.println("@Ignore: This execution is ignored"); } }
如果我们运行上面的测试,控制台输出将是下面:
@BeforeClass: onceExecutedBeforeAll @Before: executedBeforeEach @Test: EmptyArrayList @After: executedAfterEach @Before: executedBeforeEach @Test: OneItemArrayList @After: executedAfterEach @AfterClass: onceExecutedAfterAll
// 在所有测试方法执行前只执行一次的方法 @BeforeClass public void onceExecutedBeforeAll() { // ... } // 在每个测试方法执行前都会执行的方法 @Before public void executedBeforeEach() { // ... } // 测试方法1:空的ArrayList @Test public void EmptyArrayList() { // ... } // 在每个测试方法执行后都会执行的方法 @After public void executedAfterEach() { // ... } // 在每个测试方法执行前都会执行的方法(重复) @Before public void executedBeforeEach() { // ... } // 测试方法2:只有一个元素的ArrayList @Test public void OneItemArrayList() { // ... } // 在所有测试方法执行后只执行一次的方法 @AfterClass public void onceExecutedAfterAll() { // ... }
编程要求
本关的编程任务是在
JunitAnnotation.java
中修改测试函数对应的注解,使得原代码输出结果变为逆序。本关涉及的代码文件
JunitAnnotation.java
的代码如下:见下答案版
评测说明
本关卡的测试文件是
TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。具体测试过程如下:
1.平台自动编译生成
TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。预期输入: 预期输出:
in after class in after in test in before in before class true
package step2;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
public class JunitAnnotation {
/*
*以下Junit测试程序的输出结果为:
*in before class
*in before
*in test
*in after
*in after class
*请修改下面Begin/End内各个测试函数的注解,使输出结果逆序
*/
/***********************Begin**************************/
@BeforeClass
public static void afterClass() {
System.out.println("in after class");
}
//execute after test
@Before
public void after() {
System.out.println("in after");
}
//execute before test
@After
public void before() {
System.out.println("in before");
}
//execute after class
@AfterClass
public static void beforeClass() {
System.out.println("in before class");
}
//test case
@Test
public void test() {
System.out.println("in test");
}
//execute before class
/************************End***************************/
}
任务描述
给定一个断言测试类
AssertionsTest.java
,请按要求补全代码,写出相应的断言测试。相关知识
Junit断言
Junit的断言方法允许检查测试方法的期望结果值和真实返回值。Junit的org.junit.Assert类提供了各种断言方法来写junit测试,这些方法被用来检查方法的真实结果值和期望值。
代码示例
创建一个文件名为 TestAssertions.java 的类,如下:
package com.trustie.junittest; import org.junit.Test; import static org.junit.Assert.*; public class TestAssertions { @Test public void testAssertions() { //测试数据 String str1 = new String ("abc"); String str2 = new String ("abc"); String str3 = null; String str4 = "abc"; String str5 = "abc"; int val1 = 5; int val2 = 6; String[] expectedArray = {"one", "two", "three"}; String[] resultArray = {"one", "two", "three"}; //检查两个对象是否相等 assertEquals(str1, str2); //检查条件是否为真 assertTrue (val1 < val2); //检查条件是否为假 assertFalse(val1 > val2); //检查对象不为空 assertNotNull(str1); //检查对象为空 assertNull(str3); //检查两个对象引用是否指向同一个对象 assertSame(str4,str5); //检查两个对象引用是否不指向同一个对象 assertNotSame(str1,str3); //检查两个数组是否相等 assertArrayEquals(expectedArray, resultArray); } }
在以上类中我们可以看到,这些断言方法是可以工作的。
assertEquals() 如果比较的两个对象是相等的,此方法将正常返回;否则失败显示在JUnit的窗口测试将中止。
assertSame() 和 assertNotSame() 方法测试两个对象引用指向完全相同的对象。
assertNull() 和 assertNotNull() 方法测试一个变量是否为空或不为空(null)。
assertTrue() 和 assertFalse() 方法测试if条件或变量是true还是false。
assertArrayEquals() 将比较两个数组,如果它们相等,则该方法将继续进行不会发出错误。否则失败将显示在JUnit窗口和中止测试。
编程要求
本关的编程任务是给定一个断言测试类
AssertionsTest.java
,请按要求补全代码,写出相应的断言测试。具体要求如下:
1.断言obj1和obj2相等;
2.断言obj3和obj4指向完全相同的对象;
3.断言obj2和obj4指向不同的对象;
4.断言obj1对象不为空;
5.断言obj5对象为空;
6.断言var1小于var2;
7.断言arithmetic1和arithmetic2两个数组相等。
本关涉及的代码文件
AssertionsTest.java
的代码如下:见下
评测说明
本关卡的测试文件是
TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。具体测试过程如下:
1.平台自动编译生成
TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。预期输入: 预期输出:
true
package step3;
import static org.junit.Assert.*;
import org.junit.Test;
public class AssertionsTest {
String obj1 = "junit";
String obj2 = "junit";
String obj3 = "test";
String obj4 = "test";
String obj5 = null;
int var1 = 1;
int var2 = 2;
int[] arithmetic1 = { 1, 2, 3 };
int[] arithmetic2 = { 1, 2, 3 };
@Test
public void test() {
//请在下面的Begin/End内写添加断言测试的代码,不要改动其他地方的代码
/***********************Begin**************************/
assertEquals(obj1,obj2); // 判断两个字符串是否相等
assertSame(obj3,obj4); // 判断两个对象引用是否指向同一个对象
assertNotSame(obj2,obj4); // 判断两个对象引用是否不指向同一个对象
assertNotNull(obj1); // 判断对象引用是否不为空
assertNull(obj5); // 判断对象引用是否为空
assertTrue (var1 < var2); // 判断一个整数是否小于另一个整数
assertArrayEquals(arithmetic1,arithmetic2); // 判断两个数组是否相等
/************************End***************************/
}
}
任务描述
要求学员实现一个Junit时间测试:超过1000毫秒未执行结束就判定测试未通过。
相关知识
Junit时间测试
Junit 提供了一个暂停的方便选项。如果一个测试用例比起指定的毫秒数花费了更多的时间,那么Junit 将自动将它标记为失败。timeout 参数和
@Test
注释一起使用。现在让我们看看活动中的@Test(timeout)
。代码示例
import org.junit.*; /** * JUnit TimeOut Test */ public class JunitTest { @Test(timeout = 50000) //单位是毫秒 public void infinity() { while (true); // 无限循环,导致测试超时 } }
在上面的例子中,infinity() 方法将不会返回,因此JUnit引擎将其标记为失败,并抛出一个异常。
java.lang.Exception:test timed out after 50000 milliseconds
编程要求
本关的编程任务是在
TestTimeOut.java
中实现一个Junit时间测试,超过1000毫秒未执行结束就判定测试未通过。本关涉及的代码文件
TestTimeOut.java
的代码如下:见下述答案
评测说明
本关卡的测试文件是
TestRunner.java
,该文件进行了函数封装且学员不可见,用于验证学员的Junit测试代码是否正确。具体测试过程如下:
1.平台自动编译生成
TestRunner.exe
; 2.平台运行TestRunner.exe
; 3.获取TestRunner.exe
输出,并将其输出与预期输出对比:如果一致则测试通过,否则测试失败。预期输入: 预期输出:
test(step4.TestTimeOut): test timed out after 1000 milliseconds false
package step4;
import org.junit.Test;
public class TestTimeOut {
//请在下面的Begin/End内补全test()超时测试函数,要求如果超过1000毫秒执行未结束,就判定测试未通过
/***********************Begin**************************/
@Test(timeout = 1000)
public void test() {
while(true){}
}
/************************End***************************/
}