TA的每日心情 | 擦汗 3 小时前 |
---|
签到天数: 1046 天 连续签到: 4 天 [LV.10]测试总司令
|
1.原理图
2. 基本架构
被测代码
- package com.jerry;
- public class Calculator{
- private static int result;
- public void add(int n) {
- result = result + n;
- }
- public void substract(int n) {
- result = result - n;
- }
- public void multiply(int n) {
- result = result * n;
- }
- public void divide(int n){
- try {
- result = result / n;
- }catch(ArithmeticException ex){
- System.out.println(ex);
- throw new ArithmeticException("The n not allowed to 0!!")
- }
- }
- }
复制代码 最基本的测试代码
- public class CalculatorTest {
- private static Calculator calculator = new Calculator();
- @BeforeEach
- public void setUp() throws Exception {
- calculator.clear();
- }
- @Test
- @DisplayName("测试加法")
- public void testAdd() {
- calculator.add(2);
- calculator.add(3);
- assertEquals(5, calculator.getResult());
- }
- @Test
- @DisplayName("测试减法")
- public void testSubstract() {
- calculator.add(5);
- calculator.substract(3);
- Assertions.assertEquals(2, calculator.getResult());
- }
- @Test
- @DisplayName("测试乘法")
- public void testMultiply() {
- calculator.add(3);
- calculator.multiply(2);
- Assertions.assertEquals(6, calculator.getResult());
- }
- @Test
- @DisplayName("测试除法")
- public void testDivide() {
- calculator.add(9);
- calculator.divide(3);
- Assertions.assertEquals(3, calculator.getResult());
- }
复制代码 标签@DisplayName可以在测试结果的时候显示其内容。
3.JUnit5的修饰符
描述装饰符的程序
运行结果(缩进为了看起来方便,我自己设置的)
- BeforeAll
- BeforeEach
- 依赖注入1
- AfterEach
- BeforeEach
- TestIdentifier [依赖注入2]
- ReportEntry [timestamp = 2020-08-21T11:38:49.361976500, name = 'Alex’]
- AfterEach
- BeforeEach
- myFirstTest
- AfterEach
- BeforeEach
- testWithDisplayName
- AfterEach
- BeforeEach
- 运行一组断言
- AfterEach
- AfterAll
复制代码 注意:@BeforeAll、 @AfterALL注解方法必须是静态方法,否则会抛出运行时错误。 4. JUnit5 新加断言
5. 异常断言 被测的程序
- public void divide(int n){
- try {
- result = result / n;
- }catch(ArithmeticException ex){
- System.out.println(ex);
- throw new ArithmeticException("The n not allowed to 0!!");
- }
- }
复制代码 测试程序
- @Test
- @DisplayName("测试除0异常")
- public void testDivideByZero() {
- calculator.add(9);
- Throwable exception = Assertions.assertThrows(ArithmeticException.class, () -> calculator.divide(0));
- Assertions.assertEquals("The n not allowed to 0!!",exception.getMessage());
- }
复制代码 6. 超时断言
- @Test
- public void squareRoot() {
- Assertions.assertTimeoutPreemptively(Duration.of(2, ChronoUnit.SECONDS), () -> calculator.squareRoot(4))
- }
复制代码
判断程序是否应该在两秒钟执行完毕。类似于JUnit4中的(timeout=XXX)。 7. 参数化测试
7.1单参数
- @ParameterizedTest
- @ValueSource(ints = {1,2,3,4})
- @DisplayName("参数化测试_单参数")
- public void parameterizedTest(int param) {
- calculator.add(param);
- calculator.add(-1 * param);
- Assertions.assertEquals(0, calculator.getResult());
- }
复制代码 标签: ·@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
·@NullSource: 表示为参数化测试提供一个null的入参
·@EnumSource: 表示为参数化测试提供一个枚举入参
ValueSource类型:
·String values: @ValueSource(strings = {"foo", "bar", "baz"})
·Double values: @ValueSource(doubles = {1.5D, 2.2D, 3.0D})
·Long values: @ValueSource(longs = {2L, 4L, 8L})
·Integer values: @ValueSource(ints = {2, 4, 8})
7.2 Enum参数
- import java.util.concurrent.TimeUnit;
- …
- @ParameterizedTest
- @EnumSource(value = TimeUnit.class, names = {"SECONDS", "MINUTES"})
- @DisplayName("参数化测试_Enum参数")
- void testTimeUnitJustSecondsAndMinutes(TimeUnit unit) {
- Assertions.assertTrue(EnumSet.of(TimeUnit.SECONDS, TimeUnit.MINUTES).contains(unit));
- Assertions.assertFalse(EnumSet
- .of(TimeUnit.DAYS, TimeUnit.HOURS, TimeUnit.MILLISECONDS, TimeUnit.NANOSECONDS,
- TimeUnit.MICROSECONDS).contains(unit));
- }
复制代码 7.3参数化测试——方法参数(多参数) 注意:这个方法返回必须是个流
- @ParameterizedTest
- @MethodSource("paramGenerator")
- @DisplayName("参数化测试_ 方法参数(多参数)")
- void MethodParameForSquareRoot(int param, int result){
- calculator.squareRoot(param);
- Assertions.assertEquals(result, calculator.getResult());
- }
-
- static Stream<Arguments> paramGenerator(){
- return Stream.of(Arguments.of(4,2), Arguments.of(9,3), Arguments.of(16,4));
- }
复制代码 7.4.参数化测试——CVS文件参数化
- @ParameterizedTest
- @CsvFileSource(resources = "data.csv") //指定csv文件位置
- @DisplayName("参数化测试-csv文件")
- public void parameterizedCVSFile(int param, int result) {
- calculator.squareRoot(param);
- Assertions.assertEquals(result, calculator.getResult());
- }
复制代码 其中,data.csv为:
8.内嵌测试类 一般一个产品类对应一个测试类,但是使用JUnit,可以实现类的嵌套。
- package com.jerry;
- import org.junit.jupiter.api.BeforeEach;
- import org.junit.jupiter.api.DisplayName;
- import org.junit.jupiter.api.Nested;
- import org.junit.jupiter.api.Test;
- public class NestedTestDemo {
- @Test
- @DisplayName("Nested")
- void isInstantiatedWithNew() {
- System.out.println("最一层--内嵌单元测试");
- }
- @Nested
- @DisplayName("Nested2")
- class Nested2 {
- @BeforeEach
- void Nested2_init() {
- System.out.println("Nested2_init");
- }
- @Test
- void Nested2_test() {
- System.out.println("第二层-内嵌单元测试");
- }
- @Nested
- @DisplayName("Nested3")
- class Nested3 {
- @BeforeEach
- void Nested3_init() {
- System.out.println("Nested3_init");
- }
- @Test
- void Nested3_test() {
- System.out.println("第三层-内嵌单元测试");
- }
- }
- }
- }
复制代码 结果输出: 第一层--内嵌单元测试
Nested2_init
第二层-内嵌单元测试
Nested2_init
Nested3_init
第三层-内嵌单元测试
9. 重复测试
- @RepeatedTest(5) //表示重复执行5次
- @DisplayName("重复减法")
- public void testSubstractManyTimes() {
- calculator.add(5);
- calculator.substract(3);
- Assertions.assertEquals(2, calculator.getResult());
- }
复制代码 这个测试用例将被执行5次,为什么设计这个方法,我个人没有理解。 10. 动态测试
- <strong> </strong>@TestFactory
- @DisplayName("动态测试")
- Iterator<DynamicTest> dynamicTests() {
- return Arrays.asList(
- dynamicTest("第1个动态测试", () ->{calculator.squareRoot(4);Assertions.assertEquals(2, calculator.getResult());}),
- dynamicTest("第2个动态测试", () ->{calculator.squareRoot(9);Assertions.assertEquals(3, calculator.getResult());}),
- dynamicTest("第3个动态测试", () ->{calculator.squareRoot(16);Assertions.assertEquals(4, calculator.getResult());}),
- dynamicTest("第4个动态测试", () ->{calculator.squareRoot(25);Assertions.assertEquals(5, calculator.getResult());})
- ).iterator();
- }
复制代码 动态测试用得比较少,这个功能的原因我个人也不太理解。 11. 分组断言assertAll
- @Test
- @DisplayName("开根号分组断言")
- public void testGroup() {
- int[] parem = {4, 9, 16, 25, 36};
- int[] result ={2, 3, 4, 5, 6};
- Assertions.assertAll("parem,result",
- () -> {calculator.squareRoot(parem[0]);Assertions.assertEquals(result[0], calculator.getResult());},
- () -> {calculator.squareRoot(parem[1]);Assertions.assertEquals(result[1], calculator.getResult());},
- () -> {calculator.squareRoot(parem[2]);Assertions.assertEquals(result[2], calculator.getResult());},
- () -> {calculator.squareRoot(parem[3]);Assertions.assertEquals(result[3], calculator.getResult());},
- () -> {calculator.squareRoot(parem[4]);Assertions.assertEquals(result[4], calculator.getResult());}
- );
复制代码 分组断言中任一个断言的失败,都会将以 MultipleFailuresError 错误进行抛出提示。另外可以看出,使用分组断言也可以实现参数化
|
|