Catalog
Test Fixture
参数化测试
Runner运行器
Test Fixture
Test Fixture 有人叫它测试设备,有人说它是固定的代码段,我不知道该怎么称呼它,
但是它的英文的解释是: The test fixture is everything we need to have in place to exercise the SUT.
可以翻译为:运行被测试软件所需要的一切东西。
比较常见的用法:
- 实例化某个被测方法所在的类 ,eg. 你要测试Calculator类中的Add()方法,则需要实例化Calculator类;
- 准备连接数据库,eg. 平时写关于数据库操作时,你只会写一个连接类,大家都调用这个类,对于测试方法也是类似的道理;
- 其他的可以自己发现...
准备Test Fixture方法有三种,所以一步一步进化来的,目的是减少重复的代码,节约资源。
- 内联方式
- 委托方式
- 隐藏方式
内联方式
eg. 你要测试一个类中所有的方法,在每个方法中都写上被测试类的实例对象,即 被测试类XXX test = new 被测试类XXX();
这样就造成了代码的重复,如果这个new 这个实例的过程非常复杂,那么也会减低测试代码的可读性和可维护性。另外一个问题是,
这种方法很容易带来测试书库Hard code的隐患(还不理解,待解答)。
不过,对于初学者,这是最简单的方法,也是单元测试的入门过程。

1 public class MathDemoTest { 2 @Test 3 public void testAdd() { 4 MathDemo demo = new MathDemo(); 5 int expetected = 1; 6 int trueValue = demo.add(1, 1); 7 //断言方法 8 assertEquals("你好像写错了",expetected, trueValue); 9 } 10 @Test 11 public void testDiv() { 12 MathDemo demo = new MathDemo(); 13 int expected = 1; 14 int trueValue = demo.div(1, 1); 15 assertEquals(expected, trueValue); 16 } 17 }
委托方式
eg. 数据库连接过程是单独的一个方法,然后需要的时候代用该方法即可。这种方式的好处就是使得测试代码可读性增强,并且
这部分的SetUp(这个对应的注解是@Before)代码可以重复使用。而且这种做法可以屏蔽对SetUp过程的认知,使得测试人员的关注
点落在真正的测试代码上面,而不是如何SetUp。
隐藏方式
JUnit是一个可编写重复测试的简单框架,是基于Xunit架构的单元测试框架的实例。很多的Xunit框架的实现都提供了不同的隐
式SetUp 和 TearDown 。eg. 在JUnit里面的 @Before 和 @After 注解,就提供了一种隐式准备Test Fixture的支持, 在每个
测试方法运行前,都会执行带有@Before注解的方法,在每个测试方法运行结束后,都会执行带有 @After 注解的方法。这种方式
的好处就是写一次就能在各个测试方法中都实现了 Test Fixture的准备, 不用显式的调用一个外部方法,但是也有确定:可能会令
测试比较难懂,因为这些隐式调用不是必须的,有可能被遗漏掉。

1 public class MathDemoTest { 2 MathDemo demo; 3 @Before 4 public void setUp(){ 5 System.out.println("Set up ..."); 6 demo = new MathDemo(); 7 } 8 @After 9 public void tearDown(){ 10 System.out.println("Done..."); 11 demo = null; 12 } 13 @Test 14 public void testAdd() { 15 16 int expetected = 1; 17 int trueValue = demo.add(1, 1); 18 //断言方法 19 assertEquals("你好像写错了",expetected, trueValue); 20 } 21 @Test 22 public void testDiv() { 23 int expected = 1; 24 int trueValue = demo.div(1, 1); 25 assertEquals(expected, trueValue); 26 } 27 28 }
更深入、灵活的使用隐式方式可以参考该链接下面的例子:单元测试三种TestFixture方法比较
@Before 和 @ After 注解是作用于测试方法的,标注的方法是public void的,和普通的测试方法规则一样,但是对于每个测试
方法都需要执行一遍是非常费时的操作,此时,如果有一种注解可以在测试类开始和结束时只执行一次,而不是作用于每个测试方法,
这样可以节省很多时间。这两个注解就是 @BeforeClass 和 @AfterClass , 而且该方法必须是 Public static的。
一个测试类中可以出现几次 | 方法要求 | 运行次数 | |
@Before 和 @After | >= 0 次 | public void 的 | 作用于测试方法的,有几个测试方法就运行几次 |
@BeforeClass 和 @AfterClass | 0次 || 1次 | public static 的 | 作用于测试类的,只运行一次 |

public class AnnotationDemo { MathDemo demo; @BeforeClass public static void setUpBeforeClass(){ System.out.println("beforeclass set Up.."); } @AfterClass public static void tearDownAfterClass(){ System.out.println("afterclass Gone..."); } @Before public void setUp(){ System.out.println("Set up ..."); demo = new MathDemo(); } @After public void tearDown(){ System.out.println("Done..."); demo = null; } @Test public void add(){ assertEquals(2, demo.add(1, 1)); } @Test public void add2(){ assertEquals(1, demo.div(1, 1)); } }
上面代码的运行结果:
参数化测试
Parameterized:根据所设计的参数来执行测试。
eg .一个函数,参数有许多特殊值,或者参数分为很多个区域,如对考试分数进行分区,需要返回"优秀、良好、一般、及格、不及格",
因此在编写测试的时候,至少需要写5个测试,把这5种情况都包含进去,很麻烦。
eg. 假设某个需要被测试的方法,它有两个参数,每个参数需要设计不同的值,那么我们一开始是需要为每一个参数设计一个测试方法,
这样就很麻烦,10中case就需要10个方法,但是运用 Parameterized runner , 可以设计一个方法,多种参数来执行test case。
Run运行器
简简单单的写一个@test,其他的都不用管,JUnit框架就帮我们运行测试代码,那么框架是如何运行提交的测试代码呢?
----->Runner,在JUnit4中有很多的Runner,它们负责调用提交的测试代码,每个Runner都有自己的独特功能,所以我们可以
指定Runner来执行测试代码,在还不知道这个概念时,测试代码也是可以正常运行的,其原因是JUnit4中有一个默认的Runner
名字是BlockJUnit4ClassRunner.class ,如果没有指定Runner,系统会自动使用默认的Runner。
1 public class MathDemoTest { 2 @Test 3 public void testAdd() { 4 MathDemo demo = new MathDemo(); 5 int expetected = 1; 6 int trueValue = demo.add(1, 1); 7 //断言方法 8 assertEquals("系统使用默认的Runner",expetected, trueValue); 9 } 10 }
Vs 指定 BlockJUnit4ClassRunner.class , 这个即是JUnit4默认的Runner,效果和上面的代码一样。
1 @RunWith(BlockJUnit4ClassRunner.class) 2 public class MathDemoTest { 3 @Test 4 public void testAdd() { 5 MathDemo demo = new MathDemo(); 6 int expetected = 1; 7 int trueValue = demo.add(1, 1); 8 //断言方法 9 assertEquals("你好像写错了",expetected, trueValue); 10 } 11 @Test 12 public void testDiv() { 13 MathDemo demo = new MathDemo(); 14 int expected = 1; 15 int trueValue = demo.div(1, 1); 16 assertEquals(expected, trueValue); 17 } 18 }
从上面的例子可以知道,指定Runner使用的是 @RunWith 注释,标注在测试类上,是修饰类的,作用于该测试类中的所有测试方法。
其他特殊的Runner有:
- Suite.class 实现打包测试
- Parameterized.class 实现参数化测试
- Categories.class
- Enclosed.class
这几种Runner见随笔: JUnit4-Runner