如何编写单元测试?
Posted
技术标签:
【中文标题】如何编写单元测试?【英文标题】:How to write a Unit Test? 【发布时间】:2012-02-03 19:28:48 【问题描述】:我有一个 Java 类。怎么unit test呢?
在我的例子中,我有一个类进行二进制求和。它需要两个byte[]
数组,对它们求和,然后返回一个新的二进制数组。
【问题讨论】:
您可以利用jUnit 之类的工具为您的java 类编写测试用例(测试方法)。然后调用 jUnit 测试作为构建过程的一部分 (ant/maven)。使用 jUnit 一点也不难,难的是想出你能想到的尽可能多的测试场景,以便你尽早并经常发现错误。 【参考方案1】:使用正确的输入定义正常情况下的预期和期望输出。
现在,通过声明一个类来实现测试,将其命名为任何名称(通常类似于 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));
根据需要添加其他案例。
如果存在整数溢出,请测试您的二进制求和不会引发意外异常。测试您的方法是否能够优雅地处理 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. 单元测试的结果在哪里捕获?结果如何显示给用户? 是的,@Test
符号是必需的。这样做是为了向单元测试运行器发出信号,表明此方法代表单元测试并且应该执行。未使用 @Test
注释的方法不会由测试运行程序执行。
第二次测试 - 不应该在y
中添加null
只是给你y
?
谢谢!我想知道为什么不用static
添加到测试方法的修饰符中。【参考方案2】:
我为 IntelliJ 和 Eclipse 提供这篇文章。
日食:
要为您的项目进行单元测试,请按照以下步骤操作(我正在使用 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 测试用例。
6- 检查 setUp() 并单击完成。 SetUp() 将是您初始化测试的地方。
7- 点击确定。
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。
10- 这是测试的结果。
IntelliJ: 请注意,我使用 IntelliJ IDEA 社区 2020.1 作为屏幕截图。此外,您需要在这些步骤之前设置您的 jre。我正在使用 JDK 11.0.4。
1-右键单击项目的主文件夹->新建->目录。您应该将此称为“测试”。 2-右键单击测试文件夹并创建正确的包。我建议创建与原始类相同的包装名称。然后,右键单击测试目录 -> 将目录标记为 -> 测试源根目录。 3-在test目录的正确包中,需要创建一个Java类(我建议使用Test.java)。 4- 在创建的类中,输入“@Test”。然后,在 IntelliJ 为您提供的选项中,选择 Add 'JUnitx' to classpath。 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>);
...
要运行单元测试,请右键单击测试并单击 Run 。
如果您的测试通过,结果将如下所示:
我希望它有所帮助。可以在GitHubhttps://github.com/m-vahidalizadeh/problem_solving_project看到项目的结构。
【讨论】:
喜欢你的回答,这是最好的“操作方法”! 很高兴我的回答很有帮助。感谢您的评论。 教程应该是这样的;干净,简洁,完整的例子。非常好。 非常感谢杰克。我很高兴你发现它有帮助。【参考方案3】:这是一个非常笼统的问题,有很多方法可以回答。
如果你想使用 JUnit 来创建测试,你需要创建你的测试用例类,然后创建单独的测试方法来测试你的类/模块的特定功能(单个测试用例类通常与单个“生产” 正在测试的类)并在这些方法内部执行各种操作并将结果与正确的结果进行比较。尝试覆盖尽可能多的极端情况尤为重要。
在您的具体示例中,您可以测试以下内容:
-
两个正数之间的简单加法。添加它们,然后验证结果是否符合您的预期。
正数和负数之间的加法(返回带有第一个参数符号的结果)。
正数和负数之间的加法(返回带有第二个参数符号的结果)。
两个负数之间的加法。
导致溢出的添加。
要验证结果,您可以使用 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 方法验证结果,而不是手动进行。这样,您可以比必须进行手动测试更轻松地重新运行测试。
【讨论】:
【参考方案4】:就像提到的@CoolBeans 一样,看看jUnit。这是一个简短的tutorial,可以帮助您开始使用 jUnit 4.x
最后,如果您真的想了解有关测试和测试驱动开发 (TDD) 的更多信息,我建议您看看 Kent Beck 的以下书籍:Test-Driven Development By Example。
【讨论】:
【参考方案5】:其他答案已向您展示了如何使用 JUnit 设置测试类。 JUnit 不是唯一的 Java 测试框架。然而,专注于使用框架的技术细节会偏离应该指导您行动的最重要的概念,所以我将讨论这些。
测试(各种事物)将某事物(被测系统,SUT)的实际行为与其预期行为进行比较。
可以使用计算机程序进行自动化测试。因为这种比较是由一个不灵活且不智能的计算机程序完成的,所以预期的行为必须准确无误地知道。
程序或程序的一部分(类或方法)期望做的是它的规范。因此,测试软件需要您有一个 SUT 规范。这可能是明确的描述,也可能是您对预期内容的隐含说明。
因此,自动化单元测试需要对您正在测试的类或方法进行精确且明确的规范。
但是当您开始编写该代码时,您需要该规范。因此,测试的一部分实际上是在您编写一行 SUT 之前开始的。测试驱动开发(TDD)的测试技术把这个想法发挥到了极致,让你在编写要测试的代码之前创建单元测试代码。
单元测试框架使用断言测试您的 SUT。如果 SUT 行为正确,断言是一个逻辑表达式(一个具有boolean
结果类型的表达式;一个谓词),它必须是true
。因此,规范必须表达(或重新表达)为断言。
将规范表达为断言的一种有用技术是按合同设计。这些规范是根据后置条件。后置条件是关于从方法或构造函数返回后 SUT 的公开可见状态的断言。有些方法有后置条件
它们是不变量,它们是在方法执行之前和之后为真的谓词。 类也可以说是具有不变量,它们是类的每个构造函数和方法的后置条件,因此应该总是为真。后置条件(和不变量)仅以公开可见状态表示:public
和 protected
字段,public
和 protected
方法返回的值(如 getter),以及公开可见状态对象(通过引用)传递给方法。
许多初学者在这里发布问题,询问他们如何测试某些代码,展示代码但没有说明该代码的规范。正如这个讨论所表明的,任何人不可能对这样的问题给出一个好的答案,因为潜在的回答者充其量必须猜测规范,并且可能会做错。问题的提问者显然不了解规范的重要性,因此是一个新手,需要了解我在此处描述的基本原理尝试编写一些测试代码。
【讨论】:
以上是关于如何编写单元测试?的主要内容,如果未能解决你的问题,请参考以下文章