如何编写单元测试?


135

我有一个Java类。如何进行 单元测试


就我而言,我有class做一个二进制和。它需要两个byte[]数组,将它们求和,然后返回一个新的二进制数组。


7
您可以利用jUnit之类的工具为Java类编写测试用例(测试方法)。然后在构建过程(ant / maven)中调用jUnit测试。使用jUnit一点也不难,困难的部分是想出了尽可能多的测试方案,以便您尽早并经常发现错误。
CoolBeans 2012年

Answers:


133
  1. 使用正确的输入定义正常情况下的预期和期望输出。

  2. 现在,通过声明一个类来实现测试,将其命名为任何东西(通常是类似TestAddingModule之类的东西),然后向其添加testAdd方法(即,类似于下面的方法):

    • 编写一个方法,并在其上方添加@Test批注。
    • 在该方法中,运行您的二进制和assertEquals(expectedVal,calculatedVal)
    • 通过运行它来测试您的方法(在Eclipse中,右键单击,选择Run as→JUnit test)。

      //for normal addition 
      @Test
      public void testAdd1Plus1() 
      {
          int x  = 1 ; int y = 1;
          assertEquals(2, myClass.add(x,y));
      }
      
  3. 根据需要添加其他案例。

    • 如果整数溢出,请测试您的二进制和是否不会引发意外异常。
    • 测试您的方法是否可以正常处理Null输入(下面的示例)。

      //if you are using 0 as default for null, make sure your class works in that case.
      @Test
      public void testAdd1Plus1() 
      {
          int y = 1;
          assertEquals(0, myClass.add(null,y));
      }
      

1.是否需要@Test表示法?2.为什么不使用assertNotNull测试空输入?3.单元测试的结果在哪里捕获?结果如何显示给用户?
user137717

10
是的,@Test必须使用符号。这样做是为了向单元测试运行器发出信号,表明此方法代表单元测试,应该执行。没有注释的方法@Test不会由测试运行程序执行。
Ali Shah Ahmed 2014年

第二次测试-不应该加入nully只给你y
Adjit

谢谢!我想知道为什么不需要添加static测试方法的修饰符。
张亮

103

我为IntelliJEclipse提供了这篇文章。

蚀:

要为您的项目进行单元测试,请遵循以下步骤(我正在使用Eclipse来编写此测试):

1-单击新建-> Java项目。

建立专案

2-写下您的项目名称,然后单击完成。

建立专案

3-右键单击您的项目。然后,单击新建->类。

建立课程

4-写下您的班级名称,然后单击完成。

建立课程

然后,像这样完成课程:

public class Math {
    int a, b;
    Math(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int add() {
        return a + b;
    }
}

5-单击文件->新建-> JUnit测试用例。

创建JUnite测试

6-检查setUp()并单击完成。SetUp()将是您初始化测试的地方。

检查SetUp()

7-单击确定。

添加JUnit

8-在这里,我只添加7和10。因此,我希望答案是17。像这样完成测试类:

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class MathTest {
    Math math;
    @Before
    public void setUp() throws Exception {
        math = new Math(7, 10);
    }
    @Test
    public void testAdd() {
        Assert.assertEquals(17, math.add());
    }
}

9-在包资源管理器中单击您的测试类,然后单击Run as-> JUnit Test。

运行JUnit测试

10-这是测试的结果。

测试结果

IntelliJ: 请注意,我将IntelliJ IDEA社区2020.1用于屏幕截图。另外,您需要在执行这些步骤之前设置jre。我正在使用JDK 11.0.4。

1-右键单击项目的主文件夹-> new->目录。您应该将此称为“测试”。 在此处输入图片说明 2-右键单击测试文件夹,然后创建正确的程序包。我建议创建与原始类相同的包装名称。然后,右键单击测试目录->将目录标记为->测试源根目录。 在此处输入图片说明 3-在测试目录中的正确软件包中,您需要创建一个Java类(我建议使用Test.java)。 在此处输入图片说明 4-在创建的类中,键入“ @Test”。然后,在IntelliJ提供的选项中,选择“将'JUnitx'添加到类路径”。 5-在测试类中编写测试方法。方法签名如下:在此处输入图片说明 在此处输入图片说明

@Test
public void test<name of original method>(){
...
}

您可以像下面这样进行断言:

Assertions.assertTrue(f.flipEquiv(node1_1, node2_1));

这些是我添加的导入:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

在此处输入图片说明

这是我编写的测试: 在此处输入图片说明

您可以检查您的方法,如下所示:

Assertions.assertEquals(<Expected>,<actual>);
Assertions.assertTrue(<actual>);
...

要运行单元测试,请右键单击测试,然后单击“运行”。 在此处输入图片说明

如果您的测试通过,结果将如下所示: 在此处输入图片说明

希望对您有所帮助。您可以在GitHub https://github.com/m-vahidalizadeh/problem_solving_project中查看项目的结构。


12
爱你的答案,这是最好的“方法”!
alisa

4
我很高兴我的回答很有帮助。感谢您的评论。
Mohammad

1
这就是教程的外观;干净,简洁,完整的例子。很好。
杰克之刃

1
非常感谢杰克。很高兴您发现它很有帮助。
穆罕默德'18

18

这是一个非常笼统的问题,有很多方法可以解决。

如果要使用JUnit创建测试,则需要创建测试用例类,然后创建单独的测试方法来测试被测类/模块的特定功能(单个测试用例类通常与单个“生产”类关联,正在测试),并在这些方法中执行各种操作,并将结果与​​正确的结果进行比较。尝试覆盖尽可能多的极端情况尤其重要。

在您的特定示例中,您可以例如测试以下内容:

