iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 30
0
Modern Web

Angular新手村學習筆記(2019)系列 第 30

Day30_Cypress.io(ng conf 2019)

  • 分享至 

  • xImage
  •  

明天還會再寫一篇來完結,已經灌水滿30篇了,今年就不寫沒營養的心得囉,
雖然一路寫來文章雖然品質低下,但真的覺得學好多!!
尤其是看ng conf 2019講者的分享時,竟然不會覺得很難
真的要感謝每位Angular Taiwan的講者,尤其是Kevin大大的打底
不過讀書會影片雖然優質,但點閱率大都只有100~200,蠻可惜的~

今天是「Day19_Cypress.io - 優雅的E2E測試」的延申學習

(ng conf 2019)
Avoiding The Suck Of Testing Using Cypress.io | Joe Eames & Jesse Sanders
https://www.youtube.com/watch?v=GH9Dvo_BYkk

原始碼
https://github.com/jessesanders/ngdoc

簡介:

  • Jesse Sanders跟Joe Eames大大會展示test strategy fails的原因以及如何更有效率的測試app
  • 包含cypress的安裝、設定、實作多種測試方案
  • 本動手研討會將指導您完成多種測試方案,這些方案將為您提供處理即使是最複雜的測試用例所需的技能

超棒的內容!!!

E2E Testing Tools

  • Selenium
  • WebDriver
  • Protractor
  • Nightwatch

E2E的困難之處?(Challenges)

  • Snapshot at a moment in time

  • Edge cases

  • Cryptic errors/stack traces

  • No dev tools during tests

  • 安裝Cypress

npm install cypress --save-dev

# or 使用schematic建新專案
# 會幫你移除angular內建的protractor
ng new @briebug/cypress-schematic
  • 執行Cypress
npx cypress open
# 就會去跑 CY global object,幾乎都是靠這個大物件在跑cypress
# 測試畫面非常的友善

看程式

cypress.json 設定要測的網站

{
  "baseUrl": "http://localhost:4200"
}

寫整合測試,測試案例
ngdoc/cypress/integration/articles.spec.ts

describe('Articles', () => {
  beforeEach(() => {
    cy.visit('/'); // 一開始去讀網頁
  });

  it('should load when home page loads', () => {
    cy.get('app-article').should('have.length.greaterThan', 0);
  });

  it('should search', () => {
    // 支援各種selector
    cy.get('input.search').type('canvas');
    cy.get('.search-button').click();
    cy.get('app-article').should('have.length', 1);
  });

  // USER CREATED TEST
  // RUN APP WITH 'NPM START'
  // IN A DIFFERENT CONSOLE WINDOW RUN CYPRESS WITH 'NPX CYPRESS OPEN'
  it('should search (student version)', () => {
    // put test here
  });

  // 後面2個測試案例是讓你練習的,
  // 答案寫在answers/articles.answers.spec.ts
  // USER CREATED TEST FOR TAGS
  it('should filter tags', () => {
    // check that the total number of tags is 20 (tag有20個00)
    // find tags search input and type 'anim' in it
    // assert the number of tags returned
    // click on 2nd tag 'animations'
    // assert the number of selected tags is 1
    // assert total tags is 15
    // click on the tag with routing
    // assert there are 3 articles
    // BONUS
    // reset filters, check number of tags and articles
    // select a tag, assert it's selected
    // unselect that tag, assert back to default state
  });
});
  • 如果在 VS Code 裡有 TS errors
    可以試著在tsconfig.json加上
    "types":[
      "cypress"
    ],

像這樣

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2015",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "types":[
      "cypress"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  }
}

Introducing server, route,and wait

  • Cypress can wait for API calls

articles-using-waits.spec.ts

describe('Articles using waits', () => {
  it('should wait for tags', () => {
    cy.server();
    cy.route('/api/tags').as('tags'); // alias:string 取別名
    cy.visit('/');
    cy.wait('@tags'); // @symbol
    
    cy.get('.tags-container input').type('anim');
    cy.get('div.tags').should('have.length', 3);
  });

  // USER CREATED TEST FOR WAITS
  // should wait for articles to load then assert count
  // BIG HINT: route: api/articles/recent
  // More subtle hint: route: api/articles/recent
  // BONUS - assert the title of the 3rd article
  // BONUS - assert anchor target for articles is _blank
  // HINT: http://example.cypress.io
  // HINT: https://docs.cypress.io/api/commands/should.html#Value
  it('recents articles should display 25 articles', () => {
    cy.server();
    cy.route('/api/articles/recent').as('articles');
    cy.visit('/');
    cy.wait('@articles');
  });
});

Why Stubs?

  • Declaring routes with stubs
cy.server(); // start the server
cy.route({
    method: "GET", // Route all GET requests
    url: "/users/*", // that have a URL that matches '/users/*'
    response:[] // and force the response to be: []
});
// 可以攔截matches的後端路由,並強制回傳[]

articles-using-stubs.spec.ts

  // USER CREATED TEST FOR STUBS
  // stub the tags api call to only return 'constructor' & 'components'
  // assert that tags count = 2
  // HINT tag model: {_id: '1', tag:'testing'}
  // BONUS: select a tag by clicking on it and
  // have api / articles / search return 1 article
  it('should display 2 tags', () => {
    cy.server();
    // 攔截/api/tags,並回傳我們想塞的資料 [ {_id:...},{...} ]
    cy.route("/api/tags",[
      { _id: "1", tag: "constructor" },
      { _id: "2", tag: "components" }
    ]).as('tags');

    cy.visit('/');
    cy.wait('@tags');
  });

搭配指令,可導入CI

npx cypress run
# 還把測試結果錄成mp4,超棒的
# 如果測試失敗,還會有截圖

上一篇
Day29_Data Composition with RxJS(ng conf 2019)
下一篇
Day26.5_rxjs-spy,開發 RxJS 的好工具
系列文
Angular新手村學習筆記(2019)33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言