如何提供JUnit4"一致性"接口的测试套件

时间:2018-02-11 15:42:49

标签: scala sbt junit4

我想为我们库中的接口提供一个测试套件,以便实现该接口的客户端可以轻松地测试其实现是否符合接口规范。

一个非常简单的例子可能如下所示:

// Library code.
abstract class LibTest(impl: LibInterface) {
  @Test
  def myTest: Unit = {
    assertTrue(impl.getTrue())
  }
}

// Client code
class MyTest extends LibTest(new MyInterfaceImpl)

然而,我们需要更多的东西,这种方法变得困难。值得注意的是:

  • 在内部参数化我们的一些测试用例(客户端不应该看到)。
  • 允许客户端传递其实现的属性。值得注意的是:
    • 支持的功能集(我们希望启用/禁用测试)。
    • 支持告诉测试如何与实现交互的属性。

在我们当前的原型中,我们通过为每个功能配置套件和参数构造函数来解决这个问题。看起来像这样:

// Library code.
abstract class LibFeatureATest(impl: LibInterface, prop: String, paramA: Boolean)
abstract class LibFeatureBTest(impl: LibInterface, prop: String)
abstract class LibFeatureABTest(impl: LibInterface, prop: String, paramA: Boolean)

// Client code:
class FeatureATest(new MyInterfaceImpl, "my_prop", true)
class FeatureATest(new MyInterfaceImpl, "my_prop", false)
class FeatureBTest(new MyInterfaceImpl, "my_prop")

class FeatureABTest(new MyInterfaceImpl, "my_prop", true)
class FeatureABTest(new MyInterfaceImpl, "my_prop", false)

这种方法存在两个主要问题:

  • 测试的参数需要在客户端。
  • 客户端需要实例化特征交互的测试。

理想情况下,我们希望在客户端中拥有类似的内容:

class MyTest extends TestSuite(new MyInterfaceImpl,
  prop = "my_prop",
  supportsA = true,
  supportsB = true)

确切的调用语法/类型是次要的(抽象方法,参数,注释)。但请注意这些额外要求:

  • 需要成为JUnit,我们不能依赖Scala特定的测试框架。
  • 需要在sbt中工作,所以一些实验性的跑步者(例如Enclosing)可能无效。
  • 我们希望避免不必要的实现继承。

我们如何在sbt上的Scala中的JUnit4中执行此操作?

2 个答案:

答案 0 :(得分:0)

您可以分别实现提供参数化和配置的JUnit规则。

可以从文件中读取配置(即客户端提供的属性),以便客户端可以单独提供,而无需更改测试本身;然后,规则将根据配置启用或禁用测试用例。

“参数化”的含义尚不清楚,但我确信你可以使用规则。它们基本上是“围绕” - 测试用例的方面。

编辑:

所以这就是我想象你的界面:

import json
file_name = "storing and reading JSON\user_number.json"
with open(file_name) as j_obj:
    num = json.load(j_obj)
    print("I know your favorite number, it's: " + str(num))

完整的单元测试就是

interface ToTest {
    int getFeature1Value(); // let's say this needs to return 1 for compliance, if feature1 is supported
    int getFeature2Value(); // so this is a feature2 method, and needs to return 2
}

但IIUC您希望客户端能够指定支持哪些功能,如果不支持,则禁用该测试用例。这就是我使用FeatureSupport注释注释测试用例的原因,这是一个

public class ComplianceTest {
    // the rule being applied, see below
    @Rule DisablingRule rule = new DisablingRule("feature_config.prop");

    @Autowired // so this would need to run in a DI environment
    ToTest sut;
    @FeatureSupport(condition = Features.Feature1) // see below
    @Test public void testFeature1() {
        assertEquals(1, sut.getFeature1Value());
    }
    @FeatureSupport(condition = Features.Feature2)
    @Test public void testFeature2() {
        assertEquals(2, sut.getFeature2Value());
    }
}

@interface FeatureSupport {
    Features getCondition();
}

这就是编写规则的设置,类似于

enum Features {
    Feature1, Feature2
}

答案 1 :(得分:0)

我错过了你的“理想情况下我们希望在客户端拥有这样的东西”,这使事情变得更容易。

public interface MyTest<T> extends Test {
    public void setSut(T toTest);
    public void setProperties(Properties props);
}

public enum Features {
    Feature1(Feature1UnitTest::new), 
    Feature2(Feature2UnitTest::new);

    private Supplier<? extends Test> createTest;
    private Features(Supplier<? extends Test> sup) {
        createTest = sup;
    }
}

public class MyTestSuite<T> extends TestSuite {
    public MyTestSuite(T toTest, Properties testProperties, Features... supported) {
        for (Features f : supported) {
            MyTest<T> test = (MyTest<T>) f.createTest();
            test.setSut(toTest);
            test.setProperties(testProperties);
            addTest(test);
        }
    }
}