  1. 两个正数之间的简单加法。添加它们,然后验证结果是否符合您的期望。
  2. 正数和负数之间的加法(返回带有第一个参数符号的结果)。
  3. 正数和负数之间的加法(返回带有第二个参数符号的结果)。
  4. 两个负数之间的加法。
  5. 加法导致溢出。

要验证结果,可以使用org.junit.Assert类中的各种assertXXX方法(为方便起见,可以执行“ import static org.junit.Assert。*”)。这些方法会测试特定条件,如果未通过验证,则测试会失败(可选,带有特定消息)。

您的案例中的示例用例类(没有定义方法的内容):

import static org.junit.Assert.*;

public class AdditionTests {
    @Test
    public void testSimpleAddition() { ... }


    @Test
    public void testPositiveNegativeAddition() { ... }


    @Test
    public void testNegativePositiveAddition() { ... }


    @Test
    public void testNegativeAddition() { ... }


    @Test
    public void testOverflow() { ... }
}

如果您不习惯编写单元测试,而是通过编写临时测试来测试代码,然后进行“可视化”验证(例如,您编写了一个简单的main方法,该方法接受使用键盘输入的参数,然后打印出结果-然后继续输入值并验证自己是否正确(如果结果正确),则可以按照上述格式编写此类测试,然后使用正确的assertXXX方法验证结果,而不是手动进行操作。这样,与必须进行手动测试相比,您可以更轻松地重新运行测试。


8

就像提到的@CoolBeans一样,看看jUnit。这是一个简短的教程,可让您入门jUnit 4.x

最后,如果您真的想了解有关测试和测试驱动开发(TDD)的更多信息,建议您阅读Kent Beck撰写的以下书籍:示例测试驱动开发


6

其他答案还向您展示了如何使用JUnit设置测试类。JUnit不是唯一的Java测试框架。但是,专注于使用框架的技术细节会损害应该指导您的操作的最重要概念,因此,我将讨论这些概念。

  • 测试(对各种事物的测试)将事物(被测系统,SUT)的实际行为与其预期行为进行比较。

  • 可以使用计算机程序来完成自动测试。由于该比较是通过不灵活且不智能的计算机程序进行的,因此必须准确且明确地知道预期的行为。

  • 期望程序或程序的一部分(类或方法)执行的是其规范。因此,测试软件要求您具有SUT的规范。这可能是明确的描述,也可能是您所期望的隐含说明。

  • 因此,自动化的单元测试需要对要测试的类或方法进行精确且明确的说明。

  • 但是在着手编写代码时需要该规范。因此,测试的一部分实际上是在您甚至编写一行SUT之前就开始的。测试驱动开发(TDD)的测试技术将这一想法发挥到了极致,并在编写要测试的代码之前先创建了单元测试代码。

  • 单元测试框架使用断言测试您的SUT 。断言是逻辑表达式(具有boolean结果类型的表达式;谓词),true如果SUT行为正确,则必须为断言。因此,该规范必须表示为(或重新表达)为断言。

  • 将规范表达为断言的一种有用技术是通过合同编程。这些规范是基于后置条件的。后置条件是关于从方法或构造函数返回后SUT的公开可见状态的断言。一些方法具有不变的后置条件,这是在执行该方法之前和之后均成立的谓词。一个也可以说具有不变量,它们是该类的每个构造函数和方法的后置条件,因此应始终为真。后置条件(和不变式)仅以公开可见状态表示:publicprotected字段,由返回的值由publicprotected方法(例如getter),以及对象的公开可见状态(通过引用)传递给方法。


许多初学者在这里发布问题,询问他们如何测试某些代码,仅提供代码,但未说明该代码的规范。正如本讨论所显示的,任何人都不可能对这个问题给出好的答案,因为充其量潜在的答题者必须猜测该规范,并且可能会错误地这样做。该提问者的问题显然并不了解规范的重要性,因此,谁需要了解我在这里所描述的基本面新手之前尝试写一些测试代码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.