playwright端对端测试

210 阅读2分钟

playwright端对端测试

在vite安装的项目下 安装playwright

npm install @playwright/test -D
npm install eslint-plugin-playwright -D

添加playwright.config.ts

import process from 'node:process'
import { defineConfig, devices } from '@playwright/test'

/**
 * Read environment variables from file.
 * https://github.com/motdotla/dotenv
 */
// require('dotenv').config();

/**
 * See https://playwright.dev/docs/test-configuration.
 */
export default defineConfig({
  testDir: './test',
  /* Maximum time one test can run for. */
  timeout: 30 * 1000,
  expect: {
    /**
     * Maximum time expect() should wait for the condition to be met.
     * For example in `await expect(locator).toHaveText();`
     */
    timeout: 5000
  },

  fullyParallel: true,

  /* Fail the build on CI if you accidentally left test.only in the source code. */
  forbidOnly: !!process.env.CI,
  /* Retry on CI only */
  retries: process.env.CI ? 2 : 0,
  /* Opt out of parallel tests on CI. */
  workers: process.env.CI ? 1 : undefined,
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
  reporter: 'html',

  globalSetup: 'global.setup.ts',
  globalTeardown: 'global-teardown.ts',

  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
  use: {
    /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
    // actionTimeout: 0,
    /* Base URL to use in actions like `await page.goto('/')`. */
    // baseURL: process.env.CI ? 'http://localhost:4173' : 'http://localhost:5173',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry'

    /* Only on CI systems run the tests headless */
    // headless: !!process.env.CI
  },

  /* Configure projects for major browsers */
  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome']
      }
    },
    {
      name: 'firefox',
      use: {
        ...devices['Desktop Firefox']
      }
    },
    {
      name: 'webkit',
      use: {
        ...devices['Desktop Safari']
      }
    }

    /* Test against mobile viewports. */
    // {
    //   name: 'Mobile Chrome',
    //   use: {
    //     ...devices['Pixel 5'],
    //   },
    // },
    // {
    //   name: 'Mobile Safari',
    //   use: {
    //     ...devices['iPhone 12'],
    //   },
    // },

    /* Test against branded browsers. */
    // {
    //   name: 'Microsoft Edge',
    //   use: {
    //     channel: 'msedge',
    //   },
    // },
    // {
    //   name: 'Google Chrome',
    //   use: {
    //     channel: 'chrome',
    //   },
    // },
  ],

  /* Folder for test artifacts such as screenshots, videos, traces, etc. */
  // outputDir: 'test-results/',

  /* Run your local dev server before starting the tests */
  webServer: {
    /**
     * Use the dev server by default for faster feedback loop.
     * Use the preview server on CI for more realistic testing.
     * Playwright will re-use the local server if there is already a dev-server running.
     */
    command: process.env.CI ? 'npm run preview' : 'npm run dev',
    port: process.env.CI ? 4173 : 5173,
    reuseExistingServer: !process.env.CI
  }
})

测试的内容放在test文件夹内

packages.json中添加运行脚本

{
	"scripts":{
		"test": "playwright test",
		"test:ui": "playwright test --ui",
	}
}

运行脚本即可看到效果

添加覆盖率 V8

添加依赖monocart-coverage-reports

npm install monocart-coverage-reports -D

新增文件mcr.config.ts、global.setup.ts、global-teardown.ts、fixtures.ts

mcr.config.ts

// mcr.config.ts
import { CoverageReportOptions } from 'monocart-coverage-reports'

// https://github.com/cenfun/monocart-coverage-reports
const coverageOptions: CoverageReportOptions = {
  name: 'My Playwright Coverage Report',

  reports: ['console-details', 'v8', 'lcovonly'],

  // entryFilter: {
  //     '**/node_modules/**': false,
  //     '**/*.js': true
  // },

  // sourceFilter: {
  //     '**/node_modules/**': false,
  //     '**/*.js': true
  // },

  outputDir: './coverage-reports'
}

export default coverageOptions

global.setup.ts

// global.setup.ts
import MCR from 'monocart-coverage-reports'
import coverageOptions from './mcr.config'
import { type FullConfig } from '@playwright/test'

async function globalSetup(config: FullConfig) {
  const mcr = MCR(coverageOptions)
  await mcr.cleanCache()
}

export default globalSetup

global-teardown.ts

// global-teardown.ts
import MCR from 'monocart-coverage-reports'
import coverageOptions from './mcr.config'
import { type FullConfig } from '@playwright/test'

async function globalTeardown(config: FullConfig) {
  const mcr = MCR(coverageOptions)
  await mcr.generate()
}

export default globalTeardown

fixtures.ts

// fixtures.ts
import { test as testBase, Page } from '@playwright/test'
import MCR from 'monocart-coverage-reports'
import coverageOptions from './mcr.config'

// fixtures
const test = testBase.extend<{
  autoTestFixture: string
}>({
  autoTestFixture: [
    async ({ context }, use) => {
      const isChromium = test.info().project.name === 'chromium'

      const handlePageEvent = async (page: Page) => {
        await Promise.all([
          page.coverage.startJSCoverage({
            resetOnNavigation: false
          }),
          page.coverage.startCSSCoverage({
            resetOnNavigation: false
          })
        ])
      }

      // console.log('autoTestFixture setup...');
      // coverage API is chromium only
      if (isChromium) {
        context.on('page', handlePageEvent)
      }

      await use('autoTestFixture')

      // console.log('autoTestFixture teardown...');
      if (isChromium) {
        context.off('page', handlePageEvent)
        const coverageList = await Promise.all(
          context.pages().map(async (page) => {
            const jsCoverage = await page.coverage.stopJSCoverage()
            const cssCoverage = await page.coverage.stopCSSCoverage()
            return [...jsCoverage, ...cssCoverage]
          })
        )
        // console.log(coverageList.map((item) => item.url));
        const mcr = MCR(coverageOptions)
        await mcr.add(coverageList.flat())
      }
    },
    {
      scope: 'test',
      auto: true
    }
  ]
})

export { test }

测试文件添加依赖

test文件夹内每个测试文件需添加fixtures中test依赖覆盖原来的test方法

import { 
 // test, 
expect } from '@playwright/test' 
import { test } from '../fixtures' // 将test 覆盖原来的test

test('xxx', async ({ page }) => {
  await page.goto('http://localhost:5173/')
  await page.locator('button.login-btn').click()
  await page.waitForTimeout(1000)
  await expect(page.url()).toContain('/user')
})

package.json添加脚本

{
	"scripts":{
      "test:ui":"playwright test --ui",
		"test": "npx playwright test",
	}
}

录制测试用例,自动生成代码

生成的测试用例无断言,需自行添加断言

npx playwright codegen // 需启动服务之后运行,或者测试生产环境