background

With the rapid iteration of the product, there will be a scene where the product is urged to have functions in front and the package is not tested (regression testing). In order to solve this problem, I implemented the trial of end-to-end testing.

Demo Test Scenarios

Search ourselves on Baidu and judge whether the first item matches our results based on the results returned.

Demo Effect Example

The premise condition

  • Operating environment: Node environment (Node installation is preferred)
  • The test framework is ourselves test-test
  • Grammar: TypeScript
  • Test tool: offended
  • The test tool relies on a specific test browser (any one) : Google, Safari, Opera, Edge, Firefox, etc

Note: Ourselves does not support Babel compilation, so we may use ts in conjunction with ourselves. We may not configure ourselves if we do not use ECMAScript-related syntax

Installing dependency packages

yarn add playwright  @playwright/test typescript ts-node
#OR 
npm install playwright  @playwright/test typescript ts-node
Copy the code

Configure the project configuration file

Configuration package. Json
{... "scripts": { "test": "playwright test" } }Copy the code
Condemnation.config.ts is a common configuration

(For details, see test-Configuration.)

import { PlaywrightTestConfig } from "@playwright/test"; 
let config: PlaywrightTestConfig = { 	
     timeout: 6 * 60 * 1000.// Each test case timed out
     globalTimeout: 60 * 1000./ / the total timeout
     testDir: "./demo".// Test the directory
     reporter: [["html", { outputFolder: ". /".open: "always" }]],// Test report
    use: { 		
        launchOptions: { 			
        headless: false.// Not headless mode
        // recordVideo:'videos' 			
        // recordVideo 			
        // devtools: true, 		
    }, 		
    contextOptions: { 			
    viewport: {   // Window view size
        width: 1400.height: 900,}},//baseURL: process.env.tenant_url, //baseURL
    screenshot: "only-on-failure".// Take screenshots on failure
    trace: "retain-on-failure".// Trace failure records
    browserName: "webkit".// Test the browser}};export default config;
Copy the code
Configuration tsconfig. Json
{ 
    "compilerOptions": { 
    /* Visit https://aka.ms/tsconfig.json to read more about this file */
    /* Basic Options */ 
    "target": "es2017"./* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs"./* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 
    "esModuleInterop": true./* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 
    /* Advanced Options */ 
    "skipLibCheck": true./* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */}}Copy the code

Write test cases

1. Create test directory Demo in the root directory
2. Create test case files
import { expect, test } from "@playwright/test"; import { chromium } from "playwright"; 
import { TestOperationPanel } from "./TestOperationPanel"; 
import { judgeSystem } from "./config"; 
let  testOperation: TestOperationPanel, browser, page, context; 
    /** Test case group **/ 
    test.describe("Playright-demo".async function () { 
    /** Run all test cases before the function **/ 
        test.beforeAll(async ({ browserName }, testConfig) => { 
        /** Check the system type configuration **/ 
        const launch = await judgeSystem(); 
        /** Create a browser **/ 
        browser = await chromium.launch(launch); 
        /** Create window **/ 
        context = await browser.newContext(); 
        /** create interface **/ 
        page = await context.newPage(); 
        /** Create UI interaction configuration code instance **/ 
        testOperation = new TestOperationPanel(page); }); 
        /** Run the function **/ before each test case 
        test.beforeEach(async function () { 
        /** redirect address **/ 
        await testOperation.goTestUrl("http://www.baidu.com"); }); /** Test case **/ 
        test("Search Playwright".async function () { 
        /** Search for the specified content **/ 
        const result = await testOperation.searchContent("playwright"); 
        /** assertion verifies matched content **/   
        expect(result).toMatch(/^playwright/); }); 
        /** The function **/ after running all the test cases 
        test.afterAll(async function ({ browser }) /** Close the browser **/
            await browser.close()
        });
});
Copy the code
3. Create a test case common Settings file

(Create config.ts file in demo folder. Configure browser separately because you need to match different operating systems.)

import os from "os"; 
import fs from "fs";
/** * Determine the operating system to determine the Lanuch condition *@returns * / 
export function judgeSystem() { 
        const osType = os.type(); 
        if (osType === "Darwin") { 
        /**macOS test browser configuration */ 
        return { executablePath: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome".// browser address}; }
        if (osType === "Linux") { 
        /** Test the browser configuration on Linux */ 
        // return { devtools: true }
        }
        if (osType === "Windows_NT") {
        /** Windows test browser configuration */ 
        // return { devtools: true } }
}
Copy the code
4. In the Demo folder testOperationPanel.ts

(Implement UI interaction layer code and business code segmentation, capture elements more methods, refer to Page Object Model, UI interaction reference Selectors)

//UI interaction layer code
import { Page } from "playwright"; 
export class TestOperationPanel { 
    protected page: Page; 
    constructor(page: Page) { 
        this.page = page;
    } 
    /** * load test url */ 
    goTestUrl = async (url: string) => { 
        /** redirect address **/ 
        await this.page.goto(url);
        /** Wait for the page to load **/ 
        await this.page.waitForLoadState(); }; 
        /** * search for the specified content */ 
        searchContent = async param => { 
        /** Fill the input field with the search field **/ 
        await this.page.locator(".s_ipt").fill(param); 
        /** Press enter in the input box to trigger the search **/ 
        await this.page.locator(".s_ipt").press("Enter");
        /** Wait for the page to load **/ 
        await this.page.waitForLoadState(); 
        /** returns the first item of the search **/ 
        const result = await this.page.locator('//div[@id="1"]/h3//em').textContent(); 
        returnresult; }}Copy the code

Run the test case

npm run test  // To obtain detailed logs, add DEBUG=pw: API before running
Copy the code