【问题标题】:Passing JUnit data between tests在测试之间传递 JUnit 数据
【发布时间】:2010-06-29 21:27:29
【问题描述】:

我刚刚在创建一些 CRUD 测试时发现,您无法在一个测试中设置数据并让它在另一个测试中读取(数据在每次测试之间设置回其初始化)。

我要做的就是 (C) 用一个测试创建一个对象,然后 (R) 用下一个测试读取它。 JUnit 是否有办法做到这一点,或者它是否在意识形态上进行了编码,使得测试不允许相互依赖?

【问题讨论】:

标签: java junit


【解决方案1】:

嗯,对于单元测试,您的目标应该是测试最小的独立代码片段,通常是逐个方法。 所以testCreate() 是一个测试用例,testRead() 是另一个。但是,没有什么可以阻止您创建 testCreateAndRead() 来同时测试这两个功能。但是,如果测试失败,那么测试在哪个代码单元上失败了?你不知道。这类测试更像是集成测试,应该区别对待。

如果你真的想做,可以创建一个静态类变量来存放testCreate()创建的对象,然后在testRead()中使用。

因为不知道你说的是哪个版本的Junit,所以我就选了一个古老的Junit 3.8:

非常丑陋但有效:

public class Test extends TestCase{

    static String stuff;

    public void testCreate(){
        stuff = "abc";
    }

    public void testRead(){
        assertEquals(stuff, "abc");
    }
}

【讨论】:

  • 一个集成测试——呃,CRUD意味着访问数据库。
  • 顺便说一下,关于静态变量的好主意,如果它有效的话。我得试试看。
  • 你能保证这行得通吗?您是否定义了 JUnit 以什么顺序可靠地执行这些测试?
  • @oldrinb ......不再是......因为它被所有测试工具采用......他们添加了多个功能,现在使其既是单元测试工具又是集成测试工具跨度>
  • @BrianAgnew 的关注是有效的,现在在最近的 JUnit 版本中是 addressed
【解决方案2】:

JUnit 提倡独立测试。一种选择是将两个逻辑测试放入一个 @Test 方法中。

TestNG 的部分创建是为了允许测试之间存在这些类型的依赖关系。它强制执行测试依赖项的本地声明——它以有效的顺序运行测试,并且不运行依赖于失败测试的测试。有关示例,请参阅http://testng.org/doc/documentation-main.html#dependent-methods

【讨论】:

  • 所以它意识形态!我以前很怕那个。我确实认为,仔细想想,有一些新的注释与测试间依赖有关,但也许我正在阅读有关 TestNG 的文章。
  • 单元测试在状态和顺序上都独立是非常理想的。 JUnit 支持理想。 TestNG 支持理想异常和实用异常。 TestNG 的作者 Cedric Beust 在下面的资料中更详细地讨论了这些问题。他与 Beck 和 Gamma 确认了 JUnit 的意图,并发现了使用静态成员解决 JUnit 方法的缺点。 * Beust 2004 年的博文beust.com/weblog/2004/02/08/junit-pain * Beust 的书“下一代 Java 测试:TestNG 和高级概念”的前几页,Addison-Wesley,2008 年。
  • 我同意所有这些,对于单元测试。但是 CRUD 测试是数据库访问,因此不是单元测试。令人遗憾的是,如此灵活和普遍的 JUnit 应该以任何方式限制它仅限于单元测试。
  • 好点。相比之下,TestNG 允许您通过“组”属性使用“数据库”或“集成”等测试类别标记测试;提供@BeforeGroup/@AfterGroup setup/teardown 方法;并支持运行或排除运行一组组。有关 Beust 幻灯片 6-11 的更多详细信息,请点击此处:qconsf.com/sf2007/file?path=/QConSF2007/slides/public/…
  • 要进行真正的 CRUDy 单元测试,必须设置测试状态(数据库)并拆除它。不幸的是,这通常很复杂且容易出错,这增加了测试开发开销,同时也增加了测试失败的噪音。设置状态的低易出错方法的一个示例是运行 SQL 脚本,而易出错的方法是使用正在测试的相同方法。不幸的是,根据项目的不同,前者几乎总是不切实际甚至是不可能的,所以对于后者,测试依赖似乎可以解决这个问题。
【解决方案3】:

JUnit 是独立的测试。但是,如果你没有办法,你可以使用“静态”实例来存储它。

static String storage;
@Test
public void method1() {
    storage = "Hello"
}

@Test
public void method2() {
    Assert.assertThat(something, is(storage));
}

【讨论】:

  • 自从我最初问到那是一件坏事,我就知道了。 ;)
【解决方案4】:

这些测试需要多少处理时间?如果不是很多,那为什么要出汗。当然你会创建一些不必要的对象,但是这需要你多少钱?

@Test
void testCreateObject() {
    Object obj = unit.createObject();
}

@Test
void testReadObject() {
    Object obj = null;
    try {
        obj = unit.createObject(); // this duplicates tests aleady done
    } catch (Exception cause) {
        assumeNoException(cause);
    }
    unit.readObject(obj);
}

【讨论】:

  • 好点。更多的是我必须考虑测试数据以确保 2 个 createObject() 的唯一性,但这可能是要走的路。
  • 我想我的一部分拒绝编写相同的“创建”代码两次。我觉得我太干了。
  • @orbfish 在不引入测试之间依赖关系的情况下,这是尽可能 DRY。 @emory 对unit.readObject 的调用应该在try 块内执行。您依靠catch 子句的内容来避免NullPointerException 或类似的东西。
【解决方案5】:

在这个基本示例中,变量在测试 A 中被更改,并且可以在测试 B 中使用

public class BasicTest extends ActivityInstrumentationTestCase2 {
    public BasicTest() throws ClassNotFoundException {
        super(TARGET_PACKAGE_ID, launcherActivityClass);        
    }

    public static class MyClass {    
        public static String myvar = null;              
        public void set(String s) {
            myvar = s;
        }               
        public String get() {
            return myvar;
        }
    }

    private MyClass sharedVar;

    @Override
    protected void setUp() throws Exception {
        sharedVar = new MyClass();
    }

    public void test_A() {
        Log.d(S,"run A");
        sharedVar.set("blah");
    }

    public void test_B() {
        Log.d(S,"run B");       
        Log.i(S,"sharedVar is: " + sharedVar.get());        
    }

}

输出结果是:

运行A

跑B

sharedVar 是:等等

【讨论】:

  • 您的示例不包含“@Test 注释”。我尝试了添加“@Test”的代码,但没有运气。你试过这个吗?我的印象是 JUnit 测试必须至少包含一个这样的注释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-01
相关资源
最近更新 更多