Skip to content

Instantly share code, notes, and snippets.

@monolithed
Last active January 3, 2019 17:41
Show Gist options
  • Save monolithed/0afc9ee130d748f8f2ac79ff7ac4809e to your computer and use it in GitHub Desktop.
Save monolithed/0afc9ee130d748f8f2ac79ff7ac4809e to your computer and use it in GitHub Desktop.
Почему Jest вызывает боль!

Причины, по которым мне не правится Jest

  • Нельзя задать директорию для снепшотов. На первый взгляд это не кажется проблемой, но когда вы начнете создавать файлики с постфиксом .spec.js, то на каждом уровне у вас будут папки __snapshots__. Представьте, что открываете вы директорию, а там папка с кешом, открываете другую и там тоже самое — жуть!

  • testPathDirs не поддерживает glob-паттерн.

  • Jest как и Webpack 2 валидирует все поля. Это означает, что подключив какой-то сторонний препроцессор вы должны описывать его конфигурацию в вашем package.json, и даже не в секции jest, поскольку она там тоже валидируется!

  • setupFiles включаются в набор тестов, если они попадают в testPathDirs.

  • Как альтернатива glob-паттерна используется перечисление в testPathIgnorePatterns и testRegex.

  • Протестировать функцию, которая складывает два числа просто, но когда требуетя определить глобальный объект типа jQuery приходится знакомиться с setupFiles и setupTestFrameworkScriptFile. Но это ничего в сравнении с тем когда вам потребуется вызвать компонент с данными, которые обычно приходят из других компонетов (например ссылки на экшены, события и пр. хранилища). Вроде бы библиотека предназначена для тестирования React-приложений, но так только кажется. Поэтому тест писать нужно сразу чтобы не тратить время на разбирательства откуда приходят данные.

  • У вас в приложении есть события, да ладно? Тогда Jest спешит на помощь! Не забудьте определить jest.genMockFunction.

  • В scriptPreprocessor можно добавить только один препроцессор, т.е. если вам потребуется препроцессор для TypeScript и CSS, то придется класть файлик в ваш проект, который будет как-то это разруливать (документации разумеется на этот случай нет).

  • C препроцессорами вообще забавно, если например вы подключите jest-css-modules, то путь к модую нужно писать от node_modules!

  • Если требуется поддержка например CSS-файлов, то в moduleNameMapper начинается недокументированная магия типа "^.+\\.(css)$": "identity-obj-proxy"

  • По умолчнию Jest навязвает странную систему наименований директорий вида __tests__, __mocks__, __snapshots__ и т.д. И чтобы запустить тесты в кастомной директории нужно переопределить регулярное выражение testRegex на что-то вроде .*(js[x]?)

  • Конфигурационный файл может быть только в формате JSON

  • Если структура проекта имеет вложенность, то перед каждым запуском тестов, которые приходится удалять папки __snapshots__ командой вроде этой:

find tests/* -type d -name __snapshots__ -exec rm -rf -- {} +

Это же бред какой-то! Возможно проблема в тестовом фреймворке, который использует Jest? Ок, попробуем подключить Mocha (очередная недокументированная возможность):

{
    "testRunner": "node_modules/mocha"
}

Теперь запустим с опцией --debug:

jest version = 16.0.2
test framework = Mocha
config = {
  "verbose": true,
  "testRunner": "/node_modules/mocha",
  "testPathDirs": [
    "/tests/views"
  ],
...

Как мы видим, Jest любезно подключил Mocha. Однако теперь мы видим другую ошибку:

    TypeError: Cannot set property 'files' of undefined
      
      at Mocha (node_modules/mocha/lib/mocha.js:79:14)

Только вот что с этим делать неясно. Хотя нет. Решение есть — нужно добавить следующее правило:

"testPathIgnorePatterns":["__snapshots__"],

Это правило появилось из-за того, что мы не захотели размещать файлы с тестами в предопределенной директории __tests__ (резолвится по првилу (/__tests__/.*|\\.(test|spec))\\.(js|jsx)$) и выбрали более консервативное имя tests

  • Документация очень быстро устаревает. Например опцию preprocessCachingDisabled добавили и в следующем релизе удалили.

  • Все что предлагает Jest есть и в Mocha (разве что нет специфичных ассертов). Да именно так! Enzyme, ReactTestUtils, Sinon и даже react-test-renderer отдельные пакеты, которые вы должны подключать в каждый файл дополнительно. С одной стороны это хорошо, но мы все-таки, тестируем приложение на React...

  • Нельзя использовать конфигурацию Webpack'a. Иными словами, если вы сделали очень много надстроек в Webpack'е, то все это нужно повторить в Jest c помощью сторонних плагинов, препроцессоров и танцев с бубнами — даже для работы с Rect потребуется как минимум jest-css-modules и babel-jest. Даже не тратьте на это время, особенно если для этого потребуется перейти на Webpack 2!

  • Крайне неинформативные ошибки:

import React, { Component, PropTypes } from 'react';

class Error extends Component {
	render () {
		return <div>Text</div>;
	}
}

export default Error;
 FAIL  tests/views/Error/index.jsx
  ● Error view

    Invariant Violation: Error(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
      
      at invariant (node_modules/fbjs/lib/invariant.js:38:15)

Что это означает и почему эта ошибка появлется при использовании столь простого компонента?

import React from 'react';
import renderer from 'react-test-renderer';

test('Error view', () => {
	let component = renderer.create(<Error />);
	let view = component.toJSON();

	let actual = expect(view);
	actual.toMatchSnapshot();
});

А ведь компонент не был определен! Очень информативно, не правда?

  • Your test suite must contain at least one test.
    Удивительно, но эта ошибка может еще означать, что требуется удалить эталонные снепшоты или переопределить регулярку, которая резолвит пути к тестам.

  • Invariant Violation: ReactCompositeComponent: injectEnvironment() can only be called once.
    Очередная ошибка, которая частично лечится следующей не менее загадочной строчкой:

jest.mock('react/lib/ReactDefaultInjection');

После чего возникает такая ошибка:

Invariant Violation: getNodeFromInstance: Invalid argument.

На этот раз это лечится добавление следующей строки:

jest.mock('react-dom');
  • Warning: Unknown prop 'className' on <div> tag.

Эта ошибка появилась также на ровном месте из-за того что мы добавили замокали модуль ReactDefaultInjection (см. предыдущее решение). Вот только фикса нет! Точнее он есть в бета-версии react'a, который при использовании заваливает еще большим количеством ошибок типа:

Cannot find module 'react/lib/ReactTestRenderer' from 'index.js'
  • Моки, анмоки, донтмоки и пр. терминолочическая грузотень, с которой придется познакомиться в силу особенностей фреймворка.

  • Мейнтейнеры **** редкостные, на все вопросы и предложения отвечают просьбой сделать пул-реквест или отпиской вроде This is an issue tracker, not a help forum..

@dmitrykuznetsovdev
Copy link

напиши теперь почему нравиться!

@denisx
Copy link

denisx commented Feb 14, 2018

Нужно починить коммент: Это же бред како-то!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment