今天的主題是UI testing,討論的是當Postman請求的對象不是API,而是網頁的話,可以針對回傳的內容做哪些測試,舉凡效能(performance)、功能性(functionality)、安全性(security)、完整性(integrity)、可存取姓(accessibility)等這些指標,都能拿前面章節討論過的內容來應用,像是Day 26 - HTML解析就有部分應用。
今天的挑戰內容會用實際範例來檢驗效能指標,在挑戰開始前,記得先把 Day 28: UI testing 複製到自己的工作區。
回到自己的工作區,打開今天的資料夾UI testing,根據右方的文件描述,首先需要先挑選任一個網站,後續新增請求及測試來對目標網站進行檢測,這邊以https://www.postman.com/當作目標。
response time,顧名思義主要想看網站的回應速度url為目標網站 https://www.postman.com/
GET
{{url}}
Snippets可以找到常用的Response time is less than 200ms,點擊自動載入並修改成以下,這樣當網站回應的時間長於1秒,測試就會失敗
pm.test("Response time is less than 1000ms", function () {
    pm.expect(pm.response.responseTime).to.be.below(1000);
});
lighthouse
GET
https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url={{url}}
{
    "lighthouseResult": {
        "categories": {
            "performance": {
                "id": "performance",
                "title": "Performance",
                "score": 0.89,
    ...
}
pm.test("PageSpeed score should be within 90 and 100", function () {
    var res = pm.response.json();
    var score = res.lighthouseResult.categories.performance.score;
    pm.expect(score * 100).to.be.within(90, 100);    
});
今天的挑戰內容只有提到根據回應時間或是根據PageSpeed API的結果來測試與效能相關的結果,其他還有幾個常見的範例
Tests來檢查
// 網頁實際資料的大小也是會影響效能的因素
pm.test("Response size is less than 100KB", function () {
    pm.expect(pm.response.responseSize).to.be.below(100000);
});
// 檢查狀態碼是確認功能是否正常的第一步
pm.test("Status code is 200", function () {
    pm.response.to.have.status(200);
});
// 透過 cheerio 來檢查畫面的元素是否如同預期
var cheerio = require('cheerio');
var $ = cheerio.load(pm.response.text());
pm.test('Page should have header', function () {
    pm.expect($('header')).to.exist;
});
Tests來檢查
// 檢查 http 請求狀態碼 301 Move Permanently 以及 跳轉目標必須存在在回應標頭裡
pm.test('Response should have status code is 301', function () {
    pm.response.to.have.status(301);
});
pm.test('Response should redirect to secure URL', function () {
    pm.response.to.have.header(
      'Location',
      'https://' + pm.environment.get('host') + '/'
    );
});
// HSTS有被正確設定
pm.test('Strict-Transport-Security header should be set', function () {
   pm.response.to.have.header(
     'Strict-Transport-Security',
     'max-age=300; includeSubDomains'
   );
});
cheerio將頁面的所有連結撈出,就如同Day 26 - HTML解析所做的一樣,然後透過pm.sendRequest逐個檢查連結都還是有效的
var cheerio = require('cheerio');
var $ = cheerio.load(pm.response.text());
pm.test("All links on the page should be valid", function () {
    $('a').each(function(i, elem) {
        var originalPath = $(elem).attr('href');
        var path = originalPath;
        if (path && path[0] === '/') {
            path = pm.environment.get('url') + path;       
        }
        pm.sendRequest(path, function (err, res) {
            pm.test('Link with href "' + originalPath + '" should be valid', function () {
                pm.expect(err).to.equal(null);
                pm.expect(res).to.have.property('code', 200);
                pm.expect(res).to.have.property('status', 'OK');
            });
        });
    }); 
});
延伸閱讀:
那麼今天就到這裡,我們明天見~