Java 向测试类动态添加JUnit测试
我发现自己这些天写了很多很多锅炉板测试,我想以一种干净的方式优化掉很多这些基本测试,这些测试可以不费吹灰之力地添加到所有当前的测试类中 下面是一个基本的测试类:Java 向测试类动态添加JUnit测试,java,junit,junit4,Java,Junit,Junit4,我发现自己这些天写了很多很多锅炉板测试,我想以一种干净的方式优化掉很多这些基本测试,这些测试可以不费吹灰之力地添加到所有当前的测试类中 下面是一个基本的测试类: class MyClassTest { @Test public void doesWhatItDoes() { assertEquals("foo",new MyClass("bar").get()); } } 假设MyClass实现了Serializable,那么我们需要确保它确实是可序
class MyClassTest {
@Test
public void doesWhatItDoes() {
assertEquals("foo",new MyClass("bar").get());
}
}
假设MyClass实现了Serializable,那么我们需要确保它确实是可序列化的。因此,我构建了一个类,您可以对其进行扩展,该类包含一组标准测试,这些测试将与其他测试一起运行
我的问题是,例如,如果MyClass没有实现Serializable,那么类中仍然有一个序列化测试。我们可以让它在不可序列化的类中成功,但它仍然停留在测试列表中,一旦这个类开始构建,它就会变得越来越混乱
我想做的是找到一种方法,在适当的地方动态添加那些与现有测试类相关的测试。我知道有些测试可以通过一套测试服来完成,但是你必须为每个类维护两个测试类,这很快就会成为一个麻烦
如果有人知道一种不需要eclipse插件之类的东西的方法,我将永远感激
编辑:添加了我上面描述的简要示例
class MyClassTest extend AutoTest<MyClass> {
public MyClassTest() {
super(MyClass.class);
}
@Test
public void doesWhatItDoes() {
assertEquals("foo",new MyClass("bar").get());
}
}
public abstract class AutoTest<T> {
private final Class<T> clazz;
protected AutoTest(Clazz<T> clazz) {
super();
this.clazz = clazz;
}
@Test
public void serializes() {
if (Arrays.asList(clazz.getInterfaces()).contains(Serializable.class)) {
/* Serialize and deserialize and check equals, hashcode and other things... */
}
}
}
class MyClassTest扩展自动测试{
公共MyClassTest(){
超级(MyClass.class);
}
@试验
public void doesWhatItDoes(){
assertEquals(“foo”,新的MyClass(“bar”).get();
}
}
公共抽象类自动测试{
私人期末班;
受保护的自动测试(Clazz-Clazz){
超级();
this.clazz=clazz;
}
@试验
public void序列化(){
if(Arrays.asList(clazz.getInterfaces()).contains(Serializable.class)){
/*序列化、反序列化并检查equals、hashcode和其他内容*/
}
}
}
JUnit现有功能中最实用的解决方案是使用一个带注释的测试:
@Test
void followsStandardJavaLibraryProtocols() {
if (implementsInterface(Serializable.class) {
testSerialisableInterface
...
打破了TDD的各种抽象原则,但有效,没有不必要的聪明
也许,Junit可以扩展为对这种带有子测试的体系结构测试有更直接的支持,而不是简单的测试用例列表。类似于@Subtest注释的东西,它标识了一个不被直接调用的测试,而是在该测试被调用时将一个节点添加到结果树中,并使用什么参数 两个想法
想法1:
使用假设
一组用于说明关于测试有意义的条件的假设的方法。失败的假设并不意味着代码被破坏,而是测试没有提供有用的信息。默认的JUnit运行程序将忽略假设失败的测试
想法2:实施您自己的测试运行程序
看看
@RunWith
和Runner
at我觉得你的方法很有效。我没有问题
我的做法略有不同。我将创建另一个测试来测试所有可序列化类:
public class SerializablesTest {
@Test
public void serializes() {
testSerializable(MyClass.class);
testSerializable(MyClass2.class);
}
private testSerializable(Class clazz) {
// do the real test here
/* Serialize and deserialize and check equals, hashcode and other things... */
}
}
这给了你什么?对我来说,明确性。我知道我正在测试类MyClass的可序列化性。这里面没有魔法。你不需要污染你的其他测试
如果您确实需要测试所有实现可序列化的类,那么可以使用反射找到所有类
我经常使用这种方法,使用反射来构建对象。例如,我可以测试所有字段是否被正确地持久化并从数据库中重新读取。我一直在使用这种东西。您确定要单元测试实现可序列化的类是否真的可序列化吗?或者这仅仅是一个例子?是的,但是我还想测试其他一些东西,比如可空性,以及使用jsr-305注释。这在很大程度上是受Guavas测试框架的启发,但它仍然需要大量的锅炉板,我认为我们应该能够避免。IMHO,单元测试应该只关注被测试的类。如果您的对象未正确编组,功能/集成测试将捕获它。@Sahil是否确实要等到集成测试运行后才能检测此类错误?根据我的经验,这类事情确实会捕获bug,并允许您安全地重构。这太棒了,我可以用我的方法解决所有令人讨厌的问题,并且仍然保持良好的可管理性,谢谢!
public class SerializablesTest {
@Test
public void serializes() {
testSerializable(MyClass.class);
testSerializable(MyClass2.class);
}
private testSerializable(Class clazz) {
// do the real test here
/* Serialize and deserialize and check equals, hashcode and other things... */
}
}