9

自動化された Selenium テストの既存のシステムを改善しようとしています。私の目標は、接続の問題のために失敗したテストを繰り返すことです。このスレッドを見つけてフォローしようとしました失敗したJUnitテストをすぐに再実行する方法は? それは非常に有用であることがわかりました。

私の場合、スイートはクラスで構成されているため、@Rule を @ClassRule に置き換えて、@Before および @After の部分も試行するたびに繰り返すようにしました。無知で申し訳ありませんが、このルールはどこに置くべきですか? 私のスイートクラスで?または、テストを表すクラスで?

4

4 に答える 4

5

私は、失敗した JUnit テストをすぐに再実行する方法の元の回答者です?

私の理解が正しければ、あなたが抱えている問題は@Before、 のコードの前に実行されRetryRule@Afterその後に実行されることが原因です。

したがって、現在の動作は次のようになります。

@Before
@Retry
test code
@Retry
@After

@Beforeただし、ルールとしてandを実装できます-まさにそれを@After行うルールExternalResourceがあります。原則として、次のように実装@Beforeします。@After

@Rule public ExternalResource beforeAfter = new ExternalResource() {
    public void before() {
        // code that was in @Before
    }

    public void after() {
        // code that was in @After
    }
}

@Beforeその後、 andは必要ありません@Afterその後、 RuleChainを使用してこれらのルールをチェーンできます。これにより、ルールの実行順序が強制されます。

@Rule public RuleChain chain= RuleChain
                       .outerRule(new LoggingRule("outer rule")
                       .around(new LoggingRule("middle rule")
                       .around(new LoggingRule("inner rule");

したがって、最終的な解決策は次のようになります。

private ExternalResource beforeAfter = ...
private RetryRule retry = ...

@Rule public RuleChain chain = RuleChain
                               .outerRule(retry)
                               .around(beforeAfter);

を使用している場合は、との注釈はRuleChain必要なくなりますが、 では必要になることに注意してください。@RuleExternalResourceRetryRuleRuleChain

于 2015-01-21T09:45:01.490 に答える
4

これが、質問で言及されたものに基づく私の解決策です。

これは@RuleFailedRuleと RetryRule の組み合わせです@ClassRule

public class RetryTest
{
    public static class FailedRule implements TestRule
    {       
        @Override
        public Statement apply(final Statement base, final Description description)
        {
             return new Statement()
             {
                    @Override
                    public void evaluate() throws Throwable
                    {
                        try
                        {
                            base.evaluate();
                        }
                        catch (Throwable t)
                        {
                            System.out.println(description.getDisplayName() + " failed");
                            retry.setNotGood();
                            if (retry.isLastTry())
                            {
                                System.out.println("No more retry !");
                                throw t;
                            }
                            else
                            {
                                System.out.println("Retrying.");
                            }
                        }
                    }
            };
        }
    }

    public static class RetryRule implements TestRule
    {
        private int retryCount, currentTry;

        private boolean allGood = false;

        public RetryRule(int retryCount)
        {
            this.retryCount = retryCount;
            this.currentTry = 1;
        }

        public boolean isLastTry()
        {
            return currentTry == retryCount;
        }

        public void setNotGood()
        {
            allGood = false;
        }

        public Statement apply(final Statement base, final Description description)
        {
            return new Statement()
            {
                @Override
                public void evaluate() throws Throwable
                {
                    // implement retry logic here
                    for (; currentTry <= retryCount && !allGood; currentTry++)
                    {
                        allGood = true;
                        System.out.println("Try #" + currentTry);
                        base.evaluate();
                    }
                }
            };
        }
    }

    @ClassRule
    public static RetryRule retry = new RetryRule(3);

    @Rule
    public FailedRule onFailed = new FailedRule();

    @BeforeClass
    public static void before()
    {
        System.out.println("Before...");
    }

    @AfterClass
    public static void after()
    {
        System.out.println("...After\n");
    }

    @Test
    public void test1()
    {
        System.out.println("> test1 running");
    }

    @Test
    public void test2()
    {
        System.out.println("> test2 running");
        Object o = null;
        o.equals("foo");
    }
}

それは与えます :

Try #1
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After

Try #2
Before...
> test1 running
> test2 running
test2(RetryTest) failed
Retrying.
...After

Try #3
Before...
> test1 running
> test2 running
test2(RetryTest) failed
No more retry !
...After

o.equals("foo");inにコメントしている場合test2、最初の try ですべてが正常に実行されます。

Try #1
Before...
> test1 running
> test2 running
...After 
于 2015-01-19T17:15:33.447 に答える
0

または属性でテスト名自体を装飾します。@After@Afterclass

@After
@Test
@Category(SmokeTests.class)
public void testProductPageOnly() throws TimeoutException {
   //Some tests here.
}

@Afterclass
public static void SomeTest {
   //Some test here.
}

注意すべき点は、@Afterclass常に実行されます。@Beforeclass例外をスローするを使用している場合でも。

于 2013-05-24T16:25:31.250 に答える