[Puppeteer based front-end automation framework] [two] PO mode, assertion (how logic easier to write test code)

I. Summary

Introduced in front Puppeteer + jest + TypeScript do UI automation, but this knowledge base, we achieved a lot, such as PO mode automation to be considered, such as configuration files, such assertions and so on. Here's to come true is how I used to do puppeteer UI Automation

Second, the assertion

(A) the need to rely on the installation package

Dependencies command
Is asl install is --save-dev
@ Types / a npm install @types/jest --save-dev
expect-puppeteer npm install expect-puppeteer --save-dev
@types/expect-puppeteer npm install @types/expect-puppeteer --save-dev

== know we wrote Jest Jest himself with the assertion, but sometimes may be incomplete Jest assertion meet us, we take a look at the api == expect-puppeteer

Links: the Expect-Puppeteer (API)

(B) a brief introduction api

  1. See the introduction of api, expect-puppeteer encapsulates some of the methods available to us, such as the assertion toMatch (page verify whether it can match the value), whether toMathcElement ((verification page can be matched to the elements), both still relatively easy to use especially toMathcElement, besides specific combat
  2. Other api, look a little different with the puppeteer api, puppeteer as there click method so expect-puppeteer what benefit is it? This time we will look at the source code == It is recommended that even with existing library, we have a lot to look at the source ==
  3. View expect-puppeteer - index.d.ts found written a ExpectPuppeteer interface here which will have all our api, the way we see any point to see a js file, directory (expect-puppeteer - lib - options.js), we will look at this document, do not understand it does not matter, but we can probably guess, is to control the run-time thing, the actual work a case could write a lot of waitfor () is not too much trouble, so I suggest that it options.js the timeout setting longer so easy to find a more accurate page elements
  4. api introduce much to do, according to the api documentation will be relatively simple
options.js -> 修改timeout为2s
let defaultOptionsValue = {
  timeout: 2000
};

Three, PO mode

Q: What is PO mode?

A: The concept of self-Baidu, I will not stick, I think a little bit UI automation wrote, should be able to understand a little more or less, popular to say, we write element method, test case separately, so help us to manage , do not call logic is clear, take the following specific examples to illustrate

Fourth, the example (to the site the same way as an example)

Today we write, from the home into the ly.com, click on Flights - Domestic Flights - Flights Default verify bomb box

(A) my script directory

-----__tests__
-------ui
--------DomesticTictet
-------- cases
--------   basic.test.ts
-------- element
--------Index
-------- action
--------   Navi.action.help.ts   
-------- element
--------   Navigation.help.ts
-----env
------ ly.yaml
-----utils
------ config.js
  • Test cases are __tests__ folder, DomesticTictet, file folders Index of different modules, respectively cases (test case file storage folder) element (management page elements) action (method)
  • File env, management yaml files, and all files placed here yaml
  • utils write their own tools, config.js read yaml file

(B) element management class

Navigation.help.ts

import { Page } from 'puppeteer';
import expectPuppeteer = require('expect-puppeteer');
export const Nav_Ticket = '#menuNav li:nth-child(3) b';
export const DomesticTicket = '.submenu-nav .flight-submenu1';
home.help.ts 
// 标题名
export const titleContent = '.s-title.dflex span';

// 出发城市
export const start_city_input = '.s-box:nth-child(1) input[value]';

// 到达城市
export const arrive_city_input = '.s-box:nth-child(3) input[value]';

// 出发时间
export const start_data_input = 'input[placeholder="出发日期"]';

// 到达时间
export const return_data_input = 'input[placeholder="返回日期"]';

// 搜索按钮
export const domestic_tictet_search = '.s-button';

// 搜索不到航班信息提示
export const flight_no_data_tip = '.flight-no-data span'

// 存在航班的元素 
export const flight_get_data = '.top-flight-info span b'

Write (c) action method

Navi.action.help.ts

import { Page } from 'puppeteer';
import expectPuppeteer = require('expect-puppeteer');
const navi_element = require('../element/Navigation.help');

export class Navi_Action {
    /**
     * 点击国内机票
     */
    public async hover_home_ticket(page:Page) {
        await page.waitForSelector(navi_element.Nav_Ticket);
        await page.hover(navi_element.Nav_Ticket);
        await page.waitFor(3000);
        await expectPuppeteer(page).toClick(navi_element.DomesticTicket);
        await page.waitFor(3000);

    }
}

Writing (four) yaml profile

ly.yaml

url:
  web: https://www.ly.com/
  flighthome: https://www.ly.com/flights/home

# puppeteer lanuch配置
puppeteer:
  proxy:
  viewport:
    width: 1920
    height: 1080

Written (e) test

basic.test.ts

import { Page } from 'puppeteer';
import { Navi_Action } from '../../Index/action/Navi.action.help';
const config = require('../../../../utils/config');
const Home_Element = require('../element/home.help');
const time = require('silly-datetime');

const ly = config.readConfig('ly');

describe('domestic ticket page content verification', () => {
    let page : Page;
    beforeEach( async () => {
        page = await browser.newPage();
        await page.setViewport(ly.puppeteer.viewport);
        await page.goto(ly.url.web,{waitUntil:'networkidle2'});

        let navi_action = new Navi_Action();
        await navi_action.hover_home_ticket(page);
        
    },30000)
    afterEach ( async () => {
        await page.close();
    })

    test('TEST_001:验证跳转链接' , async() => {
        const url = await page.url();
        await expect(url).toBe(ly.url.flighthome);
    },30000);


    test('TEST_002:验证标题名' , async() => {
        const titleElement = Home_Element.titleContent;
        const content = await page.evaluate( (titleElement) => {
            return document.querySelector(titleElement).innerHTML;
        },titleElement);
        await expect(content).toEqual('国内机票');
    },30000);

    test('TEST_003:验证出发默认城市' , async() => {
        const content = await page.$eval(Home_Element.start_city_input,el => el.getAttribute('value'));
        await expect(content).toEqual('上海');
    },30000);

    test('TEST_004:验证到达默认城市' , async() => {
        const content = await page.$eval(Home_Element.arrive_city_input,el => el.getAttribute('value'));
        await expect(content).toEqual('北京');
    },30000);

    test('TEST_004:验证时间为当天时间' , async() => {
        const current_time = time.format(new Date(),'YYYY-MM-DD');
        const start_time_element = Home_Element.start_data_input;
        const start_time_content = await page.evaluate( (start_time_element) => {
            return document.querySelector(start_time_element).value;
        },start_time_element);
        await expect(start_time_content).toEqual(current_time);
    },30000);

    test('TEST_005:验证到达默认值' , async() => {
        const return_input = await page.$eval(Home_Element.return_data_input,el => el.getAttribute('placeholder'));
        await expect(return_input).toEqual('返回日期');
    },30000);
})

result

Guess you like

Origin www.cnblogs.com/totoro-cat/p/11401482.html