Nightwatch101 #12:BDD Verify

Nightwatch.js

在上一篇 Assert 提到,.assert.verify 的 library 基本上是做相同的事情,差別只在於斷言(assertion)失敗時的處理方式。

像是這樣…

.assert:斷言失敗時,測試結束,忽略剩餘未執行的部份。

BDD Assert

.verify:斷言失敗時,會把測試失敗記綠下來,然後繼續剩餘未執行的部份。

BDD Verify

基本上我們都希望測試不要中斷,出錯的地方先幫我們記錄下來就好。那麼…就使用 .verify 改寫前面的範例吧(點此看前面到底有什麼)。

ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚

本系列文章皆使用這個專案,可以拉下來玩玩;有什麼問題都可以提出 issue


範例

檢視露天拍賣的頂層分類頁,會檢視當前網址、標題、特定元素的屬性值、元素是否存在、元素是否可見、表單元件輸入值等。

改寫後的程式碼。

module.exports = {
  'Assert Categoty Advertisements': browser => {
    browser

      // 打開指定網址
      .url('http://class.ruten.com.tw/category/main?0008')

      // 等待 `<body>` 這個元素出現
      .waitForElementVisible('body')

      // 檢視網頁標題是否為「相機、攝影機 - 露天拍賣」
      .verify.title('相機、攝影機 - 露天拍賣')

      // 檢視 .rt-header 這個 DOM element 的屬性 data-module 其值是否包含 rt-header
      .verify.attributeEquals('.rt-header', 'data-module', 'rt-header')

      // 檢視 .rt-wrap-search 這個 DOM element 的屬性 data-module 其值是否包含 page-class-main
      .verify.attributeEquals('.rt-wrap-search', 'data-module', 'page-class-main')

      // 檢視 .rt-ad-text-only .rt-ad-item:nth-child(1) 這個 DOM element 是否存在
      .verify.elementPresent('.rt-ad-text-only .rt-ad-item:nth-child(1)')

      // 檢視 .promo-bar 這個 DOM element 是否存在
      .verify.elementPresent('.promo-bar')

      // 檢視 .rt-subcategory-list .rt-subcategory-item 這個 DOM element 是否存在
      .verify.elementPresent('.rt-subcategory-list .rt-subcategory-item')

      // 檢視 #ad-flash 這個 DOM element 是否可見
      .verify.visible('#ad-flash')

      // 檢視 #ad-flash .rt-ad-item 這個 DOM element 是否存在
      .verify.elementPresent('#ad-flash .rt-ad-item')

      // 檢視 .rt-flagship 這個 DOM element 是否存在
      .verify.elementPresent('.rt-flagship')

      // 檢視 .rt-flagship 這個 DOM element 的屬性 data-module 其值是否等於 class-main-flagship
      .verify.attributeEquals('.rt-flagship', 'data-module', 'class-main-flagship')

      // 檢視 .rt-flagship .rt-ad-item 這個 DOM element 是否存在
      .verify.elementPresent('.rt-flagship .rt-ad-item')

      // 檢視 .rt-flagship .rt-ad-item:nth-child(1) 這個 DOM element 是否存在
      .verify.elementPresent('.rt-flagship .rt-ad-item:nth-child(1)')

      // 檢視 #ad-promote .promoted-item:nth-child(4) 這個 DOM element 是否存在
      .verify.elementPresent('#ad-promote .promoted-item:nth-child(4)')

      // 檢視 #ad-special .special-item:nth-child(3) 這個 DOM element 是否存在
      .verify.elementPresent('#ad-special .special-item:nth-child(3)')

      // 檢視 .hot-sale-gallery 這個 DOM element 的屬性 data-module 其值是否等於 class-main-slideshow
      .verify.attributeEquals('#ad-slideshow', 'data-module', 'class-main-slideshow')

      // 檢視 .hot-sale-gallery 這個 DOM element 的屬性 data-module 其值是否等於 class-main-gallery
      .verify.attributeEquals('.hot-sale-gallery', 'data-module', 'class-main-gallery')

      // 檢視 .hot-sale-item:nth-child(2) 這個 DOM element 是否存在
      .verify.elementPresent('.hot-sale-item:nth-child(2)')

      // 檢視 #ad-gallery .hot-sale-gallery-item 這個 DOM element 是否存在
      .verify.elementPresent('#ad-gallery .hot-sale-gallery-item')

      // 檢視 .good-shops 這個 DOM element 是否可見
      .verify.visible('.good-shops')

      // 檢視 .good-shops .rt-ad-control-item:nth-child(1) .rt-ad-control-link 這個 DOM element 的屬性 href 其值是否包含指定字串,在這裡是放網址
      .verify.attributeContains('.good-shops .rt-ad-control-item:nth-child(1) .rt-ad-control-link', 'href', 'https://point.ruten.com.tw/ADI/ap2AD/more.php?CM08')

      // 檢視 .good-shops .rt-ad-control-item:nth-child(2) .rt-ad-control-link 這個 DOM element 的屬性 href 其值是否包含指定字串,在這裡是放網址
      .verify.attributeContains('.good-shops .rt-ad-control-item:nth-child(2) .rt-ad-control-link', 'href', 'http://pub.ruten.com.tw/adb/ad01_intro.html')

      // 檢視 .good-shops .rt-ad-item 這個 DOM element 是否可見
      .verify.visible('.good-shops .rt-ad-item')

      // 檢視 #ad-featured-list .rt-ad-item 這個 DOM element 是否可見
      .verify.visible('#ad-featured-list .rt-ad-item')

      // 檢視 .top-sell 這個 DOM element 是否存在
      .verify.elementPresent('.top-sell')

      // 檢視 .top-sell .rt-ad-item 這個 DOM element 是否存在
      .verify.elementPresent('.top-sell .rt-ad-item')

      // 檢視 .shopping-mall 這個 DOM element 是否存在
      .verify.elementPresent('.shopping-mall')

      // 檢視 .shopping-mall .rt-ad-ite 這個 DOM element 是否存在
      .verify.elementPresent('.shopping-mall .rt-ad-item')

      // 檢視 .shopping-mall .rt-ad-control-item:nth-child(1) .rt-ad-control-link 這個 DOM element 的屬性 href 其值是否包含指定字串,在這裡是放網址
      .verify.attributeContains('.shopping-mall .rt-ad-control-item:nth-child(1) .rt-ad-control-link', 'href', 'https://point.ruten.com.tw/ADI/ap2AD/more.php?CS08')

      // 檢視 .shopping-mall .rt-ad-control-item:nth-child(2) .rt-ad-control-link 這個 DOM element 的屬性 href 其值是否包含指定字串,在這裡是放網址
      .verify.attributeContains('.shopping-mall .rt-ad-control-item:nth-child(2) .rt-ad-control-link', 'href', 'pub.ruten.com.tw/adb/ad02_intro.html')

      // 檢視 .rt-ad-search-keyword 這個 DOM element 是否存在
      .verify.elementPresent('.rt-ad-search-keyword')

      // 檢視 .rt-ad-search-keyword .rt-ad-item 這個 DOM element 是否存在
      .verify.elementPresent('.rt-ad-search-keyword .rt-ad-item')

      // 檢視 #search_input 這個 DOM element 其值是否為空字串
      .verify.value('#search_input', '')

      // 對 #search_input 這個 DOM element 鍵入字串「蛋糕」
      .setValue('#search_input', '蛋糕', () => {
        // 點擊送出按鈕 .rt-site-search-submit
        browser.click('.rt-site-search-submit', () => {
          // 檢視網址是否包含 s000.php
          browser.verify.urlContains('s000.php');
        });
      })

      // 結束 session,關閉瀏覽器
      .end();
  }
};

看完整範例

這裡為了檢視元素個數而去檢查最後一個元素是否存在或可見。例如,我們期待畫面有 4 個 .promoted-item 而去檢查第四個元素是否存在。

// 檢視 .promoted-item:nth-child(4) 這個 DOM element 是否存在
.verify.elementPresent('.promoted-item:nth-child(4)')

之後會改用客製化斷言指令 count,針對抓到的元素個數來判斷是否等於預期個數,相較來說更直覺易懂好用。

// 檢視 .promoted-item 是否抓到 4 個 element
.assert.count('.promoted-item', 4)

.verify.count('.promoted-item', 4)

執行測試。

nightwatch test/e2e/class/testMainCategoryVerify.js

執行結果。

BDD Verify

話說工程師都愛模組化,不要擔心亂糟糟,待之後使用 Page Objects 來改寫 (*´∀`)~♥


2018 鐵人賽網址


comments powered by Disqus