【问题标题】:Running two same tests with different arguments使用不同的参数运行两个相同的测试
【发布时间】:2012-03-30 18:13:52
【问题描述】:

我有一个包含 15-20 个不同测试用例的测试,我想用两个不同的参数运行两次相同的测试,这些参数应该传递给测试的 BeforeClass 方法,例如:

public class TestOne {
    private static ClassToTest classToTest;

    @BeforeClass
    public static void setUp() throws Exception {
        classToTest = new ClassToTest("Argument1", "Argument2");
    }

    @Test
    public void testOne() {
    ........roughly 15 - 20 tests here
}

public class TestTwo {
    private static ClassToTest classToTest;

    @BeforeClass
    public static void setUp() throws Exception {
        classToTest = new ClassToTest("Argument3", "Argument4");
    }

    @Test
    public void testOne() {
    ........roughly 15 - 20 tests here, same as in TestOne
}

正如您所见,这两个测试之间的唯一区别在于 setup 方法,它将不同的值传递给 ClassToTest 的构造函数。我不想在两个类中复制测试方法,但更喜欢继承或其他一些智能方法在一个类中实现这一点。

【问题讨论】:

  • 简单继承应该可以正常工作。您是否尝试过将 ClassToTest 和 testOne() 移至基类?

标签: java unit-testing junit


【解决方案1】:

这似乎是 JUnit4 的 @Parameters 的完美用例;请参阅 https://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junithttp://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ 。也就是说,您必须将初始化从 setUp 方法转移到测试类的构造函数中。

【讨论】:

  • 这对我没有好处,因为我们只想要一个 ClassToTest 实例,它是一个非常重的对象。我不希望我的测试永远运行。我的意思是 ClassToTest 的一个实例,由所有测试方法共享,这就是它在 @BeforeClass 中定义的原因
  • 如果你的测试类真的很重量级......那么,你的问题就在那里。分解您的测试,直到它们更少重量级。
  • 我并不是说我的测试类很重,我要测试的类很重,因为它连接到外部系统,我们对此无能为力,事实上这个测试是集成测试以验证我们是否从该系统获得正确的数据。
  • Ewwwww。呸呸呸。 ...我可能不得不提出将被测类保存在静态变量中的邪恶解决方法,这将降低创建测试对象的成本。除此之外,我不相信有适合您的解决方案。
【解决方案2】:

对于它的价值,这里是你将如何使用TestNG

public class TestFactory {
  @Factory
  public Object[] createTests() {
    return new Object[] {
      new ClassToTest("arg1", "arg2"),
      new ClassToTest("arg3", "arg4")
    };
  }
}

public class ClassToTest {
  public ClassToTest(String arg1, String arg2) {
    this.arg1 = arg1;
    this.arg2 = arg2;
  }

  @Test
  public void testOne() {
    // use arg1 and arg2
  }
}

【讨论】:

    【解决方案3】:

    感谢大家的快速回复。这就是我最终做到的方式

    public abstract class Base {
        final HeavyObject heavy;
    
        protected Base(HeavyObject heavy) {
            this.param = param;
        }
    
        @Test
        public void test() {
            param.doSomething();
        }
    
        @Test
        .............More tests here
    
    }
    
    
    public class FirstTest extends Base{
    
        private static HeavyObject param;
    
        @BeforeClass
        public static void init() {
            param = new HeavyObject("arg1", "arg2");
        }
    
        public FirstTest() {
            super(param);
        }
    }
    
    public class SecondTest extends Base{
    
        private static HeavyObject param;
    
        @BeforeClass
        public static void init() {
            param = new HeavyObject("arg3", "arg4");
        }
    
        public FirstTest() {
            super(param);
        }
    }
    

    Base是一个包含所有测试的抽象类,FirstTest和SecondTest创建自己的具有不同参数的对象并将其传递给抽象类以使用它。

    【讨论】:

      【解决方案4】:

      根据文档 (http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html):

      子类不继承其父类的私有成员。 但是,如果超类具有公共或受保护的方法 访问它的私有字段,这些也可以被子类使用。

      【讨论】:

        【解决方案5】:

        这个怎么样:

        public class TestOne {
            private static ClassToTest classToTest1, classToTest2;
        
            @BeforeClass
            public static void setUp() throws Exception {
                classToTest1 = new ClassToTest("Argument1", "Argument2");
                classToTest2 = new ClassToTest("Argument3", "Argument4");
            }
        
            @Test
            public void testOne() {
                testOneImpl(classToTest1);
                testOneImpl(classToTest2);
            }
        
            public void testOneImpl(ClassToTest classToTest) {
                // exact samew as whatever your current testOne() test method is
            }
        
            ....
        }
        

        编辑: 或者让方法倒计时:

        public class TestOne {
            private static List<ClassToTest> classesToTest;
        
            @BeforeClass
            public static void setUp() throws Exception {
                classesToTest = new ArrayList<>;
                classesToTest.add( new ClassToTest("Argument1", "Argument2"));
                classesToTest.add( new ClassToTest("Argument3", "Argument4"));
            }
        
            @Test
            public void testOne() {
                for (ClassToTest classToTest: classesToTest) {
                    ... same test content as before
                }
            }
        

        【讨论】:

        • 记住我们有大约 20 个测试,所以需要编写 20 次 * 2 个方法
        • 我认为您担心的是代码重复,而不是方法的数量。这样就没有代码重复,意图表达简洁,关注点分离等。为每个测试方法添加另一个非常短样板方法真的很麻烦吗?当然,如果您想保持方法倒计时,您可以在每个测试方法中迭代 classToTest1classToTest2 的列表,并且该列表可以在 setUp 中定义一次。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-28
        • 1970-01-01
        • 2013-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多