测试应用程序是开发周期中不可缺乏的一部分,而且编写和维护测试单元有利于确保源代码中的方法能正常运行。IDE 集成了对 JUnit 单元测试框架的支持,它容许您快速和轻松地建立 JUnit 测试和测试套件。html
在本教程中,您将为 Java 类库项目建立简单的 JUnit 3 和 JUnit 4 单元测试及测试套件。教程的第 1 部分演示如何在 JUnit 3 中建立测试。第 2 部分演示如何使用 JUnit 标注在 JUnit 4 中建立相同的测试。这两个部分建立的测试是相同的,所以没有必要同时完成二者,可是查看测试的两种编写方法能够帮助您了解 JUnit 4 中引入的一些变化。。java
要完成本教程,您首先须要建立一个名称为 JUnit-Sample 的 Java 类库项目。建立项目后,您须要将样例项目 JUnitSampleSol 中的两个类复制到项目 JUnit-Sample 中。框架
1. 从主菜单选择“文件”>“新建项目”。 编辑器
2. 从“Java”类别中选择“Java 类库”并单击“下一步”。 ide
3. 键入 JUnit-Sample 做为项目名称并设置项目位置。 函数
4. 取消选中“使用专用文件夹存储库”选项(若是该选项处于选中状态)。 工具
在本教程中,咱们将项目库复制到一个专门的文件夹中,由于须要与其余用户或项目共享库。此选项对于 NetBeans IDE 6.0 不可用。单元测试
单击“下一步”。
5. 单击“完成”。
建立项目以后,若是您查看“项目”窗口中的“测试库”节点,您会看到项目包含 JUnit 3 和 JUnit 4 库。缺省状况下,IDE 会在新项目中添加这两个库。第一次建立 JUnit 测试时,IDE会提示您选择一个版本,而后删除不须要的库。
· 经过执行如下步骤从 Kenai 签出项目源代码:
1. 从主菜单中选择“团队开发”> "Kenai" >“从 Kenai 中获取源代码”。
或者,也能够选择“打开 Kenai 项目”以将项目添加到 "Kenai" 控制板,而后获取项目源代码。
2. 在“从 Kenai 中获取源代码”对话框中,单击“Kenai 资源库”旁边的“浏览”以打开“浏览 Kenai 项目”对话框,从而找到 Kenai 资源库。
3. 输入 NetBeans IDE Samples Catalog 以进行搜索。
4. 选择 "NetBeans IDE Samples Catalog"(NetBeans IDE 样例目录)并单击“肯定”。
5. 单击“要获取的文件夹”旁边的“浏览”以指定要获取的文件夹,而后选择 "NB67" / "Java" / "JUnitSampleSol"。单击“肯定”。
6. 指定用于存储源代码的本地文件夹(本地文件夹必须为空)。
7. 单击“从 Kenai 中获取”。
单击“从 Kenai 中获取”后,IDE 会将本地文件夹初始化为 Subversion 资源库,并签出项目源代码。
8. 在完成签出操做后将会显示一个对话框,在该对话框中单击“打开项目”。
在本练习中,您须要将样例项目 JUnitSampleSol 中的文件 Utils.java 和 Vectors.java 复制到您建立的类库项目中。
1. 在“项目”窗口中,右键单击 JUnit-Sample 项目的“源包”节点,而后从弹出式菜单中选择“新建”>“Java 包”。
2. 键入 sample 做为包名。单击“完成”。
3. 在 IDE 中打开 JUnitSampleSol 项目,而后在“项目”窗口中展开该项目节点。
4. 将 JUnitSampleSol 项目 Source Packages 文件夹中的 Utils.java 和 Vectors.java 复制到 JUnit-Sample 的 sample 源包中。
若是您查看类的源代码,您能够看到 Utils.java 包含三个方法(computeFactorial、concatWords 和 normalizeWord),而且 Vectors.java 包含两个方法(equals 和 scalarMultiplication)。接下来,为各种建立测试类并为这些方法编写一些测试用例。
在本节中,您将为 Vectors.java 和 Utils.java 类建立基本的 JUnit 3 单元测试。您将使用 IDE 根据您项目中的类来建立框架测试类。而后,您将修改生成的测试方法并添加新测试方法。
第一次使用 IDE 在项目中建立测试时,IDE 将提示您选择一个 JUnit 版本。您选择的版本将成为缺省的 JUnit 版本,而且 IDE 将为该版本生成全部后续测试和测试套件。
在本练习中,您将为 Vectors.java 建立一个 JUnit 测试框架。
1. 右键单击 Vectors.java 并选择“工具”>“建立 JUnit 测试”。
2. 在“选择 JUnit 版本”对话框中,选择“JUnit 3.x”。
当您选择 JUnit 3.x 时,IDE 将从项目中删除 JUnit 4 库。
3. 在“建立测试”对话框中,将测试类的名称修改成 VectorsJUnit3Test。
更改测试类的名称以后,您将看到一个关于修更名称的警告。缺省名称基于要测试的类名,并在该名称后面附加单词 Test。举例来讲,对于 MyClass.java 类,测试类的缺省名称为 MyClassTest.java。一般,最好是保留缺省名称,可是在教程中您将更改该名称,由于您还将在相同的包中建立 JUnit 4 测试,而且测试类的名称必须是唯一的。
4. 取消选中“测试初始化函数”和“测试释放方法”单击“肯定”。
单击肯定以后,IDE 将在 sample 测试包目录中建立一个 JUnit 测试框架。
项目须要一个目录供测试包建立测试。测试包目录的缺省位置为项目的根目录,可是根据项目的不一样,您能够在项目的“属性”对话框中为目录指定不一样的位置。
在编辑器中查看生成的测试类 VectorsJUnit3Test.java,您能够看到 IDE 为 equal 和 scalarMultiplication 方法生成了如下具有测试方法的测试类。
public class VectorsJUnit3Test extends TestCase {
/**
* Test of equal method, of class Vectors.
*/
public void testEqual() {
System.out.println("equal");
int[] a = null;
int[] b = null;
boolean expResult = false;
boolean result = Vectors.equal(a, b);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
/**
* Test of scalarMultiplication method, of class Vectors.
*/
public void testScalarMultiplication() {
System.out.println("scalarMultiplication");
int[] a = null;
int[] b = null;
int expResult = 0;
int result = Vectors.scalarMultiplication(a, b);
assertEquals(expResult, result);
// TODO review the generated test code and remove the default call to fail.
fail("The test case is a prototype.");
}
}
各生成测试的方法主体是做为指导单独提供的,所以须要将它们修改成实际的测试用例。若是您不须要生成的代码,能够在“建立测试”对话框中取消选中“缺省方法主体”。
IDE 生成测试方法的名称时,各方法名称将前面附加一个 test,由于 JUnit 3 使用命名约定和反射来标识测试。要标识测试方法,各测试方法须要遵循 test<NAME> 语法。
在 JUnit 4 中,再也不须要使用这种测试方法命名语法,由于您可使用标注来标识测试方法,而且测试类再也不须要扩展 TestCase。
在本练习中,您将修改生成的方法以实现测试功能,并修改缺省的输出消息。您不须要修改运行测试的输出消息,可是您可能但愿修改输出来帮助标识显示在“JUnit 测试结果”输出窗口中的结果。
1. 在编辑器中打开 VectorsJUnit3Test.java。
2. 修改 testScalarMultiplication 的测试框架,方法是修改 println 的值并删除生成的变量。如今,测试方法应以下所示(粗体为更改部分):
3. public void testScalarMultiplication() {
4. System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");
5. assertEquals(expResult, result);
}
6. 如今,添加一些断言来测试方法。
7. public void testScalarMultiplication() {
8. System.out.println("* VectorsJUnit3Test: testScalarMultiplication()");
9. assertEquals( 0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));
10. assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));
11. assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));
12. assertEquals( 0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));
13. assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));
}
该测试方法使用 JUnit assertEquals 方法。要使用断言,您须要提供输入变量和预期的结果。在运行被测试的方法时,要经过测试,测试方法必须根据提供的变量成功返回全部预期的结果。您应该添加足够数量的断言来涵盖各类可能的排列。
14. 修改 testEqual 的测试框架:删除生成的方法主体并添加如下 println。
System.out.println("* VectorsJUnit3Test: testEqual()");
如今,测试方法应以下所示:
public void testEqual() {
System.out.println("* VectorsJUnit3Test: testEqual()");
}
15. 修改 testEqual 方法:添加如下断言(显示为粗体)。
16.public void testEqual() {
17. System.out.println("* VectorsJUnit3Test: testEqual()");
18. assertTrue(Vectors.equal(new int[] {}, new int[] {}));
19. assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));
20. assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));
21. assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));
22. assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));
23.
24. assertFalse(Vectors.equal(new int[] {}, new int[] {0}));
25. assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));
26. assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));
27. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));
28. assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));
29. assertFalse(Vectors.equal(new int[] {0}, new int[] {}));
30.
31. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));
32. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));
33. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));
34. assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));
}
此方法使用 JUnit assertTrue 和 assertFalse 方法来测试各类可能的结果。要经过此方法的测试,assertTrue 必须所有为 true,而且 assertFalse 必须所有为 false。
如今,你能够为 Utils.java 建立测试框架。在上一练习中建立了测试以后,IDE 会提示您选择 JUnit 的版本。但此次,并无提示要求您选择版本。
1. 右键单击 Utils.java 并选择“工具”>“建立 JUnit 测试”。
2. 在对话框中,选中“测试初始化函数”和“测试释放方法”(若是为未选中状态)。
3. 在“建立测试”对话框中,将测试类的名称修改成 UtilsJUnit3Test。单击“肯定”。
单击“肯定”以后,IDE 将在“测试包”>"samples" 目录中建立测试文件UtilsJUnit3Test.java。能够看到,除了为 Utils.java 中的方法建立 testComputeFactorial、testConcatWords 和 testNormalizeWord 测试框架以外,IDE 还建立了测试初始化函数方法 setUp 和测试释放方法 tearDown。
在本练习中,您将添加一些测试用例来演示一些经常使用的 JUnit 测试元素。您还将在方法中添加 println,由于一些方法缺省不打印任何输出。经过在方法中添加 println,您能够稍后在 JUnit 测试结果窗口中查看方法是否已经运行以及它们运行的顺序。
setUp 和 tearDown 方法用于初始化和释放测试条件。您不须要使用 setUp 和 tearDown 方法来测试 Utils.java,可是此处演示了它们的运行原理。
setUp 方法是一个测试初始化方法,它在测试类中的各测试用例以前运行。运行测试不须要测试初始化方法,可是,若是您须要在运行测试以前初始化一些变量,则可使用测试初始化方法。
setUp 方法是一个测试释放方法,它在测试类中的各测试用例以后运行。运行测试不须要测试释放方法,可是,您可能须要使用释放方法来清理运行测试用例时所需的任何数据。
1. 执行如下更改(显示为粗体),在各方法中添加一个 println。
2. @Override
3. protected void setUp() throws Exception {
4. super.setUp();
5. System.out.println("* UtilsJUnit3Test: setUp() method");
6. }
7.
8. @Override
9. protected void tearDown() throws Exception {
10. super.tearDown();
11. System.out.println("* UtilsJUnit3Test: tearDown() method");
}
运行测试时,各方法的 println 文本将出如今“JUnit 测试结果”输出窗口中。若是您没有添加 println,则不会在输出中显示方法已经运行。
这个简单的测试用例将测试 concatWords 方法。您没有使用生成的 testConcatWords 测试方法,而是使用新的 testHelloWorld 测试方法,该方法使用单个简单的断言来测试方法是否正确地链接了字符串。测试用例中的 assertEquals 将使用 assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) 语法来测试预期结果是否等于实际结果。在本例中,若是 concatWords 方法的输入为 "Hello"、", ","world" 和 "!",则预期结果应该等于 "Hello, world!"。
1. 删除生成的测试方法 testConcatWords。
2. 添加如下方法来测试concatWords 方法。
3. public void testHelloWorld() {
4. assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
}
5. 添加一个 println 语句,用于在“JUnit 测试结果”窗口中显示关于测试的文本。
6. public void testHelloWorld() {
7. System.out.println("* UtilsJUnit3Test: test method 1 - testHelloWorld()");
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
此测试演示如何检查方法的完成是否花费了过长的时间。若是方法花费了过长的时间,则测试线程将中断并致使测试失败。您能够在测试中指定时间限制。
测试方法将调用 Utils.java 中的 computeFactorial 方法。您能够假定 computeFactorial 方法是正确的,可是在本例中,您但愿测试计算是不是在 1000 毫秒以内完成的。computeFactorial 线程和测试线程是在相同时间启动的。测试线程将在 1000 毫秒事后中止并抛出一个 TimeoutException 异常,除非 computeFactorial 线程先于它完成。您将添加一条消息,这样在抛出 TimeoutException 时会显示该消息。
1. 删除生成的测试方法 testComputeFactorial。
2. 添加 testWithTimeout 方法,该方法用于计算随机生成数的阶乘。
3. public void testWithTimeout() throws InterruptedException, TimeoutException {
4. final int factorialOf = 1 + (int) (30000 * Math.random());
5. System.out.println("computing " + factorialOf + '!');
6.
7. Thread testThread = new Thread() {
8. public void run() {
9. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
10. }
11. };
}
12. 修复导入,以导入 java.util.concurrent.TimeoutException。
13. 在方法中添加如下代码(显示为粗体),其做用是当测试任务的执行时间过长时中断线程并显示一条消息。
14. Thread testThread = new Thread() {
15. public void run() {
16. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
17. }
18. };
19.
20. testThread.start();
21. Thread.sleep(1000);
22. testThread.interrupt();
23.
24. if (testThread.isInterrupted()) {
25. throw new TimeoutException("the test took too long to complete");
26. }
}
在抛出超时以前,您能够经过修改 Thread.sleep 代码行来更改毫秒数。
27. 添加如下 println(显示为粗体),用于在“JUnit 测试结果”窗口中输出关于测试的文本。
28.public void testWithTimeout() throws InterruptedException, TimeoutException {
29. System.out.println("* UtilsJUnit3Test: test method 2 - testWithTimeout()");
30. final int factorialOf = 1 + (int) (30000 * Math.random());
31. System.out.println("computing " + factorialOf + '!');
此测试演示如何针对预期异常进行测试。若是未抛出指定的预期异常,则会致使方法失败。在本例中,您将测试当输入变量为负数时(-5),computeFactorial 方法是否会抛出 IllegalArgumentException。
1. 添加如下 testExpectedException 方法,它将以输入 -5 调用 computeFactorial 方法。
2. public void testExpectedException() {
3. try {
4. final int factorialOf = -5;
5. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
6. fail("IllegalArgumentException was expected");
7. } catch (IllegalArgumentException ex) {
8. }
}
9. 添加如下 println(显示为粗体),用于在“JUnit 测试结果”窗口中输出关于测试的文本。
10.public void testExpectedException() {
11. System.out.println("* UtilsJUnit3Test: test method 3 - testExpectedException()");
try {
此测试演示如何临时禁用测试方法。在 JUnit 3 中,若是某个方法名称没有以 test 开头,则它不会被识别为测试方法。在本例中,您将 DISABLED 置于测试方法的名称以前来禁用它。
1. 删除生成的测试方法 testNormalizeWord。
2. 在测试类中添加如下测试方法:
3. public void testTemporarilyDisabled() throws Exception {
4. System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");
5. assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
测试方法 testTemporarilyDisabled 将在您运行测试类时运行。
6. 将 DISABLED_(显示为粗体)置于测试方法的名称以前。
7. public void DISABLED_testTemporarilyDisabled() throws Exception {
8. System.out.println("* UtilsJUnit3Test: test method 4 - checkExpectedException()");
9. assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
如今,您已经编写了测试。接下来,您能够运行测试并在“JUnit 测试结果”窗口中查看测试输出。
运行 JUnit 测试以后,结果将显示在 IDE 的“JUnit 测试结果”窗口中。您能够单独运行 JUnit 测试类,或者也能够从主菜单中选择“运行”>“测试 PROJECT_NAME”来运行项目的全部测试。若是您选择“运行”>“测试”,则 IDE 将运行“测试包”文件夹中的全部测试类。要运行单独的测试类,右键单击“测试包”节点下的测试类并选择“运行文件”。
· 从主菜单中选择“运行”>“测试项目 (JUnit-Sample)”。
运行测试以后,您将在“JUnit 测试结果”窗口中看到如下结果之一:
在此图像中(单击图像查看大图),您能够看到项目经过了全部测试。左侧窗格显示各测试方法的结果,右侧窗格显示测试输出。若是您查看输出,您能够看到测试运行的顺序。添加到各测试方法中的 println 在输出窗口中输出测试的名称。您还能够看到,在 UtilJUnit3Test 中,setUp 方法在各测试方法以前运行,而 tearDown 方法在各方法以后运行。
在此图像中(单击图像查看大图),您能够看到项目未经过其中一个测试。testTimeout 方法花费了过长的运行时间,而且测试线程被中断,致使测试失败。它花了超过 1000 毫秒来计算出随机生成数(22991)的阶乘。.
建立单元测试类后,下一步将建立测试套件。请参见建立 JUnit 3 测试套件,了解如何以组的方式运行特定的测试,从而避免单独运行各个测试。
在本练习中,您将为 Vectors.java 和 Utils.java 建立 JUnit 4 单元测试。JUnit 4 测试用例与 JUnit 3 测试用例相同,可是您会发现其编写测试的语法更加简单。
您将使用 IDE 根据项目中的类来建立测试框架。第一次使用 IDE 建立测试框架时,IDE 会提示您选择 JUnit 版本。
若是您已经选择了 JUnit 3.x 做为测试缺省版本,则须要将缺省版本更改成 JUnit 4.x。要更改缺省的 JUnit 版本,右键单击“测试库”节点,选择“添加库”并将 JUnit 4 库添加到项目中。建立新测试时,在提示选择 JUnit 版本的窗口中选择 version 4.x。选择 JUnit 4.x 以后,IDE 将删除没必要要的 JUnit 3.x 库。您仍然能够运行 JUnit 3 测试,可是您建立的任何新测试都将使用 JUnit 4。
在本练习中,您将为 Vectors.java 建立 JUnit 测试框架。
1. 右键单击 Vectors.java 并选择“工具”>“建立 JUnit 测试”。
2. 在“选择 JUnit 版本”对话框中,选择“JUnit 4.x”。
选择 JUnit 4.x 以后,IDE 将删除 JUnit 3 库。若是您的项目中有 JUnit 4 库,那么您能够编写和运行 JUnit 3 及 JUnit 4 测试。
3. 在“建立测试”对话框中,将测试类的名称修改成 VectorsJUnit4Test。
更改测试类的名称以后,您将看到一个关于修更名称的警告。缺省名称基于要测试的类名,并在该名称后面附加单词 Test。举例来讲,对于 MyClass.java 类,测试类的缺省名称为 MyClassTest.java。与 JUnit 3 不一样,在 JUnit 4 中,测试不须要以单词 Test 结尾。一般,最好是保留缺省名称,但因为在本教程中您将在相同的包中建立全部 JUnit 4 测试,所以测试类的名称必须是唯一的。
4. 取消选中“测试初始化函数”和“测试释放方法”单击“肯定”。
单击肯定以后,IDE 将在 sample 测试包目录中建立一个 JUnit 测试框架。
项目须要一个目录来保存测试包建立的测试。测试包目录的缺省位置为项目的根目录,可是根据项目的类型不一样,您能够在项目的“属性”对话框中为目录指定不一样的位置。
在编辑器中查看 VectorsJUnit3Test.java,您能够看到 IDE 生成了测试方法 testEqual 和 testScalarMultiplication。在 JUnit 4 中,各测试方法都添加了 @Test 标注。IDE 根据 Vectors.java 中的方法的名称为测试方法生成了名称,可是,不须要将 test 置于测试方法的名称以前。各生成测试方法的缺省主体是做为指导单独提供的,所以须要将它们修改成实际的测试用例。
若是您不须要生成的方法主体,能够在“建立测试”对话框中取消选中“缺省方法主体”。
IDE 还生成了如下测试类初始化函数和释放方法:
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
建立 JUnit 4 测试类时,IDE 会生成缺省的类初始化函数和释放方法。标注 @BeforeClass 和 @AfterClass 用于标记应在测试类以前及以后运行的方法。您能够删除这些方法,由于您在 Vectors.java 测试时不须要它们。
您能够经过在“选项”窗口中配置“JUnit”选项来配置缺省生成的方法。
在本练习中,您将修改生成的各测试方法:使用 JUnit assert 方法来测试方法,并更改测试方法的名称。在 JUnit 4 中,您在命名测试方法时拥有了更好的灵活性,由于测试方法是由 @Test 标注指示的,而且不须要将单词 test 置于测试方法以前。
1. 在编辑器中打开 VectorsJUnit4Test.java。
2. 修改 testScalarMultiplication 的测试框架,方法是修改方法名称、修改 println 的值并删除生成的变量。如今,测试方法应以下所示(粗体为更改部分):
3. @Test
4. public void ScalarMultiplicationCheck() {
5. System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");
6. assertEquals(expResult, result);
}
在编写测试时,不须要更改打印的输出。在本练习中,其做用是可以更加轻松地识别输出窗口中的测试结果。
7. 如今,添加一些断言来测试方法。
8. @Test
9. public void ScalarMultiplicationCheck() {
10. System.out.println("* VectorsJUnit4Test: ScalarMultiplicationCheck()");
11. assertEquals( 0, Vectors.scalarMultiplication(new int[] { 0, 0}, new int[] { 0, 0}));
12. assertEquals( 39, Vectors.scalarMultiplication(new int[] { 3, 4}, new int[] { 5, 6}));
13. assertEquals(-39, Vectors.scalarMultiplication(new int[] {-3, 4}, new int[] { 5,-6}));
14. assertEquals( 0, Vectors.scalarMultiplication(new int[] { 5, 9}, new int[] {-9, 5}));
15. assertEquals(100, Vectors.scalarMultiplication(new int[] { 6, 8}, new int[] { 6, 8}));
}
在此测试方法中,您使用了 JUnit assertEquals 方法。要使用断言,您须要提供输入变量和预期的结果。在运行被测试的方法时,要经过测试,测试方法必须根据提供的变量成功返回全部预期的结果。您应该添加足够数量的断言来涵盖各类可能的排列。
16. 将 testEqual 测试方法的名称更改成 equalsCheck。
17. 修改 equalsCheck 测试方法,删除生成的方法主体并添加如下 println。
System.out.println("* VectorsJUnit4Test: equalsCheck()");
如今,测试方法应以下所示:
@Test
public void equalsCheck() {
System.out.println("* VectorsJUnit4Test: equalsCheck()");
}
18. 修改 equalsCheck 方法:添加如下断言(显示为粗体)。
19.@Test
20.public void equalsCheck() {
21. System.out.println("* VectorsJUnit4Test: equalsCheck()");
22. assertTrue(Vectors.equal(new int[] {}, new int[] {}));
23. assertTrue(Vectors.equal(new int[] {0}, new int[] {0}));
24. assertTrue(Vectors.equal(new int[] {0, 0}, new int[] {0, 0}));
25. assertTrue(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 0}));
26. assertTrue(Vectors.equal(new int[] {5, 6, 7}, new int[] {5, 6, 7}));
27.
28. assertFalse(Vectors.equal(new int[] {}, new int[] {0}));
29. assertFalse(Vectors.equal(new int[] {0}, new int[] {0, 0}));
30. assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0, 0, 0}));
31. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0}));
32. assertFalse(Vectors.equal(new int[] {0, 0}, new int[] {0}));
33. assertFalse(Vectors.equal(new int[] {0}, new int[] {}));
34.
35. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 0, 1}));
36. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {0, 1, 0}));
37. assertFalse(Vectors.equal(new int[] {0, 0, 0}, new int[] {1, 0, 0}));
38. assertFalse(Vectors.equal(new int[] {0, 0, 1}, new int[] {0, 0, 3}));
}
此方法使用 JUnit assertTrue 和 assertFalse 方法来测试各类可能的结果。要经过此方法的测试,assertTrue 必须所有为 true,而且 assertFalse 必须所有为 false。
比较:为 Vectors.java 编写测试方法(JUnit 3)
如今,您将为Utils.java 建立 JUnit 测试方法。在上一练习中建立了测试类以后,IDE 会提示您选择 JUnit 的版本。此次,IDE 并未提示您选择版本,由于您已经选择了 JUnit 版本,而且该版本中已经建立了全部后续 JUnit 测试。
若是您选择 JUnit 4 做为版本,那么仍然能够编写和运行 JUnit 3 测试,可是 IDE 将使用 JUnit 4 模板来生成测试框架。
1. 右键单击 Utils.java 并选择“工具”>“建立 JUnit 测试”。
2. 在对话框中,选中“测试初始化函数”和“测试释放方法”(若是为未选中状态)。
3. 在“建立测试”对话框中,将测试类的名称修改成 UtilsJUnit4Test。单击“肯定”。
单击“肯定”以后,IDE 将在“测试包”>“samples”目录中建立测试文件UtilsJUnit4Test.java。能够看到,IDE 为 Utils.java 中的方法生成了 testComputeFactorial、testConcatWords 和 testNormalizeWord 测试方法。IDE 还为测试和测试类生成了初始化函数和释放方法。
在本练习中,您将添加一些测试用例来演示一些经常使用的 JUnit 测试元素。您还将在方法中添加一个 println,由于一些方法不会在“JUnit 测试结果”窗口中打印任何输出,以表示方法已运行或经过测试。经过在方法中添加 println,您能够了解方法是否已经运行以及它们运行的顺序。
为 Utils.java 建立测试类以后,IDE 将生成标注初始化函数和释放方法。您能够为方法选择任何名称,由于没有既定的命名约定。
您不须要使用初始化函数和释放方法来测试 Utils.java,可是本教程演示了它们的运行原理。
在 JUnit 4 中,您可使用标注来标记如下类型的初始化函数和释放方法。
· 测试类初始化函数。@BeforeClass 标注将方法标记为测试类初始化方法。测试类初始化方法只能运行一次,而且在测试类中的任何其余方法以前运行。举例来讲,您没必要在测试初始化函数中建立数据库链接并在各测试方法以前建立新链接,您能够在运行测试以前使用测试类初始化函数打开链接。而后,您可使用测试类释放方法来关闭链接。
· 测试类释放方法。@AfterClass 标注将方法标记为测试类释放方法。测试类释放方法只能运行一次,而且在测试类中的任何其余方法完成以后运行。
· 测试初始化函数。@BeforeClass 标注将方法标记为测试初始化方法。测试初始化方法在测试类中的各测试用例以前运行。运行测试不须要测试初始化方法,可是,若是您须要在运行测试以前初始化一些变量,则可使用测试初始化方法。
· 测试释放方法。@After 标注将方法标记为测试释放方法。测试释放方法在测试类中的各测试用例以后运行。运行测试不须要测试释放方法,可是,您可能须要使用释放方法来清理运行测试用例时所需的任何数据。
执行如下更改(显示为粗体),在初始化函数和释放方法中添加一个 println。
@BeforeClass
public static void setUpClass() throws Exception {
System.out.println("* UtilsJUnit4Test: @BeforeClass method");
}
@AfterClass
public static void tearDownClass() throws Exception {
System.out.println("* UtilsJUnit4Test: @AfterClass method");
}
@Before
public void setUp() {
System.out.println("* UtilsJUnit4Test: @Before method");
}
@After
public void tearDown() {
System.out.println("* UtilsJUnit4Test: @After method");
}
比较:测试初始化函数和释放方法(JUnit 3)
运行测试类时,您添加的 println 文本将显示在“JUnit 测试结果”窗口的输出窗格中。若是您没有添加 println,则不会在输出中显示初始化函数和释放方法已经运行。
这个简单的测试用例将测试 concatWords 方法。您没有使用生成的 testConcatWords 测试方法,而是使用新的 helloWorldCheck 测试方法,该方法使用单个简单的断言来测试方法是否正确地链接了字符串。测试用例中的 assertEquals 将使用 assertEquals(EXPECTED_RESULT, ACTUAL_RESULT) 语法来测试预期结果是否等于实际结果。在本例中,若是 concatWords 方法的输入为 "Hello"、", "、"world" 和 "!",则预期结果应该等于 "Hello, world!"。
1. 删除生成的测试方法 testConcatWords。
2. 添加如下 helloWorldCheck 方法来测试 Utils.concatWords。
3. public void testHelloWorld() {
4. assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
}
5. 添加一个 println 语句,用于在“JUnit 测试结果”窗口中显示关于测试的文本。
6. @Test
7. public void helloWorldCheck() {
8. System.out.println("* UtilsJUnit4Test: test method 1 - helloWorldCheck()");
assertEquals("Hello, world!", Utils.concatWords("Hello", ", ", "world", "!"));
此测试演示如何检查方法的完成是否花费了过长的时间。若是方法花费了过长的时间,则测试线程将中断并致使测试失败。您能够在测试中指定时间限制。
测试方法将调用 Utils.java 中的 computeFactorial 方法。您能够假定 computeFactorial 方法是正确的,可是在本例中,您但愿测试计算是不是在 1000 毫秒以内完成的。其做用是在 1000 毫秒之好中断测试线程。若是线程被中断,则测试方法将抛出一个 TimeoutException。
1. 删除生成的测试方法 testComputeFactorial。
2. 添加 testWithTimeout 方法,该方法用于计算随机生成数的阶乘。
3. @Test
4. public void testWithTimeout() {
5. final int factorialOf = 1 + (int) (30000 * Math.random());
6. System.out.println("computing " + factorialOf + '!');
7. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
8. 添加如下代码(显示为粗体),用于设置超时并在方法执行时间过长时中断线程。
9. @Test(timeout=1000)
10.public void testWithTimeout() {
final int factorialOf = 1 + (int) (30000 * Math.random());
能够看到,超时被设置为 1000 毫秒。
11. 添加如下 println(显示为粗体),用于在“JUnit 测试结果”窗口中输出关于测试的文本。
12.@Test(timeout=1000)
13.public void testWithTimeout() {
14. System.out.println("* UtilsJUnit4Test: test method 2 - testWithTimeout()");
15. final int factorialOf = 1 + (int) (30000 * Math.random());
16. System.out.println("computing " + factorialOf + '!');
比较:在测试中使用超时(JUnit 3)
此测试演示如何针对预期异常进行测试。若是未抛出指定的预期异常,则会致使方法失败。在本例中,您将测试当输入变量为负数时(-5),computeFactorial 方法是否会抛出 IllegalArgumentException。
1. 添加如下 testExpectedException 方法,它将以输入 -5 调用 computeFactorial 方法。
2. @Test
3. public void checkExpectedException() {
4. final int factorialOf = -5;
5. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
6. 在 @Test 标注中添加如下属性(显示为粗体),指定测试应该抛出 IllegalArgumentException。
7. @Test(expected=IllegalArgumentException.class)
8. public void checkExpectedException() {
9. final int factorialOf = -5;
10. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
11. 添加如下 println(显示为粗体),用于在“JUnit 测试结果”窗口中输出关于测试的文本。
12.@Test (expected=IllegalArgumentException.class)
13.public void checkExpectedException() {
14. System.out.println("* UtilsJUnit4Test: test method 3 - checkExpectedException()");
15. final int factorialOf = -5;
16. System.out.println(factorialOf + "! = " + Utils.computeFactorial(factorialOf));
}
比较:针对预期异常的测试(JUnit 3)
禁用测试
此测试演示如何临时禁用测试方。在 JUnit 4 中,您只需经过添加 @Ignore 标注来禁用测试。
1. 删除生成的测试方法 testNormalizeWord。
2. 在测试类中添加如下测试方法:
3. @Test
4. public void temporarilyDisabledTest() throws Exception {
5. System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");
6. assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
测试方法 temporarilyDisabledTest 将在您运行测试类时运行。
7. 在 @Test 上方添加 @Ignore 标注(显示为粗体)来禁用测试。
8. @Ignore
9. @Test
10.public void temporarilyDisabledTest() throws Exception {
11. System.out.println("* UtilsJUnit4Test: test method 4 - checkExpectedException()");
12. assertEquals("Malm\u00f6", Utils.normalizeWord("Malmo\u0308"));
}
13. 修复导入,以导入 org.junit.Ignore。
比较:禁用测试(JUnit 3)
如今,您已经编写了测试。接下来,您能够运行测试并在“JUnit 测试结果”窗口中查看测试输出。
您能够对整个应用程序或单独的文件运行 JUnit 测试,并在 IDE 中查看结果。要运行项目的全部单元测试,最简单的方法是从主菜单中选择“运行”>“测试 <PROJECT_NAME>”。若是您选择此方法,则 IDE 将运行“测试包”中的全部测试类。要运行单独的测试类,右键单击“测试包”节点下的测试类并选择“运行文件”。
1. 在“项目”窗口中,右键单击 UtilsJUnit4Test.java。
2. 选择“测试文件”。
在运行 UtilsJUnit4Test.java 时,IDE 仅运行测试类中的测试。若是类经过了全部测试,那么您将在“JUnit 测试结果”窗口中看到与下图类似的结果。
在该图中(单击图像查看大图),您能够看到 IDE 对 Utils.java 运行了 JUnit 测试,而且类经过了全部测试。左侧窗格显示各测试方法的结果,右侧窗格显示测试输出。若是您查看输出,您能够看到测试运行的顺序。您向每一个测试方法添加的 println 已将测试的名称输出到“测试结果”窗口和“输出”窗口中。
从 UtilsJUnit4Test 中能够看到,使用 @BeforeClass 进行标注的测试类初始化方法运行于任何其余方法以前,而且只运行一次。使用 @AfterClass 进行标注的测试类初始化方法在类中的全部其余方法以后运行。使用 @Before 进行标注的测试初始化方法在各测试方法以前运行。
使用“测试结果”窗口左侧的控件,能够方便地再次运行测试。您可使用过滤器在显示全部测试结果和仅显示失败的测试之间进行切换。使用相应的箭头,能够跳至下一个或上一个失败的测试。
在“测试结果”窗口中右键单击某个测试结果时,将会出现一个弹出式菜单,您能够选择转至测试的源、再次运行测试或调试测试。
建立单元测试以后的下一步是建立测试套件。请参见建立 JUnit 4 测试套件,了解如何以组的方式运行特定的测试,从而避免单独运行各个测试。
为项目建立测试以后,您最后将获得许多测试类。虽然您能够单独运行测试类,也能够运行项目中的全部测试,但在许多状况下,您但愿运行测试的子集或按特定的顺序运行测试。您能够经过建立一个或多个测试套件来实现此目的。举例来讲,您能够建立测试套件来测试代码的具体方面或具体的条件。
从根本上讲,测试套件是一个类,其中包含对指定测试用例(例如,特定测试类、测试类中的测试方法以及其余测试套件)进行调用的方法。测试套件能够做为测试类的一部分包括在其中,但最佳实践建议单首创建测试套件类。
您能够手动为项目建立 JUnit 3 和 JUnit 4 测试套件,也能够经过 IDE 来生成套件。使用 IDE 生成测试套件以后,缺省状况下,IDE 将生成代码来调用与测试套件相同的包中的全部测试类。建立测试套件以后,您能够对类进行修改,指定但愿做为该套件一部分运行的测试。
若是您选择 JUnit 3 做为测试的版本,则 IDE 能够根据测试包中的测试类来生成 JUnit 3 测试套件。在 JUnit 3 中,您能够指定要包含在测试套件中的测试类,方法是建立一个 TestSuite 实例并调用各测试的 addTest 方法。
1. 在“项目”窗口中右键单击项目节点,而后选择“新建”>“其余”以打开“新建文件”向导。
2. 选择“JUnit”类别和“测试套件”。单击“下一步”。
3. 键入 JUnit3TestSuite 做为文件名称。
4. 选择 sample 包,在测试包文件夹的 sample 文件夹中建立测试套件。
5. 取消选中“测试初始化函数”和“测试释放方法”单击“完成”。
单击“完成”后, IDE 将在 sample 包中建立测试套件类,并在编辑器中打开类。若是 sample 包包含测试类 VectorsJUnit3Test.java 和 UtilsJUnit3Test.java,则测试套件将包含如下代码。
public JUnit3TestSuite(String testName) {
super(testName);
}
public static Test suite() {
TestSuite suite = new TestSuite("JUnit3TestSuite");
suite.addTest(new TestSuite(sample.VectorsJUnit3Test.class));
suite.addTest(new TestSuite(sample.UtilsJUnit3Test.class));
return suite;
}
若是您选择 JUnit 4 做为测试的版本,则 IDE 能够生成 JUnit 4 测试套件。JUnit 4 是向后兼容的,所以您能够运行包含 JUnit 4 和 JUnit 3 测试的 JUnit 4 测试套件。在 JUnit 4 测试套件中,您能够以 @Suite 标注的值的形式指定要包括的测试类。
要让 JUnit 3 做为 JUnit 4 的一部分来运行,须要 JUnit 4.4 或更高版本。
1. 在“项目”窗口中右键单击项目节点,而后选择“新建”>“其余”以打开“新建文件”向导。
2. 选择“JUnit”类别和“测试套件”。单击“下一步”。
3. 键入 JUnit4TestSuite 做为文件名称。
4. 选择 sample 包,在测试包文件夹的 sample 文件夹中建立测试套件。
5. 取消选中“测试初始化函数”和“测试释放方法”单击“完成”。
单击“完成”后, IDE 将在 sample 包中建立测试套件类,并在编辑器中打开类。测试套件包含如下代码。
@RunWith(Suite.class)
@Suite.SuiteClasses(value={UtilsJUnit4Test.class, VectorsJUnit4Test.class})
public class JUnit4TestSuite {
}
运行测试套件时,IDE 将按照测试类 UtilsJUnit4Test 和 VectorsJUnit4Test 的列出顺序来运行它们。
运行测试套件与运行任何单独测试类的方法相同。
1. 在“项目”窗口中展开“测试包”节点。
2. 右键单击测试套件类,而后选择“测试文件”。
运行测试套件以后,IDE 将按照套件中的测试的列出顺序来运行它们。JUnit 测试结果显示在“JUnit 测试结果”窗口中。
在该图中(单击图像查看大图),您能够看到 JUnit 3 测试套件的测试结果。测试套件将以单独测试的形式来运行 UtilsJUnit3Test 和 VectorsJUnit3Test 测试类,并在左侧窗格中显示各测试的结果。单独运行测试时,右侧窗格中的输出与左侧相同。
在该图中(单击图像查看大图),您能够看到 JUnit 4 测试套件的测试结果。测试套件将以单独测试的形式来运行 UtilsJUnit4Test 和 VectorsJUnit4Test 测试类,并在左侧窗格中显示各测试的结果。单独运行测试时,右侧窗格中的输出与左侧相同。
在该图中(单击图像查看大图),您能够看到混合测试套件的测试结果。该测试套件包括 JUnit 4 测试套件和一个 JUnit 3 测试类。测试套件将以单独测试的形式来运行 UtilsJUnit3Test.java 和 JUnit4TestSuite.java 测试类,并在左侧窗格中显示各测试的结果。单独运行测试时,右侧窗格中的输出与左侧相同。
本教程是在 NetBeans IDE 中建立 JUnit 单元测试和测试套件的基本介绍。IDE 支持 JUnit 3 和 JUnit 4;本文档介绍了 JUnit 4 中引入的一些更改,这些更改可简化测试的建立和运行过程。
如本教程中所述,JUnit 4 的主要改进之一就是提供了对标注的支持。在 JUnit 4 中,您如今能够将标注用于如下用途:
· 使用 @Test 标注标识测试,而不使用命名约定
· 使用 @Before 和 @After 标注标识 setUp 和 tearDown 方法
· 标识适用于整个测试类的 setUp 和 tearDown 方法。带有 @BeforeClass 标注的方法仅在类中的全部测试方法运行以前运行一次。一样,带有 @AfterClass 标注的方法仅在全部测试方法运行完以后运行一次。 标识预期的异常 使用 @Ignore 标注标识应跳过的测试
· 为测试指定超时参数
一般,测试代码能帮助确保对代码中所作的小更改不会中断应用程序。JUnit 等自动化测试工具简化了测试的流程,而且常常性的测试能帮助及时捕获代码错误。