bivium
只运行变更可能影响的测试,不要错过任何一个。
Bivium为存储库构建一个静态的、文件级的依赖关系图,并将其从更改所涉及的文件回溯到到达这些文件的测试。它关闭失败:任何它不能读取的东西(非文字) import()(未解析的说明符,没有声明输入的磁盘读取)计数取决于所有内容,并且它无法进行的更改运行整个套件,这是有原因的。它挑选测试;你的跑步者负责跑步。
它没有依赖关系,也不需要安装它计划的存储库:它从不读取git索引和工作树 node_modules. CI可以在跳过安装的作业中进行计划,并跳过选择为 none. 它运行在Node≥22和Bun上。它是从 carbon-components-svelte的 test:changed.
bun add -d bivium
// bivium.config.ts
import { defineConfig } from "bivium";
export default defineConfig({
suites: {
unit: { tests: "tests/**/*.test.ts", run: "vitest run {files}", root: "tests" },
e2e: {
tests: "e2e/**/*.test.ts",
run: "playwright test {files}",
root: "e2e",
urls: { "/*": "e2e/fixtures/*" }, // page.goto("/x.html") → e2e/fixtures/x.html
},
},
roots: ["src", "tests", "e2e"], // a changed file outside them runs everything
ignore: ["**/*.md", "docs/**"],
});
$ bunx bivium plan
unit tests: 3 of 12 files
tests/Button.test.ts
tests/Modal.test.ts
tests/css/unknown.test.ts
e2e tests: none
$ bunx bivium run --suite unit # vitest run tests/Button.test.ts …
它写的是什么?
一遍词法分析器读取JavaScript和TypeScript (.js, .ts, .jsx, .tsx,以及他们的 m/c 的脚本和标记表达式 .svelte,剧本 .vue, .astro 和 .html,和 script[src], link[href] 和 iframe[src] 的 .html. 只有代码才算数:在字符串或注释中拼写的import不加边。
| 它遵循 | 作为 |
|---|---|
静态、副作用和动态导入; export … from, require() | 说明符可以加载的每个文件的边缘:每个存在的扩展名,每个 exports 条件。一个失踪的 x.js (.jsx, .mjs, .cjs)是它的TypeScript源,因为TypeScript会读取它: x.ts, x.tsx 或者 x.d.ts,通过任何路径、别名或 exports 目标。的值导入 x.d.ts 是未知的:什么运行不在图中 |
vi.mock(), vi.importActual() 还有其他的家庭成员 | 边缘 |
import.meta.glob() | 每一个匹配的文件,现在和以后 |
JSDoc @type {import("x")} 和 @import | 边缘(TypeScript读取它们) |
%sveltekit.assets%/x 在SvelteKit里 app.html | 有优势 static/x 在项目中,最近的带有 svelte.config.* 或者一个 package.json. %sveltekit.head%, %sveltekit.body% 其余的都不是参考文献 |
page.goto("/x.html") 在一套房里 urls | 书页的边缘 |
compilerOptions.paths 和 baseUrl 最近的 tsconfig.json,与其亲属 extends | 所有目标的边缘,都试过了 alias 之前, package.json exports. 一个 tsconfig.json 它不解析映射,什么都没有 check 列出它 |
#name 子路径导入,通过 imports 导入文件本身的 package.json | 所有条件的边缘都是存在的;一个无与伦比的 #name 是未知的 |
| 从仅由再导出组成的模块中进行命名导入 | 当包声明时,导出每个名称的一个文件的边缘 sideEffects |
文件自己的包及其祖先的包 package.json 依赖项和内置项 | pkg: 节点 |
| 别的 | 未知:文件取决于每次更改 |
一个根 bun.lock, package-lock.json 或者 pnpm-lock.yaml 不是源文件:对其中一个文件的更改会产生它所更改的包的种子(参见 Lockfiles)。
不能清晰地lex的文件由regex提取器读取,这是过度近似的。CSS不会被扫描:生成的样式表通过 edges,和 窄 可以做得更好。
配置
bivium.config.ts (或 .mts, .mjs, .js, .json),或者 --config <file>. 一个 .ts 配置需要Bun或Node≥22.18。每个glob键取一个glob或一个列表。未知的键是错误的,因为拼写错误的键会悄悄地选择更少的键。
| 关键 | 意义 |
|---|---|
suites.<name>.tests | 套件的测试文件 |
suites.<name>.run | 命令 bivium run 运行。 {files} 被选择(nothing for ? all); 没有它,文件将被追加 |
suites.<name>.root | 孤儿规则适用的地方:套件测试无法到达的更改文件以其他方式连接(安装文件,运行器配置),因此整个套件运行。路径,而不是globs (e2e,而不是 e2e/**): glob是一个错误。默认值:整个存储库 |
suites.<name>.urls | URL模式→文件模式,for page.goto() 电话下 root |
suites.<name>.pages | 只有一页 goto() 打开;只有它们加载的文件才连接到没有测试 |
suites.<name>.setup | 运行程序在每次测试(测试和测试)之前加载的文件 setupFiles,摩卡 --require,剧作家 globalSetup):套件的每个测试都依赖于它们和它们导入的内容。Bivium不会读取跑步者的配置,所以在这里命名它们 |
suites.<name>.wiring | 其更改运行整个套件的文件:另一个套件,一个运行器配置 |
suites.<name>.nonInputs | 下的文件 root 运行程序从不读取,例如类型检查输入 |
suites.<name>.types | false 当套件运行代码并且无法观察类型(Vitest, Jest,剧作家, bun test):只能通过 import type, export type … from, JSDoc类型或声明文件都不选择它们。对于孤儿规则,仅类型到达只对声明文件计数,因为运行器可以按名称加载任何其他文件:列表下的仅类型模块 root 在 nonInputs。默认值: true,其中一个类型检查套件(tsc, vitest --typecheck)的需求。内联 import { type A } 永远是一个边缘:下 verbatimModuleSyntax 它仍然会加载模块 |
suites.<name>.output | 步进输出 plan --github 写道。默认值: <name>-tests |
roots | 图读取的路径(不是globs)。在它们之外的一个未被忽略的更改文件将运行所有内容。默认值:整个存储库 |
ignore | 没有测试可以观察到的文件,除非通过边缘(文档,故事)。对1的更改只选择到达它的测试,从不按孤立规则运行套件,并且不选择依赖未知的测试 |
alias | 说明符前缀→路径,作为打包器的别名。在tsconfig之前尝试过 paths 和 package.json exports. 以结尾的键 / 是前缀,就像Vite读到的: { "@/": "src/" } 地图 @/x 来 src/x |
edges | 生成的文件glob→它的输入,它依赖于传递,如 @depends-on: { "dist/*.css": "styles/**" }. 一个键可能会命名git没有列出的文件,比如被git忽略的生成器输出({ ".velite/*": "content/**" }):在它下解析的导入,通过扩展名或作为索引,落在该文件上,而不是未解析。在一个值中, $1, $2…是键的通配符匹配的内容,从左开始计数: { "examples/*/package.json": "examples/$1/**" } |
reads | 文件glob→它作为文本读取的文件,如 @reads只有一个国家的直接变化才有意义,所以他们的输入和未知不会传播到它。一个 edges 或者 reads 为一个文件命名的键(没有通配符)声明它所读取的内容为它自己的 @depends-on 或者 @reads 会,所以它的磁盘读取不是未知的。值采取 $1… edges: { "tests/*.test.ts": "tests/__snapshots__/$1.test.ts.snap" } |
self | 选择器自己的文件:更改一个就可以运行所有文件。配置文件总是一个 |
importOnly | 只有导入到达的文件:删除一个文件不会使套件孤立 |
hermetic | 磁盘读取和非文字导入的文件不会到达存储库的文件:库的文件 fs 调用调用者的路径,这种测试只读取它所写的临时文件。他们没有添加未知 |
barrels | 可以绑定命名导入的模块。默认:每个模块只由再出口组成 |
external | 将代码导入的依赖项安装打包而不声明 |
inert | 没有测试使用的包,除非导入它们:lint、formatters、type包(["@biomejs/biome", "knip", "@types/*"]). 一个 lockfile变化 只有他们到达选择什么。与 loadedByName 设置,只包带有 bin 需要的清单 |
loadedByName | 测试可以通过导入以外的方式加载的包:一个测试环境或一个配置用字符串(["jsdom", "ts-jest"]). 设置它,甚至到 [],每隔一个没有 bin 只通过导入加载,所以a lockfile变化 达到一个没有测试导入只选择它的导入。有一个包裹。 bin 总是作为一个测试可以运行 |
extensions | 在指定符之后尝试后缀 |
deadGlobs | 死着 check 允许,每个 { file, glob, reason },地球仪 file 法术, |
knownUnknowns | 节点 check 允许有未知的依赖关系 { file, reason }. 有了它,连到 [] (这是 --max-unknown 0), check 在一个未知节点上失败,一些测试到达它没有列出,在一个条目不再是未知的,所以一个新的未知不能取代一个消失了 |
narrowers | 看到 窄 |
base | 默认base ref.否则上游默认分支(origin/HEAD,然后 origin/main, origin/master, main, master) |
cache | 缓存的目录,或 false。默认值: node_modules/.cache/bivium,或者 .bivium/cache |
测试无法达到的变化
套房下的一个更改文件 root 套件的测试没有达到其他方式(一个运行器配置,一个设置文件),所以整个套件运行:孤儿规则。使用默认值 root,整个存储库,任何文件bivium都无法追踪到测试运行套件,这是健全和粗糙的。集 root 在每个套件的测试和源代码所在的目录中,说明其余部分是什么:
| 你改变了…… | 和希望…… | 使用 |
|---|---|---|
| 一个没有测试可以观察到的文件:文档、故事、变更日志 | 没有什么可运行的,除非某些测试导入它 | ignore |
套房下的一个文件 root 只有另一个工具读取:类型检查输入 | 这套房没什么可跑的 | 套房的 nonInputs |
| 一个跑路配置或第二个线束 | 整个套房 | 套房的 wiring |
| 运行程序在每次测试之前加载的安装文件,或者它导入的文件 | 套件的每个测试 | 套房的 setup |
| 选择器的配置,或者它自己的代码 | 一切 | self (配置文件总是如此) |
| 一个声明文件,在运行代码的套件中 | 没有什么 | 套房的 types: false |
仅类型模块 import type 达克斯,在一个运行代码的套件里 | 没有什么 | 套房的 types: false,其中的模块 nonInputs |
| 可以测试列出但不能读取的文件(一条路由,一个故事) | 测试,当一个被添加或删除 | // @lists <glob> 在测试中 |
| 构建时将文件转换为测试加载的文件 | 加载输出的测试 | edges 从输出到输入 |
外面的文件 roots 没有被忽视的运行一切:它是连接图无法看到的支撑,例如CI工作流。
食谱
玩笑还是玩笑。 命名运行程序加载的安装文件,mirror resolve.alias a我很喜欢 "@/" 像编写的那样工作),为他们的测试提供快照,并且,对于运行代码的套件,跳过仅类型的边缘:
suites: {
unit: {
tests: "src/**/*.test.{ts,tsx}",
run: "vitest run {files}",
root: "src",
setup: ["src/setupTests.ts"], // vitest.config.ts `setupFiles`
wiring: ["vitest.config.ts"],
types: false,
nonInputs: ["src/**/types.ts"], // types only: nothing loads them at runtime
},
},
alias: { "@/": "src/" },
reads: { "src/**/*.test.{ts,tsx}": "src/$1__snapshots__/$2.test.$3.snap" },
tsconfig paths ( vite-tsconfig-paths read)是不带an的 alias. 一个无广延性的 vi.mock("@/x") 像导入一样解析。运行程序按名称加载的测试环境(jsdom, happy-dom)进去了 loadedByName 如果你设置它。
规划工作区。 工作区包通过它们的 package.json exports,和 .js 指定符转换为一个(@acme/ui/Button.js)达到它的 .ts 源。一个 pnpm-lock.yaml Change通过它所更改的包进行选择。集 roots 到套件应该看到其更改的包和应用程序,以及每个测试运行器的套件。
剧作家。 地图 page.goto() 它们打开的页面的url urls,只列出一页 goto() 打开在 pages,及名称 playwright.config.ts 在 wiring:
e2e: {
tests: "e2e/**/*.spec.ts",
root: "e2e",
urls: { "/*": "e2e/fixtures/*.html" },
wiring: ["playwright.config.ts"],
},
生成的代码。 将内容或类型生成器写入被忽略的目录(.velite, .contentlayer/generated)是一个 edges 从写到读的条目: { ".velite/*": ["content/**", "velite.config.ts"] }. 的进口 #velite 或者 ../.velite 然后到达内容,而不是每一个变化。
Lockfiles
依赖关系会改变一个锁文件,而没有文件会导入它。当一个根 bun.lock, package-lock.json (v2或v3)或 pnpm-lock.yaml (v6或v9)更改后,bivium将其与合并基础进行区分,并使用 pkg: 条目发生变化的包的节点,以及依赖于其中一个包的每个包的节点,所以a svelte Bump选择导入的内容 svelte,或者在此基础上构建的软件包。一个 package.json 其唯一的变化是依赖,lockfile记录的方式与那些包的变化相同。
更改后的包还可以以图中看不到的方式使用:测试生成的CLI、运行器、类型包。所以当一个包发生变化时 package.json 声明,或者一些文件导入,而没有测试导入,一切都运行,原因是(bun.lock: playwright 1.63.0 → 1.64.0, and no test imports it),除非包裹是 inert. 与 loadedByName 集,只包带一个 bin 在lockfile中,或它所列出的文件中,以这种方式计数:仅到达CMS配置导入库的碰撞不选择任何内容。对于一个bivium无法解析的lockfile,它的设置(除了它的包之外)也可以运行。overrides补丁,pnpm settings, catalogs(或PNPM本身的版本),以及 package.json 更改lockfile不记录。其他锁档(yarn.lock, bun.lockb)是和其他文件一样的文件:在根目录之外,对一个文件的修改会运行所有文件。
$ bunx bivium plan
bun.lock: @biomejs/biome 2.5.14 → 2.6.3, inert
bun.lock: svelte 5.57.1 → 5.57.2
unit tests: 4 of 12 files
…
注释
| 评论 | 意义 |
|---|---|
// @depends-on <glob> [glob…] | 非导入的输入:脚本读取的文件,生成的工具。传递。一种文件,它读取磁盘时没有一个(或。 @reads,或者 @lists)是未知的,除非它 hermetic |
// @reads <glob> [glob…] | 文件作为文本读取。只有直接更改一个才算数,而不是更改它所导入的内容。配置的 reads 对于不能保存注释的文件也这样说 |
// @lists <glob> [glob…] | 它列出文件名而不是内容的文件:检查每条路由的约定测试都有一个处理程序。只有添加、删除或重命名一个才算数;编辑不会选择它,也不会按照孤立规则运行它的套件 |
// @glob-registry | 这个文件的 import.meta.glob 是一个查找表,不添加边:加载条目名称本身是什么 |
命令行界面
| 命令 | 做 |
|---|---|
bivium plan [base] [--json] [--github] | 打印每个套房的选择(none,文件出了多少, all 文件,或者 all (full run)),以及为什么一个套房会满员。 --json 添加基础,合并基础,更改的文件,更窄的结果,更改的包,每个套件的测试计数(totals),以及作为数据的原因(causes,每一个 FullRunCause: { kind, suites, file?, package?, narrower?, message })。 --github 还将每个套件的选择写入 $GITHUB_OUTPUT |
bivium run [base] [--suite <name>] | 管理套房 run 命令及其选择(默认:第一个套件),或者在没有任何影响时跳过它 |
bivium why <test> [file] [--format tree|chain|source|json] [--all] | 从已更改的文件或从 file每条边和它所在的线的拼写,以及有多少其他的变化达到了测试。 --format tree (默认值)从测试中提取; chain 从更改中读取到测试; source 打印每个跳的源行; json (或 --json)将链打印为数据。 --all 显示每个变化的链。对于未选择的测试,它会显示文件链到达的位置 |
bivium check [--max-unknown <n>] [--json] | 首先计算它根据原因找到了什么,然后列出每个具有未知依赖关系的节点,以及在哪里和如何修复每个原因,并在超过 n 他们中的一个达到了测试,或者只有一个 knownUnknowns 没有列表。没有测试所依赖的节点被单独列出并且不计数:计划只运行测试,因此没有扩展。还列出了 tsconfig.json 不能解析的文件,以及 死着,一次失败 deadGlobs 不允许在不匹配的条目上使用或。 --json 将报告打印为数据 |
bivium graph [--suite <name>] [--top <n>] [--json] | 对每个文件的更改在图中选择了多少个套件的测试(忽略在任何更改上运行的测试,它分开计算): n 到达最多的文件,以及文件如何从没有扩展到每个测试。达到大多数测试的几个集线器文件是使计划广泛的东西。 --json 打印每个套房的 total 和 everyChange 测试,每个节点都有它的 imports 和 importers (文件边), fanIn 每个套房,是否 unknown |
--config, --cwd 和 --no-cache 使用每个命令,在它之前或之后,和 why 和 check 采取 --base <ref>. --help (或 -h)打印使用情况。一个未知的命令、选项或 --format 是一个错误。退出状态:完成时为0,完成时为1 check 查找问题,2用于查找使用或配置错误; run 带着命令的状态退出。
why 按拼法命名每条边: import, type (一个 import type, export type … from(JSDoc类型,或与声明文件之间的边), setup (一个套件的安装文件), goto (一个页面 page.goto() 打开), html (一个HTML页面加载的模块: script[src], link[href], iframe[src] 或者内联脚本的import), name (绑定到桶名的命名导入)和 export (导出它的文件), glob (import.meta.glob), depends-on, edges (配置) reads 和 lists.
$ bunx bivium why e2e/accordion.test.ts
e2e/accordion.test.ts
└─ goto e2e/fixtures/accordion.html e2e/accordion.test.ts:13
└─ html e2e/fixtures/accordion.ts e2e/fixtures/accordion.html:10
└─ import e2e/fixtures/Fixture.svelte e2e/fixtures/accordion.ts:1
└─ name src/index.js#AccordionItem e2e/fixtures/Fixture.svelte:2
└─ export src/AccordionItem.svelte src/index.js:2
● changed
+ 1 more change reaches this test: css/_accordion.scss (--all shows each chain)
$ bunx bivium why e2e/accordion.test.ts --format chain
src/AccordionItem.svelte changed
exported as AccordionItem src/index.js:2
imported by e2e/fixtures/Fixture.svelte:2
imported by e2e/fixtures/accordion.ts:1
loaded by page e2e/fixtures/accordion.html:10
opened by e2e/accordion.test.ts:13 ← selected
+ 1 more change reaches this test: css/_accordion.scss (--all shows each chain)
$ bunx bivium why e2e/accordion.test.ts --format source
selected: e2e/accordion.test.ts ← src/AccordionItem.svelte (5 hops)
--> e2e/accordion.test.ts:13 goto
13 | await page.goto("/accordion.html");
--> e2e/fixtures/accordion.html:10 html
10 | <script type="module" src="./accordion.ts"></script>
--> e2e/fixtures/accordion.ts:1 import
1 | import Fixture from "./Fixture.svelte";
--> e2e/fixtures/Fixture.svelte:2 name
2 | import { Accordion, AccordionItem } from "carbon-components-svelte";
--> src/index.js:2 export
2 | export { default as AccordionItem } from "./AccordionItem.svelte";
● src/AccordionItem.svelte: changed
+ 1 more change reaches this test: css/_accordion.scss (--all shows each chain)
对于一个依赖于每一个变化的测试, chain 说明为什么,在哪里,以及如何修复它,如 check :
$ bunx bivium why tests/e2e.test.ts --format chain
tests/e2e.test.ts runs on every change
because scripts/launcher.js:10 unresolved "./cli-entry.js"
fix: no file at that path: fix the import, or add an `edges` entry if a build generates it
reached via scripts/launcher.js
depended on by scripts/build.ts:1
depended on by tests/e2e.test.ts:2 ← selected
死着
一个错字就 @depends-on,或者只指向计划器跳过的文件,看起来很好,但从不选择它的文件。 check 评估每一个 @depends-on, @reads, @lists 和 import.meta.glob 模式,每 edges 和 reads 价值,每个套房 setup,针对git列出的每个文件(跟踪的和未跟踪的,是否在根目录中),并报告其中一个:
| 问题 | 意味着 |
|---|---|
| 不匹配 | 没有文件匹配:拼写错误或过时的路径 |
| 只匹配被忽略的文件,部分被忽略 | 有些匹配会被忽略,并且不在图中,因此更改为1将不选择任何内容 |
带有capture的配置值只有在其键匹配的每个文件都不匹配时才会失效,并且在配置文件下也会报告与图读取的文件不匹配的键。图读取的被忽略的文件仍然是遍历的种子,而根之外的更改将运行所有内容,因此两者都不是死的。一个故意死掉的球进去 deadGlobs 有一个原因:
deadGlobs: [
{ file: "tests/css/tokens.test.ts", glob: "docs/src/**", reason: "docs-only changes skip CI" },
],
CI
在任何安装之前,计划自己的作业,并为每个套件的作业提供其选择:
jobs:
plan:
runs-on: ubuntu-latest
outputs:
unit: ${{ steps.plan.outputs.unit-tests }}
e2e: ${{ steps.plan.outputs.e2e-tests }}
steps:
- uses: actions/checkout@v7
with:
# History for the merge base, without old file contents: git
# fetches the few a plan reads (a changed barrel or lockfile).
fetch-depth: 0
filter: blob:none
- uses: oven-sh/setup-bun@v2
- id: merge-base
run: echo "sha=$(git merge-base origin/main HEAD)" >> "$GITHUB_OUTPUT"
- uses: actions/cache@v6
with:
path: .bivium/cache
key: bivium-${{ steps.merge-base.outputs.sha }}
restore-keys: bivium-
- id: plan
# --bun: run on Bun, which loads a TypeScript config whatever Node
# the runner has.
run: bunx --bun bivium plan origin/main --github
unit:
needs: plan
if: needs.plan.outputs.unit != 'none'
steps:
# …install, then run all tests or the selected files:
- run: bunx vitest run ${{ needs.plan.outputs.unit != 'all' && needs.plan.outputs.unit || '' }}
缓存保存从每个文件提取的内容,这些内容由git blob键控,因此warm计划只读取分支更改的文件。在合并基础上键入它:拉取请求可以从默认分支恢复缓存,该分支在提交时运行是要命中的。没有 node_modules,缓存就在 .bivium/cache;它写了一个 .gitignore 所以它不会显示为变化。
在一台苹果m系列笔记本电脑的负载情况下,一个套餐的成本是多少(5个套餐中值,待机时间):
| 存储库 | 文件 | 包,没有缓存 | 包子,温暖 | 节点24,没有缓存 | 节点24,温暖 | 缓存 |
|---|---|---|---|---|---|---|
| carbon-components-svelte | 4680年 | 0.15秒 | 0.09秒 | 0.27秒 | 0.13秒 | 452 KB |
| 生成的TypeScript, 23 MB | 7000年 | 0.14秒 | 0.08秒 | 0.30秒 | 0.12秒 | 896 KB |
所以这个大小的缓存是可选的, bunx --bun 这是值得的,并且在测试作业中进行规划(没有额外的作业,没有安装)花费的时间不到一秒钟。生成的存储库的冷计划在Bun上的RSS峰值为88 MB,在Node上为124 MB。
窄
有些更改通过生成的文件到达每个测试:每个页面加载已编译的样式表,因此任何样式编辑都会选择每个测试。更窄的使用来自语义差异的更细的种子替换这种更改的粗种子,例如呈现更改的CSS规则的源。
narrowers: [
{
name: "css",
match: "styles/**", // the changed files it narrows
opaque: "dist/*.css", // the generated nodes its seeds stand in for
suites: ["e2e"],
async narrow({ base, head, changed, graph }) {
const rules = diffRules(await compile(base.commit), await compile(head.commit));
if (!rules) return { all: "a rule that requires no class changed" };
return { seeds: sourcesSpelling(rules), note: `${rules.length} rules changed` };
},
},
],
匹配的文件仍然沿着路径走,但是它停在 opaque 结点和种子代表着它们。窄的只能窄:它的套房的选择被削减到没有它选择的步行。一个返回的 { all: reason }抛出或返回的任何东西都将完整地运行其套件。 narrow() 获取存储库 root,合并基和工作树为 base 和 head (每个都有 commit 和 read(path)),匹配的 changed 文件,和只读 graph (nodes(), importers(node), dependents(nodes), tests(suite))。 eval/carbon/css-narrower.ts 它的碳成分是细长的,在玻璃上。
从代码
import { defineConfig, plan } from "bivium";
const config = defineConfig({ suites: { unit: { tests: "tests/**/*.test.ts" } } });
const result = await plan({ config, base: "origin/main" });
result.suites.unit; // { mode: "some", files: [...] }; result.suites.e2e is a type error
plan(options?) 需要 cwd, base, config (默认:配置文件 cwd), cache,并返回每个套件的选择、测试计数、作为句子和数据的原因、lockfile更改种子或发现惰性的包、基文件、合并基文件和更改的文件,以及每个狭窄返回的内容。给定一个配置,套件名称将传递到结果的类型。包只导出 plan, defineConfig 以及它们的类型。
相比之下,
| 选择 | 错过 | |
|---|---|---|
vitest --changed, jest --changedSince | 从运行程序自己的解析器测试其模块图到达已更改文件的测试 | 磁盘读取,固定装置,页面测试访问,配置和设置布线 |
剧作家 --only-changed | 测试导入更改的文件 | 测试打开的页面以及它们加载的内容 |
| Nx, Turborepo | 整个项目的投入发生了变化 | 在项目粒度中,项目声明的输入中没有任何内容 |
| 巴泽尔 | 其声明的输入发生变化的目标 | 如果每个输入都声明了,那么什么也没有 |
| bivium | 测试文件,跨运行程序和文件类型,从一个图 | 它什么也看不见;它不能的,它就跑 |