refator: test result type

This commit is contained in:
Anthony Fu 2021-12-09 12:56:10 +08:00
parent 68bb2c1005
commit da229de2cf
5 changed files with 69 additions and 55 deletions

View File

@ -83,8 +83,8 @@ export class DefaultReporter implements Reporter {
return {
title: this.relative(file.filepath),
task: () => {
if (file.error)
throw file.error
if (file.result?.error)
throw file.result?.error
return createSuiteListr(file)
},
@ -116,8 +116,8 @@ export class DefaultReporter implements Reporter {
const suites = files.flatMap(file => file.children.filter(c => c.type === 'suite')) as Suite[]
const tasks = files.flatMap(getSuiteTasks)
const failedFiles = files.filter(i => i.error)
const failedSuites = suites.filter(i => i.error)
const failedFiles = files.filter(i => i.result?.error)
const failedSuites = suites.filter(i => i.result?.error)
const runnable = tasks.filter(i => i.result?.state === 'pass' || i.result?.state === 'fail')
const passed = tasks.filter(i => i.result?.state === 'pass')
@ -132,7 +132,7 @@ export class DefaultReporter implements Reporter {
console.log()
for (const file of failedFiles) {
await printError(file.error)
await printError(file.result?.error)
console.log()
}
}
@ -141,7 +141,7 @@ export class DefaultReporter implements Reporter {
console.error(c.bold(c.red(`\nFailed to run ${failedSuites.length} suites:`)))
for (const suite of failedSuites) {
console.error(c.red(`\n- ${suite.file?.filepath} > ${suite.name}`))
await printError(suite.error)
await printError(suite.result?.error)
console.log()
}
}

View File

@ -1,6 +1,6 @@
import { File, Suite, Task } from '../types'
import { interpretOnlyMode } from '../utils'
import { clearContext, createSuiteHooks, defaultSuite } from './suite'
import { interpretOnlyMode } from './run'
import { context } from './context'
import { setHooks } from './map'
@ -35,7 +35,11 @@ export async function collectTests(paths: string[]) {
}
}
catch (e) {
file.error = e
file.result = {
start: performance.now(),
state: 'fail',
error: e,
}
process.exitCode = 1
}

View File

@ -1,8 +1,9 @@
import { HookListener } from 'vitest'
import { File, ResolvedConfig, Task, RunnerContext, Suite, RunMode, SuiteHooks } from '../types'
import { File, ResolvedConfig, Task, RunnerContext, Suite, SuiteHooks, TaskOrSuite } from '../types'
import { getSnapshotManager } from '../integrations/chai/snapshot'
import { startWatcher } from '../node/watcher'
import { globTestFiles } from '../node/glob'
import { partitionSuiteChildren } from '../utils'
import { getFn, getHooks } from './map'
import { collectTests } from './collect'
import { setupRunner } from './setup'
@ -49,30 +50,21 @@ export async function runTask(task: Task, ctx: RunnerContext) {
await reporter.onTaskEnd?.(task, ctx)
}
/**
* If any items been marked as `only`, mark all other items as `skip`.
*/
export function interpretOnlyMode(items: { mode: RunMode }[]) {
if (items.some(i => i.mode === 'only')) {
items.forEach((i) => {
if (i.mode === 'run')
i.mode = 'skip'
else if (i.mode === 'only')
i.mode = 'run'
})
}
}
export async function runSuite(suite: Suite, ctx: RunnerContext) {
const { reporter } = ctx
await reporter.onSuiteBegin?.(suite, ctx)
suite.result = {
start: performance.now(),
state: 'run',
}
if (suite.mode === 'skip') {
suite.status = 'skip'
suite.result.state = 'skip'
}
else if (suite.mode === 'todo') {
suite.status = 'todo'
suite.result.state = 'todo'
}
else {
try {
@ -92,37 +84,20 @@ export async function runSuite(suite: Suite, ctx: RunnerContext) {
await callHook(suite, 'afterAll', [suite])
}
catch (e) {
suite.error = e
suite.status = 'fail'
suite.result.error = e
suite.result.state = 'fail'
process.exitCode = 1
}
}
suite.result.end = performance.now()
await reporter.onSuiteEnd?.(suite, ctx)
}
async function runSuiteChild(c: (Task | Suite), ctx: RunnerContext) {
return c.type === 'task' ? runTask(c, ctx) : runSuite(c, ctx)
}
/**
* Partition in tasks groups by consecutive computeMode ('serial', 'concurrent')
*/
function partitionSuiteChildren(suite: Suite) {
let childrenGroup: (Task | Suite)[] = []
const childrenGroups: (Task | Suite)[][] = []
for (const c of suite.children) {
if (childrenGroup.length === 0 || c.computeMode === childrenGroup[0].computeMode) {
childrenGroup.push(c)
}
else {
childrenGroups.push(childrenGroup)
childrenGroup = [c]
}
}
if (childrenGroup.length > 0)
childrenGroups.push(childrenGroup)
return childrenGroups
async function runSuiteChild(c: TaskOrSuite, ctx: RunnerContext) {
return c.type === 'task'
? runTask(c, ctx)
: runSuite(c, ctx)
}
export async function runFile(file: File, ctx: RunnerContext) {

View File

@ -103,6 +103,8 @@ export interface TaskResult {
error?: unknown
}
export type TaskOrSuite = Task | Suite
export type TestFunction = () => Awaitable<void>
interface ConcurrentCollector {
@ -149,11 +151,9 @@ export interface Suite {
name: string
mode: RunMode
computeMode: ComputeMode
children: (Task | Suite)[]
state?: SuiteState
children: TaskOrSuite[]
file?: File
error?: unknown
status?: TaskState
result?: TaskResult
}
export interface SuiteCollector {
@ -171,7 +171,6 @@ export type TestFactory = (test: (name: string, fn: TestFunction) => void) => Aw
export interface File extends Suite {
filepath: string
error?: unknown
}
export interface RunnerContext {

36
src/utils.ts Normal file
View File

@ -0,0 +1,36 @@
import { RunMode, Suite, TaskOrSuite } from './types'
/**
* Partition in tasks groups by consecutive computeMode ('serial', 'concurrent')
*/
export function partitionSuiteChildren(suite: Suite) {
let childrenGroup: TaskOrSuite[] = []
const childrenGroups: TaskOrSuite[][] = []
for (const c of suite.children) {
if (childrenGroup.length === 0 || c.computeMode === childrenGroup[0].computeMode) {
childrenGroup.push(c)
}
else {
childrenGroups.push(childrenGroup)
childrenGroup = [c]
}
}
if (childrenGroup.length > 0)
childrenGroups.push(childrenGroup)
return childrenGroups
}
/**
* If any items been marked as `only`, mark all other items as `skip`.
*/
export function interpretOnlyMode(items: { mode: RunMode }[]) {
if (items.some(i => i.mode === 'only')) {
items.forEach((i) => {
if (i.mode === 'run')
i.mode = 'skip'
else if (i.mode === 'only')
i.mode = 'run'
})
}
}