Инфраструктура тестирования
INFO
Эта заметка — приглашение обмениваться идеями по улучшению тестовой инфраструктуры; можно связаться с нами в Discord.
В Oxc надёжность и корректность воспринимаются очень серьёзно.
Много времени уходит на укрепление тестовой инфраструктуры, чтобы проблемы не доходили до downstream-инструментов.
Парсер
Соответствие спецификации
Используются парсерные тесты из Test262, Babel и TypeScript для проверки синтаксиса JavaScript, TypeScript и JSX.
Для Test262 включены все тесты stage 4 и тесты регулярных выражений.
Результаты соответствия хранятся в снимках для отслеживания изменений:
Все синтаксические ошибки попадают в эти файлы-снимки для удобного диффа.
Фаззинг
Чтобы парсер не падал на случайных данных, используются три фаззера:
- cargo fuzz: случайные байты в парсер.
- shift-fuzzer-js от bakkot — случайные, но синтаксически валидные AST.
- Automated-Fuzzer от qarmin; он активно сообщает о падениях.
Безопасность памяти
У Oxc для AST и связанных структур используется arena на базе bumpalo. У типов узлов AST нет реализации Drop. allocator Oxc на этапе компиляции запрещает класть в arena типы с Drop, если кто-то попытается — будет ошибка компиляции. Так статически гарантируется, что владеющие кучей данные не окажутся в arena без возможности их корректно освободить.
Небезопасный код
unsafe используется ради производительности. Мы стараемся держать его внутри изолированных структур с безопасным внешним API. Miri прогоняется по крейтам с таким кодом на каждом PR.
Линтер
Снимки диагностик
Все диагностики линтера пишутся в файлы-снимки для регрессионных тестов.
Пример:
⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent.
╭─[adjacent_overload_signatures.tsx:3:18]
2 │ function foo(s: string);
3 │ function foo(n: number);
· ───
4 │ type bar = number;
5 │ function foo(sn: string | number) {}
· ───
6 │ }
╰────Ecosystem CI
oxc-ecosystem-ci гоняет oxlint по крупным репозиториям в поисках ложных срабатываний, регрессий и паник. Среди проверяемых:
- rolldown/rolldown
- napi-rs/napi-rs
- toeverything/affine
- preactjs/preact
- microsoft/vscode
- bbc/simorgh
- elastic/kibana
- DefinitelyTyped/DefinitelyTyped
Идемпотентность
Идемпотентное тестирование применяется в интеграционных и сквозных тестах всех инструментов.
Схема:
let sourceText = "foo";
let printed = tool(sourceText);
let printed2 = tool(printed);
assert(printed == printed2);Например, повторное минифицирование одного и того же кода должно давать тот же результат.
Все инструменты (парсер, трансформер, минификатор и т.д.) идемпотентно тестируются на файлах из Test262, Babel и TypeScript.
Интеграционные тесты
Предпочтительны интеграционные тесты, а не изолированные юнит-тесты.
codecov сейчас показывает покрытие по строкам.
Сквозные тесты
Репозиторий monitor-oxc выполняет E2E-тесты на топ-3000 пакетов npm из npm-high-impact.
В package.json перечислены 3000 зависимостей:
"devDependencies": {
"@aashutoshrathi/word-wrap": "latest",
"@actions/http-client": "latest",
"@adobe/css-tools": "latest",
"@alloc/quick-lru": "latest",
...
"zip-stream": "latest",
"zod": "latest",
"zone.js": "latest",
"zustand": "latest"
}И тестовый файл, который импортирует пакеты и проверяет импорт:
src/dynamic.test.mjs
import test from "node:test";
import assert from "node:assert";
test("@aashutoshrathi/word-wrap", () => import("@aashutoshrathi/word-wrap").then(assert.ok));
test("@actions/http-client", () => import("@actions/http-client").then(assert.ok));
test("@adobe/css-tools", () => import("@adobe/css-tools").then(assert.ok));
test("@alloc/quick-lru", () => import("@alloc/quick-lru").then(assert.ok));
...
test("zod", () => import("zod").then(assert.ok));
test("zone.js", () => import("zone.js").then(assert.ok));
test("zustand", () => import("zustand").then(assert.ok));
test("zwitch", () => import("zwitch").then(assert.ok));Файл запускается после того, как инструменты (codegen, трансформер, минификатор и т.д.) переписали все файлы в node_modules.
Пакеты ежедневно обновляются до последних версий.
Так находились многие редкие баги, которые пропускали наборы соответствия.
Если есть идеи, как улучшить нашу тестовую инфраструктуру, пишите в Discord.