Эта статья в основном дает вам глубокое понимание принципов работы Jest, что удобно для ответов на интервью и реальных потребностей бизнеса. Я считаю, что мы уже знакомы с подготовкой Jest, но мы можем быть очень незнакомы с тем, как работает Jest. Давайте войдем в Jest вместе. Внутренне исследуйте вместе. Сначала прикрепите код к нуждающимся студентам, обратите внимание: https://github.com/Wscats/jest-tutorial
Что такое шутка
Jest — это среда тестирования Javascript, разработанная Facebook. Это библиотека JavaScript для создания, запуска и написания тестов.
Jest выпускается в виде пакета NPM и может быть установлен и запущен в любом проекте JavaScript. Jest в настоящее время является одной из самых популярных тестовых библиотек для интерфейса.
Что означает тестирование
С технической точки зрения тестирование означает проверку того, соответствует ли наш код определенным ожиданиям. Например: функция с именем sum (sum
) должна возвращать ожидаемый результат с учетом некоторого результата операции.
Есть много типов тестов, и вы скоро будете ошеломлены терминологией, но короткие тесты делятся на три категории:
- модульный тест
- Интеграционное тестирование
- E2E-тест
Откуда мне знать, что тестировать
С точки зрения тестирования, даже самый простой блок кода может запутать новичков. Самый распространенный вопрос: «Откуда мне знать, что тестировать?».
Если вы пишете веб-страницу, хорошей отправной точкой будет тестирование каждой страницы приложения и каждого взаимодействия с пользователем. Однако веб-страница также должна состоять из единиц кода, таких как функции и модули, которые необходимо протестировать.
Чаще всего возникают две ситуации:
- Вы наследуете устаревший код, в котором нет встроенных тестов.
- Вы должны внедрить новую функцию из воздуха
так что мне теперь делать? В обоих случаях вы можете думать о тесте как о проверке того, дает ли функция ожидаемый результат. Наиболее типичный процесс тестирования выглядит следующим образом:
- Импортируйте функцию для тестирования
- Дайте функции вход
- Определите желаемый результат
- Проверьте, выдает ли функция ожидаемый результат
Как правило, это так просто. Освойте следующие основные идеи, писать тесты больше не будет страшно:
Ввод -> Ожидаемый результат -> Результат утверждения.
Тестовые блоки, утверждения и сопоставители
Мы создадим простой код функции Javascript для сложения 2 чисел и напишем для него соответствующий тест на основе Jest.
const sum = (a, b) => a + b;
Теперь для тестирования создайте тестовый файл в той же папке и назовите его test.spec.js
. Этот специальный суффикс является соглашением Jest и используется для поиска всех тестовых файлов. Мы также импортируем тестируемую функцию, чтобы выполнить тестируемый код. Шуточные тесты следуют стилю тестов BDD. Каждый тест должен иметь основной тестовый блок test
, а тестовых блоков может быть несколько. Теперь вы можете написать тестовые блоки для метода sum
. Здесь мы пишем тест, чтобы добавить 2 числа и проверить ожидаемый результат. Мы предоставим числа 1 и 2 и ожидаем, что на выходе будет 3.
test
Требуется два параметра: строка для описания тестового блока и функция обратного вызова для переноса фактического теста. expect
оборачивает целевую функцию и объединяет ее с сопоставителем toBe
, чтобы проверить, соответствует ли результат вычисления функции ожиданиям.
Это полный тест:
test("sum test", () => { expect(sum(1, 2)).toBe(3); });
Наблюдаем приведенный выше код и находим две точки:
Блок test
— это отдельный тестовый блок, который имеет функцию описания и разделения области видимости, то есть представляет собой общий контейнер для теста, который мы хотим написать для функции расчета sum
. -expect
является утверждением. Этот оператор использует входные данные 1 и 2 для вызова метода sum
в тестируемой функции и ожидает выход 3. -toBe
— это сопоставитель, используемый для проверки ожидаемого значения, если ожидаемый результат не достигнут, должно быть исключение. брошенный.
Как реализовать тестовый блок
Тестовый блок на самом деле не сложный. Простейшая реализация выглядит следующим образом. Нам нужно сохранить функцию обратного вызова фактического теста тестового пакета, поэтому мы инкапсулируем метод dispatch
для получения типа команды и функции обратного вызова:
const test = (name, fn) => { dispatch({ type: "ADD_TEST", fn, name }); };
Нам нужно создать функцию обратного вызова с именем state
глобально, чтобы сохранить тест. Функция обратного вызова теста хранится в массиве.
global["STATE_SYMBOL"] = { testBlock: [], };
В настоящее время методу dispatch
нужно только идентифицировать соответствующие команды и сохранить тестовую функцию обратного вызова в глобальном файле state
.
const dispatch = (event) => { const { fn, type, name } = event; switch (type) { case "ADD_TEST": const { testBlock } = global["STATE_SYMBOL"]; testBlock.push({ fn, name }); break; } };
Как реализовать утверждения и сопоставители
Библиотека утверждений также очень проста в реализации. Вам нужно только инкапсулировать функцию, чтобы предоставить метод сопоставления, удовлетворяющий следующей формуле:
expect(A).toBe(B)
Здесь мы реализуем часто используемый метод toBe
, когда результат не равен ожидаемому, просто выдает ошибку:
const expect = (actual) => ({ toBe(expected) { if (actual !== expected) { throw new Error(`${actual} is not equal to ${expected}`); } } };
На самом деле, try/catch используется в тестовом блоке для перехвата ошибок и вывода информации о стеке для обнаружения проблемы.
В простых случаях мы также можем использовать модуль assert
, который поставляется с Node, для создания утверждений. Конечно, есть много более сложных методов утверждения, и принципы схожи по сути.
Интерфейс командной строки и конфигурация
После написания теста нам нужно ввести команду в командной строке для запуска одиночного теста. Обычно команда похожа на следующую:
node jest xxx.spec.js
Суть тут в разборе параметров командной строки.
const testPath = process.argv.slice(2)[0]; const code = fs.readFileSync(path.join(process.cwd(), testPath)).toString();
В сложных ситуациях вам также может понадобиться прочитать параметры локального файла конфигурации Jest, чтобы изменить среду выполнения и т. д. Здесь Jest использует сторонние библиотеки yargs
, execa
и chalk
и т. д. для разбора, выполнения и печати команд.
Моделирование
В сложных тестовых сценариях мы не должны избегать шутливого термина: mock (mock
)
В документации Jest мы можем найти, что Jest имеет следующее описание симуляции: «Функция симуляции стирает реальную реализацию функции, захватывает вызов функции и параметры, передаваемые в этих вызовах, так что связь между тестовые коды становятся проще»
Короче говоря, симуляцию можно создать, назначив следующие фрагменты кода функциям или зависимостям:
jest.mock("fs", { readFile: jest.fn(() => "wscats"), });
Это простой пример моделирования, который имитирует возвращаемое значение функции readFile модуля fs при тестировании конкретной бизнес-логики.
Как имитировать функцию
Далее мы изучим, как это реализовать. Первый jest.mock
. Его первый параметр принимает имя модуля или путь к модулю, а второй параметр — это конкретная реализация метода внешнего воздействия модуля.
const jest = { mock(mockPath, mockExports = {}) { const path = require.resolve(mockPath, { paths: ["."] }); require.cache[path] = { id: path, filename: path, loaded: true, exports: mockExports, }; }, };
Наше решение на самом деле такое же, как реализация приведенного выше тестового блока test
. Вам нужно только найти место для сохранения конкретного метода реализации и заменить его, когда модуль действительно будет использоваться позже, поэтому мы сохраняем его в require In .cache
, конечно, мы также можем хранить его в глобальном state
.
Реализация jest.fn
не сложна. Здесь мы используем замыкание mockFn
для хранения замененных функций и параметров, что удобно для последующих тестовых проверок и статистики данных вызовов.
const jest = { fn(impl = () => {}) { const mockFn = (...args) => { mockFn.mock.calls.push(args); return impl(...args); }; mockFn.originImpl = impl; mockFn.mock = { calls: [] }; return mockFn; }, };
Среда выполнения
Некоторые студенты могли заметить, что в среде тестирования нам не нужно вручную вводить функции test
, expect
и jest
. Каждый тестовый файл можно использовать напрямую, поэтому нам нужно создать запуск, который внедряет эти методы здесь. окрестности.
Виртуальная машина V8 и область действия
Так как все готово, нам остается только внедрить необходимые для тестирования методы в виртуальную машину V8, то есть внедрить область тестирования.
const context = { console: console.Console({ stdout: process.stdout, stderr: process.stderr }), jest, expect, require, test: (name, fn) => dispatch({ type: "ADD_TEST", fn, name }), };
После внедрения области действия мы можем запустить код тестового файла на виртуальной машине V8. Код, который я передал здесь, — это код, который был преобразован в строку. Jest выполнит некоторую обработку кода, обработку безопасности и SourceMap здесь. Для шитья и других операций наш пример не должен быть таким сложным.
vm.runInContext(code, context);
До и после выполнения кода разницу во времени можно использовать для расчета времени выполнения одного теста. Jest также предварительно оценит размер и количество отдельных тестовых файлов и решит, следует ли включить Worker для оптимизации скорости выполнения.
const start = new Date(); const end = new Date(); log("\x1b[32m%s\x1b[0m", `Time: ${end - start}ms`);
Запуск одного тестового обратного вызова
После завершения выполнения виртуальной машины V8 глобальный state
соберет все упакованные тестовые функции обратного вызова в тестовом блоке. Наконец, нам нужно только пройти через все эти функции обратного вызова и выполнить их.
testBlock.forEach(async (item) => { const { fn, name } = item; try { await fn.apply(this); log("\x1b[32m%s\x1b[0m", `√ ${name} passed`); } catch { log("\x1b[32m%s\x1b[0m", `× ${name} error`); } });
Функция крюка
Мы также можем добавить жизненные циклы в одиночный процесс выполнения теста, такие как функции ловушек, такие как beforeEach
, afterEach
, afterAll
и beforeAll
.
Добавление функции ловушки к вышеуказанной инфраструктуре фактически вводит соответствующую функцию обратного вызова в каждый процесс выполнения теста. Например, beforeEach
помещается перед тестовой функцией выполнения обхода testBlock
, а afterEach
помещается перед testBlock
. После обхода выполнения тестовой функции это очень просто. Вам нужно только поставить правильную позицию, чтобы выставить функцию хука любого периода.
testBlock.forEach(async (item) => { const { fn, name } = item; beforeEachBlock.forEach(async (beforeEach) => await beforeEach()); await fn.apply(this); afterEachBlock.forEach(async (afterEach) => await afterEach()); });
А beforeAll
и afterAll
можно ставить до и после завершения всех тестов testBlock
.
beforeAllBlock.forEach(async (beforeAll) => await beforeAll()); testBlock.forEach(async (item) => {}) + afterAllBlock.forEach(async (afterAll) => await afterAll());
На данный момент мы реализовали простую тестовую среду. Основываясь на этом, мы можем обогатить метод утверждения, сопоставление и конфигурацию параметров поддержки, а также прочитать личные примечания к исходному коду ниже.
шутка-кли
Загрузите исходный код Jest и запустите его в корневом каталоге.
yarn npm run build
По сути, он запускает два файла build.js и buildTs.js в папке скрипта:
"scripts": { "build": "yarn build:js && yarn build:ts", "build:js": "node ./scripts/build.js", "build:ts": "node ./scripts/buildTs.js", }
build.js по существу использует библиотеку babel, создает новую папку сборки в пакете package/xxx, а затем использует transformFileSync для создания файла в папке сборки:
const transformed = babel.transformFileSync(file, options).code;
И buildTs.js по существу использует команду tsc для компиляции файла ts в папку сборки и использует библиотеку execa для выполнения команды:
const args = ["tsc", "-b", ...packagesWithTs, ...process.argv.slice(2)]; await execa("yarn", args, { stdio: "inherit" });
Успешное выполнение будет отображаться следующим образом, это поможет вам скомпилировать все файлы js files и ts файлы в папке packages в папку сборки каталога, в котором вы находитесь:
Далее мы можем запустить команду jest:
npm run jest # Equivalent to # node ./packages/jest-cli/bin/jest.js
Здесь вы можете выполнить обработку анализа в соответствии с различными переданными параметрами, такими как:
npm run jest -h node ./packages/jest-cli/bin/jest.js /path/test.spec.js
Он выполнит файл jest.js
, а затем введет метод запуска в файл build/cli
. Метод run будет анализировать различные параметры в команде. Конкретный принцип заключается в том, что библиотека yargs взаимодействует с process.argv для достижения
const importLocal = require("import-local"); if (!importLocal(__filename)) { if (process.env.NODE_ENV == null) { process.env.NODE_ENV = "test"; } require("../build/cli").run(); }
шутка-конфигурация
Когда будут получены различные параметры команды, будет выполнен основной метод runCLI
, который является основным методом библиотеки @jest/core -> packages/jest-core/src/cli/index.ts
.
import { runCLI } from "@jest/core"; const outputStream = argv.json || argv.useStderr ? process.stderr : process.stdout; const { results, globalConfig } = await runCLI(argv, projects);
Метод runCLI
будет использовать входной параметр argv, только что проанализированный в команде, для чтения информации файла конфигурации с помощью метода readConfigs
. readConfigs
происходит от packages/jest-config/src/index.ts
, здесь будет normalize для заполнения и инициализации некоторых настроенных по умолчанию параметров. Его параметры по умолчанию записываются в файл packages/jest-config/src/Defaults.ts
. Например, если вы запускаете только один тест js, значение по умолчанию require. resolve('jest-runner')
— это бегун, который запускает один тест, и он также взаимодействует с библиотекой chalk для создания outputStream для вывода содержимого на консоль.
Кстати, отмечу принцип введения шутки в модуль. Сначала require.resolve(moduleName)
найдет путь к модулю и сохранит путь в конфигурации, а затем с помощью библиотеки инструментов packages/jest-util/src/requireOrImportModule The
requireOrImportModule method of .ts
вызовет инкапсулированный собственный метод import/reqiure
для сопоставления пути в файле конфигурации для извлечения модуля.
- Конфигурация globalConfig из argv
- конфиги взяты из конфигурации jest.config.js
const { globalConfig, configs, hasDeprecationWarnings } = await readConfigs( argv, projects ); if (argv.debug) { /*code*/ } if (argv.showConfig) { /*code*/ } if (argv.clearCache) { /*code*/ } if (argv.selectProjects) { /*code*/ }
шутка-спешка-карта
jest-haste-map используется для получения всех файлов в проекте и зависимостей между ними. Это достигается путем просмотра вызовов import/require
, извлечения их из каждого файла и создания карты, содержащей каждый файл A и его зависимости. Здесь Haste — это модульная система, используемая Facebook. У него также есть что-то под названием HasteContext, потому что у него есть HasteFS (файловая система Haste). HasteFS — это просто список файлов в системе и всех связанных с ним зависимостей. Элемент — это структура данных карты, где ключом является путь, а значением — метаданные. Сгенерированный здесь contexts
будет использоваться до этапа onRunComplete
.
const { contexts, hasteMapInstances } = await buildContextsAndHasteMaps( configs, globalConfig, outputStream );
шутник
Метод _run10000
получит contexts
в соответствии с информацией о конфигурации globalConfig
и configs
. contexts
будет хранить информацию о конфигурации и пути каждого локального файла и т. д., а затем вызовет функцию обратного вызова onComplete
, глобальную конфигурацию globalConfig
и область действия contexts
войдут в метод runWithoutWatch
.
Затем вы войдете в метод runJest
файла packages/jest-core/src/runJest.ts
, где переданный contexts
будет использоваться для прохождения всех модульных тестов и сохранения их в массиве.
let allTests: Array<Test> = []; contexts.map(async (context, index) => { const searchSource = searchSources[index]; const matches = await getTestPaths( globalConfig, searchSource, outputStream, changedFilesPromise && (await changedFilesPromise), jestHooks, filter ); allTests = allTests.concat(matches.tests); return { context, matches }; });
И используйте метод Sequencer
для сортировки отдельных тестов.
const Sequencer: typeof TestSequencer = await requireOrImportModule( globalConfig.testSequencer ); const sequencer = new Sequencer(); allTests = await sequencer.sort(allTests);
Метод runJest
вызывает ключевой метод packages/jest-core/src/TestScheduler.ts
метода scheduleTests
.
const results = await new TestScheduler( globalConfig, { startRun }, testSchedulerContext ).scheduleTests(allTests, testWatcher);
Метод scheduleTests
будет делать много вещей, он будет собирать contexts
в allTests
в contexts
, собирать duration
в массив timings
и подписываться на четыре жизненных цикла перед выполнением всех одиночных тестов:
- запуск тестового файла
- тест-файл-успех
- сбой тестового файла
- результат теста
Затем перейдите по contexts
и используйте новый пустой объект testRunners
, чтобы выполнить некоторую обработку и сохранить его, что вызовет метод createScriptTransformer
, предоставляемый @jest/transform
, для обработки импортированных модулей.
import { createScriptTransformer } from "@jest/transform"; const transformer = await createScriptTransformer(config); const Runner: typeof TestRunner = interopRequireDefault( transformer.requireAndTranspileModule(config.runner) ).default; const runner = new Runner(this._globalConfig, { changedFiles: this._context?.changedFiles, sourcesRelatedToTestsInChangedFiles: this._context?.sourcesRelatedToTestsInChangedFiles, }); testRunners[config.runner] = runner;
Метод scheduleTests
вызовет метод runTests
packages/jest-runner/src/index.ts
.
async runTests(tests, watcher, onStart, onResult, onFailure, options) { return await (options.serial ? this._createInBandTestRun(tests, watcher, onStart, onResult, onFailure) : this._createParallelTestRun( tests, watcher, onStart, onResult, onFailure )); }
В последнем методе _createParallelTestRun
или _createInBandTestRun
:
Будет метод runTestInWorker
, который, как следует из названия, должен выполнить один тест в воркере.
_createInBandTestRun
выполнит базовый метод runTest
в packages/jest-runner/src/runTest.ts
и выполнит метод runTestInternal
в runJest
, который подготовит много приготовлений перед выполнением одного теста. Дело в том, что глобальный метод переписывается и захватывает методы импорта и экспорта.
await this.eventEmitter.emit("test-file-start", [test]); return runTest( test.path, this._globalConfig, test.context.config, test.context.resolver, this._context, sendMessageToJest );
В методе runTestInternal
модуль fs
будет использоваться для чтения содержимого файла и помещения его в cacheFS
, который можно кэшировать для последующего быстрого чтения. Например, если позже содержимое файла будет в формате json, его можно будет прочитать прямо в cacheFS
. Также используйте Date.now
разницу во времени для расчета затрат времени.
const testSource = fs().readFileSync(path, "utf8"); const cacheFS = new Map([[path, testSource]]);
В методе runTestInternal
будет представлен packages/jest-runtime/src/index.ts
, который поможет вам кэшировать и читать модули и запускать выполнение.
const runtime = new Runtime( config, environment, resolver, transformer, cacheFS, { changedFiles: context?.changedFiles, collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, coverageProvider: globalConfig.coverageProvider, sourcesRelatedToTestsInChangedFiles: context?.sourcesRelatedToTestsInChangedFiles, }, path );
Здесь пакет @jest/console
используется для перезаписи глобальной консоли. Для того, чтобы консоль однократно протестированного блока файлового кода плавно выводила результаты на терминал узла, в связке с пакетом jest-environment-node
установите глобальный environment.global
all Rewrite для облегчения последующих методов получения этих областей видимости в vm.
// Essentially it is rewritten using node's console to facilitate subsequent overwriting of the console method in the vm scope testConsole = new BufferedConsole(); const environment = new TestEnvironment(config, { console: testConsole, // Suspected useless code docblockPragmas, testPath: path, }); // Really rewrite the console method setGlobal(environment.global, "console", testConsole);
runtime
в основном использует эти два метода для загрузки модуля, сначала оцените, является ли он модулем ESM, если это так, используйте runtime.unstable_importModule
для загрузки модуля и запуска модуля, если нет, используйте runtime.requireModule
для загрузки модуля и запуска модуля.
const esm = runtime.unstable_shouldLoadAsEsm(path); if (esm) { await runtime.unstable_importModule(path); } else { runtime.requireModule(path); }
шутка-цирк
Сразу после того, как testFramework
в runTestInternal
примет поступающую среду выполнения для вызова одного тестового файла для запуска, метод testFramework
поступает из библиотеки с интересным названием packages/jest-circus/src/legacy-code-todo-rewrite /jestAdapter.ts
, где legacy-code-todo-rewrite
означает переписываемый устаревший код, jest-circus
в основном переписывает некоторые методы глобального global
, с участием этих немногих:
- после всего
- после каждого
- перед всем
- перед каждым
- описывать
- it
- контрольная работа
Прежде чем вызвать одиночный тест здесь, функция jestAdapter
, которая является вышеупомянутой runtime.requireModule
, загрузит файл xxx.spec.js
. Среда выполнения globals
была предварительно задана с помощью initialize
перед выполнением. And
snapshotState, and rewrite
beforeEach. If
resetModules,
clearMocks,
resetMocks,
restoreMocksand
setupFilesAfterEnv` будут выполнены соответственно следующие методы:
- runtime.resetModules
- время выполнения.clearAllMocks
- время выполнения.resetAllMocks
- время выполнения.restoreAllMocks
- runtime.requireModule или runtime.unstable_importModule
После выполнения инициализации метода initialize
, поскольку initialize
переписал глобальные методы describe
и test
, все эти методы переписаны здесь, в /packages/jest-circus/src/index.ts
, здесь. Обратите внимание, что в методе test
есть метод dispatchSync
. Это ключевой метод. Здесь копия state
будет поддерживаться глобально. dispatchSync
означает сохранение функций и другой информации в кодовом блоке test
в state
. В dispatchSync
используется name
в сочетании с методом eventHandler
для изменения state
. Эта идея очень похожа на поток данных в Redux.
const test: Global.It = () => { return (test = (testName, fn, timeout) => (testName, mode, fn, testFn, timeout) => { return dispatchSync({ asyncError, fn, mode, name: "add_test", testName, timeout, }); }); };
Единственный тест xxx.spec.js
, то есть файл testPath, будет импортирован и выполнен после файла initialize
. Обратите внимание, что этот единственный тест будет выполняться при импорте сюда, потому что файл одного теста xxx.spec.js
написан в соответствии со спецификациями. Там будут блоки кода, такие как test
и describe
, поэтому в это время все функции обратного вызова, принятые test
и describe
, будут хранится в глобальном state
.
const esm = runtime.unstable_shouldLoadAsEsm(testPath); if (esm) { await runtime.unstable_importModule(testPath); } else { runtime.requireModule(testPath); }
время шутки
Здесь он сначала определит, является ли это модулем esm, если это так, используйте метод unstable_importModule
для его импорта, в противном случае используйте метод requireModule
для его импорта, в частности, он войдет в следующую функцию.
this._loadModule(localModule, from, moduleName, modulePath, options, moduleRegistry);
Логика _loadModule состоит всего из трех основных частей.
- Оцените, является ли это файлом суффикса json, выполните readFile, чтобы прочитать текст, и используйте transformJson и JSON.parse для преобразования выходного содержимого.
- Определите, является ли файл суффикса узла, и выполните требуемый собственный метод для импорта модуля.
- Для файлов, которые не соответствуют двум вышеуказанным условиям, выполните модуль исполнения _execModule.
_execModule будет использовать babel для преобразования исходного кода, прочитанного fs. Это transformFile
метод transform
packages/jest-runtime/src/index.ts
.
const transformedCode = this.transformFile(filename, options);
_execModule будет использовать метод createScriptFromCode
для вызова собственного модуля vm узла для фактического выполнения js. Модуль vm принимает безопасный исходный код и использует виртуальную машину V8 с входящим контекстом для немедленного выполнения кода или отсрочки выполнения кода. Здесь вы можете принять разные области действия для выполнения одного и того же кода для вычисления разных результатов, что очень подходит для использования тестовых фреймворков. Внедренный vmContext здесь представляет собой указанную выше глобальную область перезаписи, включая afterAll, afterEach, beforeAll, beforeEach, description, it, test. Таким образом, наш единственный тестовый код получит эти методы с областью внедрения при запуске.
const vm = require("vm"); const script = new vm().Script(scriptSourceCode, option); const filename = module.filename; const vmContext = this._environment.getVmContext(); script.runInContext(vmContext, { filename, });
Когда глобальный метод перезаписывается и state
сохраняется выше, он войдет в логику функции обратного вызова, которая фактически выполняет describe
, в методе run
packages/jest-circus/src/run.ts
, здесь Используйте метод getState
, чтобы вынуть блок кода describe
, затем используйте _runTestsForDescribeBlock
для выполнения этой функции, затем введите метод _runTest
, а затем используйте функцию ловушки до и после выполнения _callCircusHook
и используйте _callCircusTest
для выполнения.
const run = async (): Promise<Circus.RunResult> => { const { rootDescribeBlock } = getState(); await dispatch({ name: "run_start" }); await _runTestsForDescribeBlock(rootDescribeBlock); await dispatch({ name: "run_finish" }); return makeRunResult(getState().rootDescribeBlock, getState().unhandledErrors); }; const _runTest = async (test, parentSkipped) => { // beforeEach // test function block, testContext scope await _callCircusTest(test, testContext); // afterEach };
Это основная позиция реализации функции хука, а также основной элемент функции Jest.
Наконец
Я надеюсь, что эта статья поможет вам понять основную реализацию и принципы среды тестирования Jest. Спасибо, что терпеливо читаете. Если статьи и заметки могут дать вам намек на помощь или вдохновение, пожалуйста, не скупитесь на свою звезду и вилку. Статьи постоянно обновляются синхронно, ваше подтверждение - моя самая большая мотивация двигаться вперед😁