or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdenvironment-integration.mdindex.mdplugin-integration.mdtest-runner.mdutilities.md

test-runner.mddocs/

0

# Test Runner

1

2

Main test runner implementation that executes Jest tests within Stryker's mutation testing workflow. Handles dry runs for coverage analysis and mutant runs for testing specific mutations.

3

4

## Capabilities

5

6

### Jest Test Runner Class

7

8

The primary test runner implementation that manages Jest test execution for mutation testing.

9

10

```typescript { .api }

11

/**

12

* Main Jest test runner implementation for Stryker

13

* Manages Jest configuration, test execution, and result processing

14

*/

15

export class JestTestRunner implements TestRunner {

16

/**

17

* Initialize the test runner with Jest configuration

18

* Loads and merges Jest config from various sources

19

*/

20

init(): Promise<void>;

21

22

/**

23

* Get test runner capabilities

24

* @returns Capabilities indicating reloadEnvironment support

25

*/

26

capabilities(): TestRunnerCapabilities;

27

28

/**

29

* Execute dry run for initial test execution and coverage analysis

30

* @param options - Options including coverage analysis mode and files to test

31

* @returns Results of test execution with optional coverage data

32

*/

33

dryRun(options: Pick<DryRunOptions, 'coverageAnalysis' | 'files'>): Promise<DryRunResult>;

34

35

/**

36

* Execute tests with an active mutant for mutation testing

37

* @param options - Options including active mutant, test filters, and limits

38

* @returns Results of mutant testing execution

39

*/

40

mutantRun(options: MutantRunOptions): Promise<MutantRunResult>;

41

}

42

```

43

44

**Usage Example:**

45

46

```typescript

47

import { JestTestRunner } from "@stryker-mutator/jest-runner";

48

// Note: Typically instantiated through Stryker's dependency injection

49

50

// Test runner is created and managed by Stryker internally

51

// Configuration is passed through Stryker options

52

const runner = new JestTestRunner(logger, options, adapter, configLoader, jestWrapper, namespace);

53

54

// Initialize with Jest configuration

55

await runner.init();

56

57

// Check capabilities

58

const caps = runner.capabilities(); // { reloadEnvironment: true }

59

60

// Execute dry run for coverage analysis

61

const dryResult = await runner.dryRun({

62

coverageAnalysis: 'perTest',

63

files: ['src/example.js']

64

});

65

66

// Execute mutant run

67

const mutantResult = await runner.mutantRun({

68

activeMutant: { id: '1', replacement: '>' },

69

sandboxFileName: 'src/example.js',

70

testFilter: ['should pass basic test'],

71

disableBail: false,

72

hitLimit: 10

73

});

74

```

75

76

### Test Runner Factory

77

78

Factory functions for creating Jest test runner instances with dependency injection.

79

80

```typescript { .api }

81

/**

82

* Create a Jest test runner factory with optional custom namespace

83

* @param namespace - Global namespace for instrumenter (defaults to Stryker namespace)

84

* @returns Factory function with dependency injection configuration

85

*/

86

export function createJestTestRunnerFactory(

87

namespace?: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__'

88

): {

89

(injector: Injector<PluginContext>): JestTestRunner;

90

inject: ['$injector'];

91

};

92

93

/**

94

* Default Jest test runner factory instance

95

* Pre-configured with standard Stryker namespace

96

*/

97

export const jestTestRunnerFactory: ReturnType<typeof createJestTestRunnerFactory>;

98

```

99

100

**Usage Example:**

101

102

```typescript

103

import { createJestTestRunnerFactory, jestTestRunnerFactory } from "@stryker-mutator/jest-runner";

104

105

// Create custom factory with different namespace

106

const customFactory = createJestTestRunnerFactory('__customStryker__');

107

108

// Use default factory (typical usage)

109

const defaultFactory = jestTestRunnerFactory;

110

111

// Factories are used by Stryker's dependency injection system

112

// to create test runner instances with proper dependencies

113

```

114

115

### Jest Test Adapters

116

117

Adapter pattern implementation that abstracts differences between Jest versions.

118

119

```typescript { .api }

120

/**

121

* Factory function that creates version-appropriate Jest test adapter

122

* Automatically selects adapter based on detected Jest version

123

* @returns Jest test adapter instance compatible with current Jest version

124

*/

125

export function jestTestAdapterFactory(): JestTestAdapter;

126

127

/**

128

* Abstract interface for Jest test execution adapters

129

* Provides version-agnostic interface for running Jest tests

130

*/

131

export interface JestTestAdapter {

132

run(settings: RunSettings): Promise<JestRunResult>;

133

}

134

135

/**

136

* Jest test adapter for versions prior to 25.x

137

* Handles legacy Jest API and configuration patterns

138

*/

139

export class JestLessThan25TestAdapter implements JestTestAdapter {

140

run(settings: RunSettings): Promise<JestRunResult>;

141

}

142

143

/**

144

* Jest test adapter for versions 25.x and later

145

* Uses modern Jest API with improved performance and features

146

*/

147

export class JestGreaterThan25TestAdapter implements JestTestAdapter {

148

run(settings: RunSettings): Promise<JestRunResult>;

149

}

150

```

