2012-06-25 60 views
2

我正在编写JUnit测试,用于以各种方式创建并在实体上执行操作的服务。我希望我的测试能够尝试很多不同的活动组合。我有这样的事情:写这套JUnit测试的“正确”方式是什么?

test1() { 
/** create entity **/ 
/** assert **/ 
} 

test2() { 
/** do X to entity **/ 
/** assert **/ 
} 

test3() { 
/** do X again to entity, expect failure **/ 
/** assert **/ 
} 

test4() { 
/** do Y to entity, expect success **/ 
/** assert **/ 
} 

但是,我的理解是,我不能指望JUnit进行正确的顺序测试,以及每个测试应该完全自给自足的。

但是,如果我做每一个包含自我测试,然后有很多重复的代码,事情办得相当长,而且它更难以维持......例如:

test1() { 
/** create entity **/ 
/** assert **/ 
} 

test2() { 
/** create entity **/ 
/** do X to entity **/ 
/** assert **/ 
} 

test3() { 
/** create entity **/ 
/** do X to entity **/ 
/** do X again to entity, expect failure **/ 
/** assert **/ 
} 

test4() { 
/** create entity **/ 
/** do X to entity **/ 
/** do X again to entity, expect failure **/ 
/** do Y to entity, expect success **/ 
/** assert **/ 
} 

...如果你跟着我。

所以我的问题是,写这些测试的“正确”方式是什么,所以代码干净而优雅?

谢谢,罗布

+2

我可以建议选项#3,您只有test4(){...}更多断言来记录失败的位置。 – Sam

+1

@sam当然,您不是在一次JUnit测试中提示多个断言?正确?甚至http://junit.sourceforge.net/doc/faq/faq.htm#tests_12建议每个测试一个断言 –

+0

我建议,是的。 :)根据Robert Hume测试的结果,我不认为这个建议是有帮助的。您可以说应该使用另一个测试框架来测试一系列事件或特定的使用场景。您也可以构建一个测试运行程序来维护测试用例中的顺序,但是会打破另一个常见问题解答。好的想法,但。 – Sam

回答

3

你可以调用每个测试方法来处理重复代码的设置方法。

test1() { 
setup(); 
/** create entity **/ 
/** assert **/ 
} 

test2() { 
setup(); 
/** create entity **/ 
/** do X to entity **/ 
/** assert **/ 
} 

setup(){ 
/**perform setup here*/ 
} 
5

你可以使用@Before标注的方法来初始化实体在测试中使用。 然后,使用@After带注释的方法清除/释放您的测试使用的任何资源。

你可以有:

private Entity entity; 

@Before 
public void init() { 
    entity = ... 
} 

@Test 
public void test1() { 
    // do things to entity 
    ... 
} 
+0

但是,如果一系列测试应该从检查连接开始,那么不能将此检查放在“before”子句中。 – Gangnus

1

哪个更可读的吗?

@OrderRunner 
public class EntityTest { 
    Entity e; 

    shouldBeCreatedInValidState() { 
    e = new Entity(); 
    assert(e.isValid()); 
    } 

    shouldBeWigglable() { 
    e.wiggle(); 
    assert(e.hasBeenWiggled()); 
    } 

    shouldNotBeWigglableTwice() { 
    try { 
     e.wiggle(); 
     fail("Wiggled too many times") 
    } catch(OverWiggledException e) {} 
    } 
} 

public class EnttityTest { 
    shouldBeCreatedInValidState() { 
    Entity e = new Entity(); 
    assert(e.isValid()); 
    } 

    shouldBeWigglable() { 
    Entity e = new Entity(); 
    e.wiggle(); 
    assert(e.hasBeenWiggled()); 
    } 

    shouldNotBeWigglableTwice() { 
    Entity e = new Entity(); 
    e.wiggle(); 
    try { 
     e.wiggle(); 
     fail("Wiggled too many times") 
    } catch(OverWiggledException e) {} 
    } 
} 

我的选择是后者。这个属性很容易遗漏,所以第二个“摆动”看起来就像一个单纯的摆动,对测试进行因果关系的一瞥。

如果设置/测试方法比较复杂,那么创建方法。

shouldNotBeWigglableTwice() { 
    givenAnEntity(); 
    andIWiggleIt(); 
    try { 
     whenIWiggleIt(); 
     thenItShouldThrowAnException(); 
    } catch(OverWiggledException e) {} 
    } 
相关问题