異步校驗工具awaitility快速入門

xhwm7111 7年前發布 | 11K 次閱讀 Java 測試技術 Java開發

1.背景

在編寫自動化測試用例過程中,往往會遇見被測代碼有異步或者隊列處理的中間過程;如果需要校驗這部分結果,必須等待異步操作結束或隊列消費完,而這個中間等待的時間是不確定的,常常是根據經驗值設定,通過 Thread.sleep(經驗值) ,而這個時間通常會設置成最長的那次時間,但是可能99%次這個異步操作都低于這個最長的時間,這就造成了每次執行這個測試用例都花費了異步任務最長的那次時間。

現介紹一款開源工具awaitility: https://github.com/awaitility/awaitility ,該工具提供輪詢的方式,判斷操作是否完成,以最短的時間獲取異步任務結果。

2.入門

awaitility支持Java、Scala、Groovy,本文以Java介紹。

maven工程在pom.xml添加awaitility依賴:

<dependency>
      <groupId>org.awaitility</groupId>
      <artifactId>awaitility</artifactId>
      <version>2.0.0</version>
      <scope>test</scope>
</dependency>

3.實例

測試類import相關Class:

import java.util.concurrent.Callable;
import static java.util.concurrent.TimeUnit.*;

import static org.awaitility.Awaitility.; import static org.awaitility.Duration.; import static org.awaitility.pollinterval.FibonacciPollInterval.*;</code></pre>

構造一個異步任務:

interface CounterService extends Runnable {
        int getCount();
    }
    // 每隔1s, count累加1
    class CounterServiceImpl implements CounterService {
        private volatile int count = 0;
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for(int index = 0; index < 5; index++) {
                            Thread.sleep(1000);
                            count += 1;
                        }
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
        }
        public int getCount() {
            return count;
        }
    }

3-1.默認等待時間

await().until(Callable conditionEvaluator)最多等待10s直到conditionEvaluator滿足條件,否則ConditionTimeoutException。

@Test
    public void testAsynchronousNormal(){
        final CounterService service = new CounterServiceImpl();
        service.run();
        try{
            // 默認10s, 如果在這時間段內,條件依然不滿足,將拋出ConditionTimeoutException
            await().until(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return service.getCount() == 5;
                }
            });
        } catch (Exception e) {
            Assert.fail("測試代碼運行異常:" + e.getMessage() + ",代碼位置:" + e.getStackTrace()[0].toString());
        }
    }

默認超時時間為10s, 可通過setDefaultTimeout()自定義默認超時時間。

3-2.最多等待

await().atMost() 設置最多等待時間,如果在這時間內條件還不滿足,將拋出ConditionTimeoutException。

@Test
    public void testAsynchronousAtMost(){
        final CounterService service = new CounterServiceImpl();
        service.run();
        try{
            // 指定超時時間3s, 如果在這時間段內,條件依然不滿足,將拋出ConditionTimeoutException
            await().atMost(3, SECONDS).until(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return service.getCount() == 5;
                }
            });
        } catch (Exception e) {
            Assert.fail("測試代碼運行異常:" + e.getMessage() + ",代碼位置:" + e.getStackTrace()[0].toString());
        }
    }

3-3.至少等待

await().atLeast() 設置至少等待時間;多個條件時候用and()連接。

@Test
    public void testAsynchronousAtLeast(){

    final CounterService service = new CounterServiceImpl();
    service.run();

    try{
        // 指定至少1s, 最多3s, 如果在這時間段內,條件依然不滿足,將拋出ConditionTimeoutException
        await().atLeast(1, SECONDS).and().atMost(3, SECONDS).until(new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return service.getCount() == 2;
            }
        });

    } catch (Exception e) {
        Assert.fail("測試代碼運行異常:" + e.getMessage() + ",代碼位置:" + e.getStackTrace()[0].toString());

    }
}</code></pre> 

3-4.forever等待

forever等待,不推薦使用,可能導致死循環。

await().forever().until(new Callable<Boolean>() {
                @Override
                public Boolean call() throws Exception {
                    return service.getCount() == 6;
                }
            });

3-5.輪詢

with().pollInterval(ONE_HUNDRED_MILLISECONDS).and().with().pollDelay(50, MILLISECONDS) that is conditions are checked after 50ms then 50ms+100ms。

@Test
    public void testAsynchronousPoll(){
        final CounterService service = new CounterServiceImpl();
        service.run();
        try{
            // 輪詢查詢,pollInterval每隔多少時間段輪詢, pollDelay每次輪詢間隔時間
            with().pollInterval(ONE_HUNDRED_MILLISECONDS).and().with().pollDelay(50, MILLISECONDS).await("count is greater 3").until(
                    new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            return service.getCount() == 4;
                        }
                    });
        } catch (Exception e) {
            Assert.fail("測試代碼運行異常:" + e.getMessage() + ",代碼位置:" + e.getStackTrace()[0].toString());
        }
    }

3-6.Fibonacci輪詢

with().pollInterval(fibonacci(SECONDS))非線性輪詢,按照fibonacci數輪詢。

@Test
    public void testAsynchronousFibonacciPoll(){
        final CounterService service = new CounterServiceImpl();
        service.run();
        try{
            // 使用fibonacci數作為間隔數1,1,2,3,5,8,..., 默認單位milliseconds         with().pollInterval(fibonacci(SECONDS)).await("count is greater 3").until(
                    new Callable<Boolean>() {
                        @Override
                        public Boolean call() throws Exception {
                            return service.getCount() == 4;
                        }
                    });
        } catch (Exception e) {
            Assert.fail("測試代碼運行異常:" + e.getMessage() + ",代碼位置:" + e.getStackTrace()[0].toString());
        }
    }

 

來自:http://blog.csdn.net/neven7/article/details/55004939

 

 本文由用戶 xhwm7111 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!