Espresso 测试框架 - JUnit 概述

在本章中,我们将了解 JUnit 的基础知识,这是 Java 社区开发的流行单元测试框架,Espresso 测试框架就是在此框架上构建的。

JUnit 是 Java 应用程序单元测试的事实标准。尽管它在单元测试中很受欢迎,但它也完全支持和提供仪器测试。Espresso 测试库扩展了必要的 JUnit 类,以支持基于 Android 的仪器测试。

编写一个简单的单元测试

让我们创建一个 Java 类 Computation (Computation.java) 并编写简单的数学运算 SummationMultiplication。然后,我们将使用 JUnit 编写测试用例,并通过运行测试用例进行检查。

  • 启动 Android Studio。

  • 打开上一章中创建的 HelloWorldApp

  • app/src/main/java/com/tutorialspoint/espressosamples/helloworldapp/ 中创建一个文件 Computation.java,并编写两个函数 - SumMultiply,如下所示,

package com.tutorialspoint.espressosamples.helloworldapp;
public class Computation {
   public Computation() {}
   public int Sum(int a, int b) {
      return a + b;
   }
   public int Multiply(int a, int b) {
      return a * b;
   }
}
  • 在 app/src/test/java/com/tutorialspoint/espressosamples/helloworldapp 中创建一个文件 ComputationUnitTest.java,并编写单元测试用例来测试 Sum 和 Multiply 功能,如下所示

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class ComputationUnitTest {
   @Test
   public void sum_isCorrect() {
      Computation computation = new Computation();
      assertEquals(4, computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      Computation computation = new Computation();
      assertEquals(4, computation.Multiply(2,2));
   }
}

这里,我们使用了两个新术语 - @TestassertEquals。一般来说,JUnit 使用 Java 注解来识别类中的测试用例以及如何执行测试用例的信息。@Test 就是这样一种 Java 注解,它指定特定函数是 Junit 测试用例。assertEquals 是一个断言第一个参数(预期值)和第二个参数(计算值)相等且相同的函数。JUnit 为不同的测试场景提供了许多断言方法。

  • 现在,在 Android Studio 中运行 ComputationUnitTest,方法是右键单击该类并调用运行 'ComputationUnitTest' 选项,如上一章所述。这将运行单元测试用例并报告成功。

计算单元测试的结果如下所示 −

Computation Unit Test

注解

JUnit 框架广泛使用注解。一些重要的注解如下 −

  • @Test

  • @Before

  • @After

  • @BeforeClass

  • @AfterClass

  • @Rule

@Test 注解

@TestJUnit 框架中非常重要的注解。@Test 用于区分普通方法和测试用例方法。一旦方法用 @Test 注解修饰,则该特定方法将被视为 测试用例 并将由 JUnit Runner 运行。JUnit Runner 是一个特殊类,用于查找和运行 Java 类中可用的 JUnit 测试用例。目前,我们使用 Android Studio 的内置选项来运行单元测试(进而运行 JUnit Runner)。示例代码如下,

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   @Test
   public void multiply_isCorrect() {
      Computation computation = new Computation();
      assertEquals(4, computation.Multiply(2,2));
   }
}

@Before

@Before 注解用于引用一个方法,该方法需要在运行特定测试类中可用的任何测试方法之前调用。例如,在我们的示例中,可以在单独的方法中创建 Computation 对象,并使用 @Before 注解,以便它在 sum_isCorrectmultiply_isCorrect 测试用例之前运行。完整代码如下,

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   Computation computation = null;
   @Before
   public void CreateComputationObject() {
      this.computation = new Computation();
   }
   @Test
   public void sum_isCorrect() {
      assertEquals(4, this.computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      assertEquals(4, this.computation.Multiply(2,2));
   }
}

@After

@After@Before类似,但是被@After注解的方法会在每次测试用例运行之后被调用或者执行,示例代码如下,

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   Computation computation = null;
   @Before
   public void CreateComputationObject() {
      this.computation = new Computation();
   }
   @After
   public void DestroyComputationObject() {
      this.computation = null;
   }
   @Test
   public void sum_isCorrect() {
      assertEquals(4, this.computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      assertEquals(4, this.computation.Multiply(2,2));
   }
}

