Live share

WHO I AM

dmtrKovalenko

@dmtrKovalenko

Пирамида

Для кого?

Для кого?

Для кого?

Для кого?

Unit testing

Для кого?

Integration testing

Для кого?

e2e testing

e2e

Integration

Unit

Вопрос

?=

Давайте разбираться!

Где граница?

e2e

Integration

Unit

непонятно

Rest API

e2e

Front-end

Cypress.Commands.add('login', () => {
  cy.visit('/login')
  cy.get('#email').type('admin@cypress.io')
  cy.get('#password').type('security')

  cy.get('#submit-btn').click()
})
cy.login()
Cypress.Commands.add('login', () => {
  cy.request('/testRoutes/loginAsAdmin')
})

Где граница?

e2e

Integration

Unit

 Назад
 В
 Прошлое

Мы тут

React

Angular 1.0

Vue

JQuery

2006

2012

2013

2014

2019

Timeline

Testing Pyramid

2008

Google it

https://benhutchison.wordpress.com/2008/03/20/automated-testing-2-the-test-pyramid/

Почему

- Долгаааа

- Сложнааа

(запускать и писать)

 

(писать и поддерживать)

 

не e2e?

чо
так
сложно        долго

Мы тут

React

Angular 1.0

Vue

JQuery

2006

2012

2013

2014

2019

Timeline

Testing 🔼

2008

2004

Selenium

Если у вас нету тестов

 
 

То билд у вас не упадет

 

Если вы не запускаете  тесты

 
 

То у вас нету
тестов

 
 

e2e

is painfull

Build Time: 42:14

Мы тут

React

Angular 1.0

Vue

JQuery

2006

2012

2013

2014

2019

Timeline

Testing 🔼

2008

2004

Selenium

version: 2
jobs:
  build:
    docker:
      - image: cypress/base:10
    steps:
      - checkout
      - restore_cache:
          name: Restore Yarn Package Cache
          keys:
            - yarn-packages-{{ checksum "yarn.lock" }}
      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile
      - save_cache:
          name: Save Yarn Package Cache
          key: yarn-packages-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache
      - run: cypress run --record

Проще не бывает

version: 2
jobs:
  build:
    docker:
      - image: cypress/base:10
    parallelism: 15
    steps:
      - checkout
      - restore_cache:
          name: Restore Yarn Package Cache
          keys:
            - yarn-packages-{{ checksum "yarn.lock" }}
      - run:
          name: Install Dependencies
          command: yarn install --frozen-lockfile
      - save_cache:
          name: Save Yarn Package Cache
          key: yarn-packages-{{ checksum "yarn.lock" }}
          paths:
            - ~/.cache
      - run: cypress run --record

Еще и быстро

e2e

e2e

Integration

Unit

Ну-ка напиши тест

import db from './db'

const router = express.Router();

router.get('/users', (req, res) => {
  db.getAllUsers().then(res.json)
})

Dependency Injection

const router = express.Router();

router.get('/users', (req, res) => {
  req.db.getAllUsers().then(res.json)
})

Я

Unit tests

TRIGGERED

Rest API

Frontend

GraphQL

Overmocking

import { fetchFromApi } from '~/fetcher'

function fetchUsers() {
  return fetchFromApi('/users')
}

it('Should fetch users', async () => {
  jest.mock(fetchFromApi, () => Promise.resolve([{ id: 1 }]))

  const result = await fetchUsers()
  expect(result).toEqual([{ id: 1 }])
})

И правда

Чем больше тесты знают про реализацию, тем...

Но ведь e2e тоже не огонь

/root/div/descendant::*[not (@class='bad')]  

//h1/following-sibling::ul[1]

<div data-test-id="user-list-name"/>

Убираем хрупкость

e2e

 

One more thing

Зачем мы пишем тесты?

Зачем? 

Надежность

e2e

Integration

Unit

Надежность

Скорость

>.<  Бесполезные тесты

UI components unit testing

it("renders three <Foo /> components", () => {
  const wrapper = shallow(
    <MyComponent>
      <Foo />
      <Foo />
      <Foo />
    </MyComponent>
  );

  expect(wrapper.find(Foo)).to.have.lengthOf(3);
});
const Component = () => (
  <MyComponent>
    <Foo />
    <Foo />
    <Foo />
  </MyComponent>
)
const jsx = React.createElement

const Component = () => jsx(
  MyComponent,
  null,
  jsx(Foo, null),
  jsx(Foo, null),
  jsx(Foo, null)
);

===

UI components unit testing

it("renders three <Foo /> components", () => {
  const wrapper = shallow(jsx(
    MyComponent,
    null,
    jsx(Foo, null),
    jsx(Foo, null),
    jsx(Foo, null)
  ));
  
  const arguments = jsx.mock.calls[0]
  expect(arguments.filter((element) => element.type === Foo).to.have.lengthOf(3)
});

Text

Тестирование Реализации

vs

export function calculateUsagePeriods(
  currentUsagePeriodStartsAt,
  currentUsagePeriodEndsAt,
  organizationCreatedAt,
  n = 6
) {
  if (!currentUsagePeriodStartsAt) return []

  const usagePeriods = []
  let startTime = moment.utc(currentUsagePeriodStartsAt)
  let endTime = moment.utc(currentUsagePeriodEndsAt)

  for (let i = 0; i < n; i++) {
    if (endTime.isBefore(organizationCreatedAt)) {
      break
    }

    usagePeriods.push({
      startTime: startTime.clone(),
      endTime: endTime.clone(),
    })

    startTime.subtract(1, 'month')
    endTime.subtract(1, 'month')
  }

  return usagePeriods
}
test("Should calculate usage periods when n = 5", () => {
  const result = calculateUsagePeriods(new Date(), addDays(new Date(), 5), 5)

  expect(result).toEqual([...])
})
test.each`
  startsAt      | endsAt                      | n     | expected
  ${new Date()} | ${new Date()}               | ${10} | ${[15, 16]}
  ${new Date()} | ${addDays(new Date(), 10)}  | ${6}  | ${[15, 16]}
  ${new Date()} | ${addDays(new Date(), -10)} | ${15} | ${[15, 16]}
`(
  "Should calculate usage periods when startsAt = $startsAt, endsAt = $endsAt n = $n",
  ({ startsAt, endsAt, n, expected }) => {
    expect(calculateUsagePeriods(startsAt, endsAt, n)).toEqual(expected);
  }
);

Unit Tests

But useless

Users ❤️ Quality app

Business 

Dev ❤️ Coding

Dev ❤️ Create quality apps

❤️ Happy users

e2e

Integration

Unit

===

 

Illuminati confirmed

Links

Спасибо за внимание

Unit tests are useless

By dkovalenko

Unit tests are useless

  • 1,706