【问题标题】:Is there a equivalent of testNG's @BeforeSuite in JUnit 4?JUnit 4中是否有相当于testNG的@BeforeSuite?
【发布时间】:2011-12-08 17:50:00
【问题描述】:

我是测试自动化领域的新手,如果这是一个愚蠢的问题,请原谅我,但这次谷歌让我失望了。或者至少我读过的任何东西都让我更加困惑。

我在 Eclipse 中使用 JUnit 4 和 Selenium Webdriver。我有几个测试需要作为一个套件运行,也需要单独运行。目前,这些测试在单独运行时运行良好。在测试开始时,会向测试人员/用户显示一个输入框,首先询问他们希望在哪个服务器上进行测试(这是一个字符串变量,成为 URL 的一部分)以及他们希望针对哪个浏览器进行测试。在套件中运行测试时,用户在每次测试开始时都会被问到这个问题,因为显然这已被编码到他们的每个 @Before 方法中。

我如何一次获取这些值,然后将它们传递给每个测试方法?

因此,如果 server = "server1" 和 browser = "firefox" 那么 firefox 是我希望 selenium 使用的浏览器,并且对于以下所有测试方法,我希望它打开的 URL 是 http://server1.blah.com/。我一直使用单独的 @Before 方法的原因是因为每种测试方法所需的 URL 略有不同。即每个方法测试不同的页面,例如 server1.blah.com/something 和 server1.blah.com/somethingElse

测试运行良好,我只是不想继续输入值,因为测试方法的数量最终会很大。

如果在 testNG 中有更简单的方法,我也可以将我的测试转换为 testNG。我认为@BeforeSuite 注释可能有效,但现在我不确定。

非常感谢任何建议和批评(建设性的)

【问题讨论】:

    标签: eclipse testing selenium junit junit4


    【解决方案1】:

    您可以在JUnit 4 Test invocation 的答案中调整为套件设置全局变量的解决方案。

    基本上,您扩展 Suite 以创建 MySuite。这会创建一个静态变量/方法,可以从您的测试中访问。然后,在您的测试中,您检查此变量的值。如果已设置,则使用该值。如果没有,那么你得到它。这允许您运行单个测试和一组测试,但您只会询问用户一次。

    因此,您的套件将如下所示:

    public class MySuite extends Suite {
        public static String url;
    
        /**
         * Called reflectively on classes annotated with <code>@RunWith(Suite.class)</code>
         * 
         * @param klass the root class
         * @param builder builds runners for classes in the suite
         * @throws InitializationError
         */
        public MySuite(Class<?> klass, RunnerBuilder builder) throws InitializationError {
            this(builder, klass, getAnnotatedClasses(klass));
            // put your global setup here
            MySuite.url = getUrlFromUser();
        }
    }
    

    这将像这样在您的套件中使用:

    @RunWith(MySuite.class)
    @SuiteClasses({FooTest.class, BarTest.class, BazTest.class});
    

    然后,在您的测试类中,您可以在@Before/@After 中执行某些操作,或者更好地查看TestRule,或者如果您想要之前和之后的行为,请查看ExternalResource。 ExternalResource 看起来像这样:

    public static class FooTest {
        private String url;
    
        @Rule
        public ExternalResource resource= new ExternalResource() {
            @Override
            protected void before() throws Throwable {
                url = (MySuite.url != null) ? MySuite.url : getUrlFromUser();
            };
    
            @Override
            protected void after() {
                // if necessary
            };
        };
    
        @Test
        public void testFoo() {
            // something which uses resource.url
        }
    }
    

    您当然可以外部化 ExternalResource 类,并在多个测试用例中使用它。

    【讨论】:

    • 谢谢马修,这有帮助。恐怕我不得不问你一些可怕的菜鸟问题:(首先行 this(builder, klass, getAnnotatedClasses(klass)); 行不通,因为 getAnnotatedClasses(Class>)不可见。其次,我不确定在哪里定义 getUrlFromUser() .....我意识到我可能有点过头了,我会非常感谢你的耐心:)
    • 您在问题中说“向用户显示了一个输入框”这将是 getUrlFromUser,它在哪里并不重要,但在 MySuite 中可能是一个好地方。至于 this(...) 你用的是哪个版本的 JUnit?
    • 好的,我现在关注你。我正在使用 JUnit 4。这可能不相关,但我最初使用 selenium IDE 创建了测试用例,然后将它们导出为 JUnit 4 (WebDriver) 测试用例以在 eclipse 中使用它们。
    【解决方案2】:

    我认为在这里有用的 TestNG 的主要功能不仅仅是 @BeforeSuite 而是 @DataProviders,这使得使用不同的值集运行相同的测试变得微不足道(并且不需要您使用静态,这总是成为一种责任)。

    您可能还对 TestNG 的脚本支持感兴趣,这使得在测试开始之前询问用户一些输入变得微不足道,here is an example of what you can do with BeanShell

    【讨论】:

    • 不错的cmets,但他们不回答问题。
    【解决方案3】:

    对测试进行分组可能是有意义的,这样测试套件将具有相同的 @Before 方法代码,因此每个单独的测试套件都有一个测试套件。

    另一种选择可能是对每个测试使用相同的基本 url,但通过让 selenium 点击进入您要执行测试的位置导航到特定页面。

    【讨论】:

      【解决方案4】:

      如果使用@RunWith(Suite.class),您可以使用@BeforeClass(和@AfterClass)添加静态方法,这些方法将在您定义的整个套件之前(和之后)运行。见this question

      如果您指的是动态找到的整个类集,并且不使用Suite runner,这当然无济于事。

      【讨论】:

        猜你喜欢
        • 2013-12-09
        • 1970-01-01
        • 2011-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-26
        • 2017-01-08
        • 2010-10-16
        相关资源
        最近更新 更多