@BeforeClass

@BeforeClass@Before 类似,但使用 @BeforeClass 注解的方法在运行特定类中的所有测试用例之前只会被调用或执行一次。创建资源密集型对象(如数据库连接对象)很有用。这将减少执行一组测试用例的时间。此方法必须是静态的才能正常工作。在我们的示例中,我们可以在运行所有测试用例之前创建一次计算对象,如下所示,

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   private static Computation computation = null;
   @BeforeClass
   public static void CreateComputationObject() {
      computation = new Computation();
   }
   @Test
   public void sum_isCorrect() {
      assertEquals(4, computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      assertEquals(4, computation.Multiply(2,2));
   }
}

@AfterClass

@AfterClass@BeforeClass类似,但是用@AfterClass注解的方法只会在特定类中的所有测试用例运行完之后被调用或执行一次。此方法也需要是静态的才能正常工作。示例代码如下−

package com.tutorialspoint.espressosamples.helloworldapp;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   private static Computation computation = null;
   @BeforeClass
   public static void CreateComputationObject() {
      computation = new Computation();
   }
   @AfterClass
   public static void DestroyComputationObject() {
      computation = null;
   }
   @Test
   public void sum_isCorrect() {
      assertEquals(4, computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      assertEquals(4, computation.Multiply(2,2));
   }
}

@Rule

@Rule 注解是 JUnit 的亮点之一。它用于向测试用例添加行为。我们只能注解 TestRule 类型的字段。它实际上提供了 @Before@After 注解提供的功能集,但方式高效且可重用。例如,我们可能需要一个临时文件夹来在测试用例期间存储一些数据。通常,我们需要在运行测试用例之前创建一个临时文件夹(使用 @Before 或 @BeforeClass 注解),并在测试用例运行后销毁它(使用 @After 或 @AfterClass 注解)。相反,我们可以使用 JUnit 框架提供的 TemporaryFolder(类型为 TestRule)类为我们的所有测试用例创建一个临时文件夹,并且临时文件夹将在测试用例运行时被删除。我们需要创建一个类型为 TemporaryFolder 的新变量,并使用 @Rule 进行注解,如下所示,

package com.tutorialspoint.espressosamples.helloworldapp;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;

public class ComputationUnitTest {
   private static Computation computation = null;
   @Rule
   public TemporaryFolder folder = new TemporaryFolder();
   @Test
   public void file_isCreated() throws IOException {
      folder.newFolder("MyTestFolder");
      File testFile = folder.newFile("MyTestFile.txt");
      assertTrue(testFile.exists());
   }
   @BeforeClass
   public static void CreateComputationObject() {
      computation = new Computation();
   }
   @AfterClass
   public static void DestroyComputationObject() {
      computation = null;
   }
   @Test
   public void sum_isCorrect() {
      assertEquals(4, computation.Sum(2,2));
   }
   @Test
   public void multiply_isCorrect() {
      assertEquals(4, computation.Multiply(2,2));
   }
}

执行顺序

JUnit 中,使用不同注解的方法将按特定顺序执行,如下所示,

  • @BeforeClass

  • @Rule

  • @Before

  • @Test

  • @After

  • @AfterClass

断言

断言是一种检查测试用例的预期值是否与测试用例结果的实际值匹配的方法。JUnit 为不同的场景提供了断言;下面列出了一些重要的断言 −

  • fail() − 明确使测试用例失败。

  • assertTrue(boolean test_condition) − 检查 test_condition 是否为真

  • assertFalse(boolean test_condition) − 检查 test_condition 是否为假

  • assertEquals(expected, actual) −检查两个值是否相等

  • assertNull(object) − 检查对象是否为空

  • assertNotNull(object) − 检查对象是否不为空

  • assertSame(expected, actual) − 检查两者是否引用同一个对象。

  • assertNotSame(expected, actual) − 检查两者是否引用不同的对象。