151

152

**Usage Example:**

153

154

```typescript

155

import { jestTestAdapterFactory } from "@stryker-mutator/jest-runner";

156

157

// Factory automatically selects appropriate adapter

158

const adapter = jestTestAdapterFactory();

159

160

// Execute tests with version-appropriate adapter

161

const result = await adapter.run({

162

jestConfig: myJestConfig,

163

fileNamesUnderTest: ['src/example.js'],

164

testLocationInResults: true

165

});

166

```

167

168

## Types

169

170

### Test Runner Interface

171

172

```typescript { .api }

173

interface TestRunner {

174

init(): Promise<void>;

175

capabilities(): TestRunnerCapabilities;

176

dryRun(options: Pick<DryRunOptions, 'coverageAnalysis' | 'files'>): Promise<DryRunResult>;

177

mutantRun(options: MutantRunOptions): Promise<MutantRunResult>;

178

}

179

180

interface TestRunnerCapabilities {

181

reloadEnvironment: boolean;

182

}

183

```

184

185

### Options and Results

186

187

```typescript { .api }

188

interface DryRunOptions {

189

coverageAnalysis: CoverageAnalysis;

190

files: string[];

191

}

192

193

interface MutantRunOptions {

194

activeMutant: Mutant;

195

sandboxFileName: string;

196

testFilter?: string[];

197

disableBail: boolean;

198

hitLimit?: number;

199

}

200

201

interface DryRunResult {

202

status: DryRunStatus;

203

tests?: TestResult[];

204

errorMessage?: string;

205

mutantCoverage?: MutantCoverage;

206

}

207

208

interface MutantRunResult {

209

status: MutantRunStatus;

210

tests?: TestResult[];

211

errorMessage?: string;

212

killedBy?: string[];

213

survivalReason?: string;

214

}

215

216

type CoverageAnalysis = 'off' | 'all' | 'perTest';

217

218

enum DryRunStatus {

219

Complete = 'Complete',

220

Error = 'Error',

221

Timeout = 'Timeout'

222

}

223

224

enum MutantRunStatus {

225

Killed = 'Killed',

226

Survived = 'Survived',

227

Error = 'Error',

228

Timeout = 'Timeout'

229

}

230

```

231

232

### Mutant and Test Types

233

234

```typescript { .api }

235

interface Mutant {

236

id: string;

237

replacement: string;

238

fileName: string;

239

location: Location;

240

}

241

242

interface TestResult {

243

id: string;

244

name: string;

245

status: TestStatus;

246

timeSpentMs: number;

247

fileName?: string;

248

startPosition?: Position;

249

failureMessage?: string;

250

}

251

252

enum TestStatus {

253

Success = 'Success',

254

Failed = 'Failed',

255

Skipped = 'Skipped'

256

}

257

258

interface Position {

259

line: number;

260

column: number;

261

}

262

```

263

264

## Implementation Details

265

266

### Configuration Merging

267

268

The test runner merges Jest configuration from multiple sources:

269

270

1. **File-based config**: Loaded from Jest config files or package.json

271

2. **User config**: Custom configuration from Stryker jest options

272

3. **Override config**: Internal Stryker optimizations and requirements

273

274

### Coverage Analysis Modes

275

276

- **`off`**: No coverage analysis, fastest execution

277

- **`all`**: Global coverage analysis for all tests

278

- **`perTest`**: Individual test coverage tracking (recommended)

279

280

### Hit Limiting

281

282

Prevents infinite loops during mutation testing by limiting the number of times instrumented code can be executed:

283

284

- Configurable hit limit per mutant run

285

- Automatic timeout when limit is exceeded

286

- Helps identify problematic mutations

287

288

### Environment Variables

289

290

The test runner manages several environment variables:

291

292

- **`BABEL_ENV`**: Set to 'test' for proper Babel transformation

293

- **`NODE_ENV`**: Set to 'test' for consistent environment

294

- **`FORCE_COLOR`**: Set to '0' to disable colored output

295

- **Active mutant variable**: Set during mutant runs for instrumenter

296

297

### Performance Optimizations

298

299

- **Related tests**: Uses `--findRelatedTests` to run only relevant tests

300

- **Disabled features**: Turns off Jest features that slow down mutation testing

301

- **Lazy execution**: Defers expensive operations until needed

302

- **Result caching**: Optimizes repeated test executions