Playwright. Fixtures

Agenda

  • Use
  • Fixtures
  • Annotations & Groups

Use

Позволяет задать определенные настройки

use можно использовать в 

  • глобально(pw.config.ts)
  • проекте(pw.config.ts - projects)
  • в тесте

Use. Config

// playwright.config.ts
import { defineConfig } from '@playwright/test';

export default defineConfig({
  use: {
    // Base URL
    baseURL: 'https://example.com',

    // Capture screenshot after each test failure.
    screenshot: 'only-on-failure',
  },
});

Use. Project

import { defineConfig } from '@playwright/test';
export default defineConfig({
  use: {},
  projects: [
    {
      name: 'chromium',
      use: {
        ...devices['Desktop Chrome'],
        baseURL: 'https://google.com/'
      },
    },
  ],
});

Use. Test

// example.test.ts

import { test, expect } from '@playwright/test';

test.use({ baseURL: 'https://jsonplaceholder.typicode.com' })

test('has title', async ({ page }) => {
  await page.goto('/');
  console.log('URL:', page.url())
});

Примечание

  • Работает для разных URL
  • Нельзя задать URL с путем (/test/qwe/asd)

Fixtures

позволяет переиспользовать однотипный код

Примеры

  • создание-авторизация-удаление
  • подключение к БД
  • переиспользование утилит (генерация строк, паролей)
  • свои проверки (expectations)

Создание

// example.fixture.ts

import { 
  test as baseTest, 
  expect as baseExpect 
} from '@playwright/test'

type TestContext = {
  user: number
}

export const test = baseTest.extend<TestContext>({
  user: async ({}, use) => {
    console.log('user created')
    await use(5)
    console.log('user cleanup')
  },
})

export const expect = baseExpect.extend({})

Использование

// example.test.ts

import { test, expect } from './example.fixture';

test('has title', async ({ page, user }) => {
  await page.goto('/');
  console.log('myUser:', user)
});
$ pnpm exec playwright test --project=chromium

Running 1 test using 1 worker
[chromium] › example.spec.ts:3:5 › has title
user created
myUser: 5
user cleanup

Merge fixtures

// composite.fixture.ts
import { mergeTests } from '@playwright/test';
import { test as dbTest } from 'database-test-utils';
import { test as a11yTest } from 'a11y-test-utils';

export const test = mergeTests(dbTest, a11yTest);
// composite.fixture.ts
import { test as baseTest } from '@playwright/test';

type Context = {
  usePassword(length: number): string
}

export const test = baseTest.extend({
  usePassword: async ({}, use) => {
    await use((length) => {
      return randomPassowrd(length)
    })
  },
});

// test
test('some test', async ({usePassword}) => {
  const user = {
    email: 'some@example.com',
    password: await usePassword(20),
  }
})

Свои expectations

// example.fixture.ts

export const expect = baseExpect.extend({
  toBeUser: function (actual) {
    let pass = false
    let matcherResult: any;
    try {
      baseExpect(actual).toBe(5)
      pass = true
    } catch (e) {
      matcherResult = e.matcherResult
      pass = false;
    }

    return {
      message: () => 'my custom message',
      pass,
      actual,
      expected: 5,
      name: 'toBeUser'
    }
  },
})

Использование

// example.spec.ts
import { test, expect } from './example.fixture';

test('has title', async ({ page, user }) => {
  await page.goto('/');
  console.log('myUser:', user)
  expect(user).toBeUser() // OK
  expect(2).toBeUser() // fails
});

Ошибка

> pnpm exec playwright test --project=chromium

Running 1 test using 1 worker
[chromium] › example.spec.ts:3:5 › has title
user created
myUser: 5
user cleanup
  1) [chromium] › example.spec.ts:3:5 › has title ──

    Error: my custom message

      5 |   console.log('myUser:', user)
      6 |   expect(user).toBeUser() // OK
    > 7 |   expect(2).toBeUser() // fails
        |             ^
      8 | });
      9 |

        at /[masked]/tests/example.spec.ts:7:13

  1 failed
    [chromium] › example.spec.ts:3:5 › has title ─

Работа с ожиданиями

  • soft assertions
  • poll (достучаться)

Пример. Soft

import { test, expect } from './example.fixture';

test('has title', async ({ page, user }) => {
  await page.goto('/');
  console.log('myUser:', user)
  expect.soft(2).toBeUser() // fails
  expect(user).toBeUser() // OK
});

Пример. Poll

import { test, expect } from './example.fixture';

test('has title', async ({ page }) => {
  await page.goto('/');
  let userInfo = 2
  // server thinking 🤔
  setInterval(() => {
    userInfo++
  }, 1000)
  
  await expect.poll(() => {
    return userInfo
  }, {
    // Custom expect message for reporting, optional.
  message: 'user finally 5',
  timeout: 10000, // 5 default
  intervals: [1_000, 2_000, 10_000]
  }).toBe(5)
});

Annotations & Groups

Annotations & Groups

  • skip - пропустить
  • slow - медленный тест, таимаут увеличен в 3 раза
  • fail - тест помечен как упавший, если не так - то будет ошибка у PW 
  • fixme -тест помечен как упавший, pw не запустит этот тест

Аннотации можно двать одному тесту, или группе

Annotations

import { test, expect } from './example.fixture';

test('has title @acceptance', async ({ page }) => {
  test.skip(browserName === 'firefox', 'Still working on it!');
  await page.goto('/');
});

test('has title on page2',{
  tag: '@acceptance @unstable',
}, async ({ page }) => {
  test.slow() // timeouts increased in 3 times
  await page.goto('/page2');
});

Groups

import { test, expect } from './example.fixture';

test.describe('some big feature', {tag: '@feature1'}, () => {
  test.beforeEach(async () => {
    // create user
  })
  test('assert1', () => {})
  test('assert1', () => {})
})

References

pw. Fixtures

By vitalic gorodkov

pw. Fixtures

  • 224