单元或集成测试可以有 getter 和 setter 吗?
Can Unit or Integretation Test have getters and setters?
我正在尝试编写集成测试,并希望在编程最佳实践、礼仪等方面以最佳方式进行编写。
首先我有一个关于如何在另一个测试中重用现有测试的问题 class 我找到了 answer in topic How to reuse existing JUnit tests in another test class?
将基础测试功能和相关成员字段移动到基础中后 class 我发现我需要保护成员字段或者我需要拥有适当的 getter 和 setter 以便我可以使用他们在继承测试 classes 中。这是一个例子:
public abstract class BaseTests {
private Class classObj; // or protected without getter/setter?
protected void somethingHelper() {
// Test something
}
protected void somethingElseHelper() {
// Test something for classObj
}
public Class getClassObj() {
return classObj;
}
public void setClassObj(Class other) {
classObj = other;
}
}
public class TestClass1 extends BaseTests {
@Test
public void testSomething() {
somethingHelper();
}
}
public class TestClass2 extends BaseTests {
@Test
public void testSomethingAndSomethingElse() {
somethingHelper();
ClassObj obj = new ClassObj();
// set obj member fields
// and then test something else
setClassObj(obj); // or classObj = obj;?
somethingElseHelper();
}
}
我的问题是:
- 在基础测试 class 中使用成员字段并在继承测试 classes 中使用它们是一个好习惯吗?
- 如果是,哪个更好:受保护的成员字段或 getters/setters?
- 如果不是,是否有其他方法可以实现我想要的示例?
只要您牢记单元测试是关于隔离行为和测试特定工作单元,使用吸气剂不一定是坏习惯。之后,您应该确保您的 getter 始终返回对象的新实例,而不是将相同的副本分发给所有单元测试方法。
共享对象会在单元测试中引起很多问题。大多数测试运行器并行执行测试,并且不保证顺序执行。您的测试很可能会修改对象,因此共享对象可能会以不可预知的方式破坏其他测试。
我经常创建小型工厂方法来创建我在所有测试中使用的对象。特别是对于正在测试的特定class。
public ClassUnderTest GetNewClassUnderTest()
{
return new ClassUnderTest("My favorite string", 1234);
}
就将测试功能分解为辅助方法而言,我不想那样做。它使测试代码难以快速扫描。如果是像一两行代码这样简单的东西,我总是将它内嵌在我的测试中。除此之外,我开始考虑将我的测试重构为更简单的东西,如果可能的话。
编辑:我也强烈推荐阅读 The Art of Unit Testing。这是一本很棒的书,其中有很多关于构建和构建单元测试的好建议。
如果可能的话,我会在你的单元测试中完全避免状态。不要弄乱属性,而是让派生测试覆盖一个工厂函数,该函数生成测试所需的任何东西,并让通用测试调用该函数。
如果无法避免属性,请考虑是否可以在构造函数中设置它们。然后派生测试需要使用适当的值调用 super
构造函数。
如果这也不起作用,使用 protected
setter 似乎是下一个尝试的解决方案。或者重构您的测试,使上述方法之一起作用。
Is it good practice...
没有看到 referenced question 的第二个答案。
If no, is there another way to achieve what I wanted in example?
避免继承状态并将辅助方法重构为具有静态辅助方法的 class。即
CUnitTestHelper.createTestCustomer()
CUnitTestHelper.assertEqual(Customer customrer1, Customer customrer2)
。
这背后的原理叫做Composition_over_inheritance
Jay Fields ( se-radio podcast ) 指出在编写单元测试时有一些不同的规则。
当然你还是应该尽量避免代码重复。但是决定一个单元测试是否有用的主要因素是……你需要多少时间来理解一个失败的测试。
换句话说:理想情况下,测试 class 中的任何测试方法或套件都是相互独立的。您只读了那个方法;你明白它在做什么;你看看失败;你找到了你需要的一切。
将其与存在(复杂)耦合的解决方案进行比较;例如,因为您的具体测试方法依赖于很多东西,这些东西甚至来自 class 的 之外;例如通过继承。
但正如其他人所说:这在很大程度上取决于您和您的团队。您需要大量经验才能创建真正有用的测试;并且没有简单的规则可以保证在盲目遵循时会取得好的结果。
我正在尝试编写集成测试,并希望在编程最佳实践、礼仪等方面以最佳方式进行编写。
首先我有一个关于如何在另一个测试中重用现有测试的问题 class 我找到了 answer in topic How to reuse existing JUnit tests in another test class?
将基础测试功能和相关成员字段移动到基础中后 class 我发现我需要保护成员字段或者我需要拥有适当的 getter 和 setter 以便我可以使用他们在继承测试 classes 中。这是一个例子:
public abstract class BaseTests {
private Class classObj; // or protected without getter/setter?
protected void somethingHelper() {
// Test something
}
protected void somethingElseHelper() {
// Test something for classObj
}
public Class getClassObj() {
return classObj;
}
public void setClassObj(Class other) {
classObj = other;
}
}
public class TestClass1 extends BaseTests {
@Test
public void testSomething() {
somethingHelper();
}
}
public class TestClass2 extends BaseTests {
@Test
public void testSomethingAndSomethingElse() {
somethingHelper();
ClassObj obj = new ClassObj();
// set obj member fields
// and then test something else
setClassObj(obj); // or classObj = obj;?
somethingElseHelper();
}
}
我的问题是:
- 在基础测试 class 中使用成员字段并在继承测试 classes 中使用它们是一个好习惯吗?
- 如果是,哪个更好:受保护的成员字段或 getters/setters?
- 如果不是,是否有其他方法可以实现我想要的示例?
只要您牢记单元测试是关于隔离行为和测试特定工作单元,使用吸气剂不一定是坏习惯。之后,您应该确保您的 getter 始终返回对象的新实例,而不是将相同的副本分发给所有单元测试方法。
共享对象会在单元测试中引起很多问题。大多数测试运行器并行执行测试,并且不保证顺序执行。您的测试很可能会修改对象,因此共享对象可能会以不可预知的方式破坏其他测试。
我经常创建小型工厂方法来创建我在所有测试中使用的对象。特别是对于正在测试的特定class。
public ClassUnderTest GetNewClassUnderTest()
{
return new ClassUnderTest("My favorite string", 1234);
}
就将测试功能分解为辅助方法而言,我不想那样做。它使测试代码难以快速扫描。如果是像一两行代码这样简单的东西,我总是将它内嵌在我的测试中。除此之外,我开始考虑将我的测试重构为更简单的东西,如果可能的话。
编辑:我也强烈推荐阅读 The Art of Unit Testing。这是一本很棒的书,其中有很多关于构建和构建单元测试的好建议。
如果可能的话,我会在你的单元测试中完全避免状态。不要弄乱属性,而是让派生测试覆盖一个工厂函数,该函数生成测试所需的任何东西,并让通用测试调用该函数。
如果无法避免属性,请考虑是否可以在构造函数中设置它们。然后派生测试需要使用适当的值调用 super
构造函数。
如果这也不起作用,使用 protected
setter 似乎是下一个尝试的解决方案。或者重构您的测试,使上述方法之一起作用。
Is it good practice...
没有看到 referenced question 的第二个答案。
If no, is there another way to achieve what I wanted in example?
避免继承状态并将辅助方法重构为具有静态辅助方法的 class。即
CUnitTestHelper.createTestCustomer()
CUnitTestHelper.assertEqual(Customer customrer1, Customer customrer2)
。
这背后的原理叫做Composition_over_inheritance
Jay Fields ( se-radio podcast ) 指出在编写单元测试时有一些不同的规则。
当然你还是应该尽量避免代码重复。但是决定一个单元测试是否有用的主要因素是……你需要多少时间来理解一个失败的测试。
换句话说:理想情况下,测试 class 中的任何测试方法或套件都是相互独立的。您只读了那个方法;你明白它在做什么;你看看失败;你找到了你需要的一切。
将其与存在(复杂)耦合的解决方案进行比较;例如,因为您的具体测试方法依赖于很多东西,这些东西甚至来自 class 的 之外;例如通过继承。
但正如其他人所说:这在很大程度上取决于您和您的团队。您需要大量经验才能创建真正有用的测试;并且没有简单的规则可以保证在盲目遵循时会取得好的结果。