在测试类中复制代码是“糟糕的”吗?如你所见,我将驾驶记录添加到驾驶记录中,以便在多种方法中进行测试。将它提取到私有帮助器方法是否更好?或者更清楚地保持它是否像它一样?在这种情况下你会怎么做?
@Test
public void shouldRemoveAllDrivingRecords() {
Duration duration1 = new Duration(1, 30, 45);
Duration duration2 = new Duration(2, 50, 12);
DrivingRecord drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
DrivingRecord drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");
drivingLog.addDrivingRecord(drivingRecord1);
drivingLog.addDrivingRecord(drivingRecord2);
drivingLog.removeAllDrivingLogs();
assertEquals(0, drivingLog.numberOfDrivingRecords());
}
@Test
public void shouldSumTheDistanceDriven() {
Duration duration1 = new Duration(1, 30, 45);
Duration duration2 = new Duration(2, 50, 12);
DrivingRecord drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
DrivingRecord drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");
drivingLog.addDrivingRecord(drivingRecord1);
drivingLog.addDrivingRecord(drivingRecord2);
double expectedDistanceDriven = drivingRecord1.getDistance() + drivingRecord2.getDistance();
double totalDistanceDriven = drivingLog.getDistanceDriven();
assertEquals(expectedDistanceDriven, totalDistanceDriven, 0.1);
}
答案 0 :(得分:7)
在任何地方复制代码都是“坏事”。此代码是否因某种原因而重复,或仅仅是为了方便。如果有一个原因,你想要在两者中使用相同的数据并以相同的方式添加它,那么一个小的“设置”方法是有意义的。
答案 1 :(得分:7)
我不敢同意大多数答案,对我来说测试代码不与生产代码相同。当然,测试代码应该像生产代码一样受到关注和关注,因为它是整体开发工作的一部分,但它们的性质不同。我不会重复自己,而是指出我的另一个答案:Is it OK to copy past unit test when logic is the same。
那就是说,重复 测试数据的创建是不好的。更好的方法是考虑为测试而精心创建的数据集,并支持测试大多数情况。可以使用setUp
方法创建此数据集。如有必要,可以有多个测试数据集,涵盖业务规则的变体。创建有用的测试数据集并不容易,但值得花一些时间。此外,可以从JSON等加载测试数据。在某些情况下,它更容易维护。
单元测试通常不应相互依赖。但经常,测试用例确实相互依赖。例如,要测试列表,可以测试add()
是否有效,isEmpty()
是否有效,remove()
是否有效。测试remove()
假设add()
有效。对于这种情况,您可以使用JExample,一个单元测试框架,您可以使用它来“链接”测试。
答案 2 :(得分:6)
您可以使用@org.junit.Before
注释方法并初始化该方法中的变量:
public class DrivingLogTest {
//suposing DrivingLog class...
private DrivingLog drivingLog;
private Duration duration1;
private Duration duration2;
private DrivingRecord drivingRecord1;
private DrivingRecord drivingRecord2;
@Before
public void setUp() {
drivingLog=new DrivingLog();
duration1 = new Duration(1, 30, 45);
duration2 = new Duration(2, 50, 12);
drivingRecord1 = new DrivingRecord(230.0, duration1, "This was a long trip");
drivingRecord2 = new DrivingRecord(300.0, duration2, "This trip is even longer.");
drivingLog.addDrivingRecord(drivingRecord1);
drivingLog.addDrivingRecord(drivingRecord2);
}
@Test
public void shouldRemoveAllDrivingRecords() {
drivingLog.removeAllDrivingLogs();
assertEquals(0, drivingLog.numberOfDrivingRecords());
}
@Test
public void shouldSumTheDistanceDriven() {
double expectedDistanceDriven = drivingRecord1.getDistance() + drivingRecord2.getDistance();
double totalDistanceDriven = drivingLog.getDistanceDriven();
assertEquals(expectedDistanceDriven, totalDistanceDriven, 0.1);
}
}
答案 3 :(得分:2)
单元测试代码是生产代码,因此如上面的答案中所述,应避免所有代码重复。
我通常要么使用@Before方法进行所有变量初始化,要么使用可以在多个单元测试/项目之间共享的TestUtility类。
答案 4 :(得分:1)
代码重复总是很糟糕,没有问号。
为了避免这种情况,请编写可重用的测试场景(实现场景并接受参数的私有方法),然后使用带有特定参数的@Test
注释注释的方法调用它。
@Test
public void shouldRemoveAllDrivingRecords() {
theTest(0);
}
@Test
public void shouldSumTheDistanceDriven() {
theTest(0.1);
}
如果需要,您还可以创建TestSuites。这允许您使用不同的参数运行测试组。
答案 5 :(得分:1)
我认为我们应该始终将它提取到setUp()
方法,如果该类中的所有测试方法都需要该代码,或者其他方式是私有帮助方法。
答案 6 :(得分:1)
另见Meszaros'XUnit Test Patterns,其中包含测试代码重复的部分。
@Before
是给定片段的方法。
答案 7 :(得分:0)
我也在JUnit中关注DRY原则!我甚至是编写助手或构建器类来执行重复任务。一个好的Junit方法应该首先只包含数据,因此很明显测试什么没有污染如何它被测试。
答案 8 :(得分:0)
将所有常见配置提取到@before。你也可以使用参数,@ Parametrized或我的项目:zohhak,例如
@Before
public void prepareBank() {
...
}
@TestWith({
"25 USD",
"38 GBP",
"null"
})
public void testMethod(Money money) {
...
}