<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經轉移至github,大家請訪問 http://qaseven.github.io/

    2013年度持續集成實踐小結[2] —單元測試

      前文提到,在UI自動化之外,我們著力探索了如何實施單元測試(unit test
      相對于UI自動化,單元測試方面的實踐還是不夠充分的,因此,這里也只是小結一下我們的經驗
      概述
      首先明確一下,此處單元測試概念與經典意義有所不同,泛指所有:
      由開發工程師編寫的,可以在開發本地一鍵運行的,運行時間在分鐘級別的測試用例,用例執行會依賴不多的,但往往也是穩定可靠的外部環境
      測試框架一般使用TestNg而不是JUnit,主要原因在于TestNg的 DataProvider 功能很給力,非常適合用例須要覆蓋多分支的場景
      用例組織原則:
      一個測試類對應一個功能類: funcOneTest.java 對應于 funcOne.java
      若干個測試方法對應一個功能方法:test_funcOne_smoke() & test_funcOne_normal() & test_funcOne_error() 對應于 funcOne()
      用例分類約定
      還是以 超市購物 為背景,寫幾個Demo用例
      Δ冒煙型用例 – 甲
    @Test(description = "getNewestItems_冒煙_獲取最新商品并檢查若干關鍵屬性")
    public void test_getNewestItems_smoke() {
    List<ItemVo> itemList = itemBean.getNewestItems(1);
    Assert.assertTrue(itemList.size() == 16,        "size應該是16");
    for (ItemVo vo : itemList) {
    Assert.assertTrue(vo.getName() != null,     "name不能為空");
    Assert.assertTrue(vo.getPrice() != null,    "price不能為空");
    }
    }
      說明:
      顧名思義,就是在用例中簡單調用一下被測方法(method),主要是為了跑通流程,拒絕Block級別問題
      實踐中,推薦 伴隨著功能開發,隨時編寫冒煙用例,功能代碼與冒煙用例一起提交代碼庫
      對于一些復雜的功能,功能開發的過程也是一個持續重構的過程,編碼前期完成的冒煙用例,可以有效起到安全網作用
      Δ冒煙型用例 – 乙
    @Test(description = "enter_and_leave_market_冒煙_進入與離開超市")
    public void test_enter_and_leave_market_smoke() {
    Custom tom = new Custom("Tom");
    tom.enterMarket();
    Assert.assertTrue(Custom.isAtMarket(tom),   "tom應該在超市內");
    tom.leaveMarket();
    Assert.assertFalse(Custom.isAtMarket(tom),  "tom應該不在超市");
    }
      說明:
      這個用例把進入超市及離開超市這兩個(強相關的)接口串起來了,目的在于走通流程
      實踐中,建議 將新模塊(函數)與其強相關的模塊(函數)盡早進行簡單的集成測試以提前發現一些問題

     Δ正常流程用例
    @Test(description = "addToCart_正常流程_往購物車內添加各種類型數目的商品", dataProvider = "test_addToCart_normal_data")
    @Rollback
    public void test_addToCart_normal(String caseNote, long itemId, int count) {
    Custom tom = new Custom("Tom");
    this.setCustom(tom);
    cartBean.addToCart(itemId, count);
    Item item = tom.getCart.getItems.get(0);    // 獲取購物車中的第一項商品
    Assert.assertEquals(item.getId,      itemId,  "itemId is wrong");
    Assert.assertEquals(item.getCount,   count,   "count is wrong");
    }
    @DataProvider
    public Object[][] test_addToCart_normal_data() {
    return new Object[][] {
    // caseNote,                    itemId,     count
    {"Milk  - just a dozen",        39001L,     12,  },
    {"Bread - huge number",         116001L,    999},
    {"Bean  - less then 10",        1018100L,   2},
    };
    }
      說明:
      這個示例代碼演示了如何測試addToCart()的功能,假定這個方法內部有十分復雜的業務邏輯,我們須要覆蓋各種場景
      可以看到,正常流程用例與冒煙用例其實差不多,不同的是,正常流程用例會覆蓋更多分支,冒煙用例則一般是走通流程就行
      這個用例使用了@Rollback標簽,用例執行后會回滾數據,而不會真正往數據庫內插入數據;這個功能十分有用,可以大大減少數據準備與清理的工作;至于@Rollback背后的實現原理,此處暫時按下不表
      測試參數使用TestNg的@DataProvider組織起來,每一行都是一組測試數據,覆蓋一種測試分支
      測試參數的第一列建議設置為caseNote,簡單闡述用例的意圖,可以有效提升用例可讀性
      Δ異常流程用例
    @Test(description = "addToCart_異常流程_往購物車內添加參數非法的商品", dataProvider = "test_addToCart_error_data")
    @Rollback
    public void test_addToCart_error(String caseNote, long itemId, int count, int expectedErrorCode) {
    Custom tom = new Custom("Tom");
    this.setCustom(tom);
    try {
    cartBean.addToCart(itemId, count);
    Assert.fail();
    } catch (Exception e) {
    Assert.assertEquals(e.getErrorCode, expectedErrorCode);
    }
    }
    @DataProvider
    public Object[][] test_addToCart_error_data() {
    return new Object[][] {
    // caseNote,                        itemId,     count,  expectedErrorCode
    {"iPad       - 0 count",            39001L,     0,      Cart.ZERO_COUNT},
    {"MacBookPro - more then stock",    116001L,    1024,   Cart.MORE_THAN_STOCK},
    {"no such item",                    0L,         1L,     Cart.NO_SUCH_ITEM}
    };
    }
      說明:
      如果不同的異常輸入會有相應的 errorCode 的話, 可以把errorCode當成測試數據的一項參數傳進去

     Δ特殊場景 & 復雜流程
      個別特殊場景,不方便使用@DataProvider合并的復雜流程,可以單獨創建一個用例進行測試,函數命名的時候注明一下,例如:
      test_addToCart_error_withoutEnoughMoney() – 鈔票不夠
      test_addToCart_normal_mergeMultiCarts() – 合并多個購物車
      Δ前事不忘,后事之師
      出過Bug的地方(及其周邊)補充單元測試覆蓋,由單元測試幫你記住前事 – test_funcOne_issue12345_bugfix()
      用例編寫流程
      用例編寫順序:
      開發新功能時,同步編寫冒煙測試,用于自測及調試,功能代碼與冒煙用例一起提交 – test_funcOne_smoke()
      稍晚,補充更多分支覆蓋的正常流程用例,相當于進行又一輪自測 – test_funcOne_normal()
      最后,補充異常流程和特殊(復雜)場景用例 – test_funcOne_error() & test_funcOne_specialScenario()
      之所以這樣安排,一個很重要的原因是希望 保持主干及正常流程的暢通,確保開發及測試不會Block
      此外:
      盡量把單個開發任務切分成多個小功能點,頻繁提交,穩扎穩打,配合Jenkins & Sonar,多跑單元測試和靜態代碼檢查,問題早發現早處理
      前事不忘,后事之師,出過Bug的地方補充單元測試
      補遺
      單元測試與靜態代碼檢查(static analysis, SA)是一對好基友,兩者可以統一顯示在Sonar上面,在實踐中往往一起考察
      關于Sonar,實乃居家必備,代碼度量之利器,以后會另外講述,這里先貼個圖:
    相關文章:

    posted on 2013-12-13 09:49 順其自然EVO 閱讀(214) 評論(0)  編輯  收藏 所屬分類: selenium and watir webdrivers 自動化測試學習

    <2013年12月>
    24252627282930
    1234567
    891011121314
    15161718192021
    22232425262728
    2930311234

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲制服丝袜中文字幕| 亚洲一区影音先锋色资源| 亚洲久悠悠色悠在线播放| 99re视频精品全部免费| 久久亚洲精品人成综合网| 国产成人精品免费久久久久| 人人狠狠综合久久亚洲88| 91在线视频免费观看| 精品久久香蕉国产线看观看亚洲| 一个人免费观看视频在线中文| 亚洲国产一区视频| 国产黄色片免费看| 亚洲国产精品乱码一区二区| 无码人妻AV免费一区二区三区| 亚洲一区二区中文| 欧洲精品成人免费视频在线观看| 亚洲色在线无码国产精品不卡| 国产精品无码一区二区三区免费 | 国内精品免费麻豆网站91麻豆| 亚洲成a人不卡在线观看| 在线天堂免费观看.WWW| 亚洲男人的天堂网站| 亚洲AV成人精品日韩一区18p| 国产精品成人啪精品视频免费| 亚洲s色大片在线观看| 真人做人试看60分钟免费视频| 成人亚洲国产va天堂| 亚洲国产成人VA在线观看| a毛片在线还看免费网站| 亚洲最新在线视频| 全部免费国产潢色一级| 在线看片免费人成视频福利| 亚洲五月综合缴情婷婷| 亚洲精品国产综合久久一线| 免费无码中文字幕A级毛片| 亚洲熟妇少妇任你躁在线观看| 亚洲成AV人网址| 69av免费观看| 免费的黄网站男人的天堂 | 亚洲男人的天堂www| **aaaaa毛片免费同男同女|