or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

config-storage.mdengine-implementation.mdhierarchical-engine.mdindex.mdtest-descriptors.mdtest-discovery.mdtest-execution.md

test-execution.mddocs/

0

# Test Execution

1

2

Test execution infrastructure providing contexts, listeners, and result reporting for test engines. This system enables engines to execute discovered tests and communicate results back to the platform.

3

4

## Capabilities

5

6

### ExecutionRequest

7

8

Provides test engines with everything needed to execute discovered tests, including the test descriptor tree, execution listener, configuration, and test-scoped storage.

9

10

```java { .api }

11

/**

12

* Request object providing context and resources for test execution.

13

*/

14

public final class ExecutionRequest {

15

/**

16

* Get the root test descriptor to execute.

17

* @return root test descriptor containing test hierarchy

18

*/

19

public TestDescriptor getRootTestDescriptor();

20

21

/**

22

* Get the engine execution listener for reporting test events.

23

* @return execution listener for this request

24

*/

25

public EngineExecutionListener getEngineExecutionListener();

26

27

/**

28

* Get configuration parameters for test execution.

29

* @return configuration parameters

30

*/

31

public ConfigurationParameters getConfigurationParameters();

32

33

/**

34

* Get the output directory provider for file outputs.

35

* @return output directory provider

36

*/

37

public OutputDirectoryProvider getOutputDirectoryProvider();

38

39

/**

40

* Get the request-scoped hierarchical store.

41

* @return namespaced hierarchical store for request-scoped data

42

*/

43

public NamespacedHierarchicalStore<Namespace> getStore();

44

}

45

```

46

47

**Usage Example:**

48

49

```java

50

@Override

51

public void execute(ExecutionRequest request) {

52

TestDescriptor rootDescriptor = request.getRootTestDescriptor();

53

EngineExecutionListener listener = request.getEngineExecutionListener();

54

ConfigurationParameters config = request.getConfigurationParameters();

55

56

// Start execution of root descriptor

57

listener.executionStarted(rootDescriptor);

58

59

try {

60

// Execute all child descriptors

61

for (TestDescriptor child : rootDescriptor.getChildren()) {

62

executeDescriptor(child, listener, config);

63

}

64

listener.executionFinished(rootDescriptor, TestExecutionResult.successful());

65

} catch (Exception e) {

66

listener.executionFinished(rootDescriptor, TestExecutionResult.failed(e));

67

}

68

}

69

```

70

71

### EngineExecutionListener Interface

72

73

Listener interface for receiving test execution events and results. Test engines use this to communicate execution progress and outcomes.

74

75

```java { .api }

76

/**

77

* Listener for test execution events, enabling engines to report progress and results.

78

*/

79

public interface EngineExecutionListener {

80

/**

81

* Called when a dynamic test is registered during execution.

82

* @param testDescriptor the dynamically registered test descriptor

83

*/

84

void dynamicTestRegistered(TestDescriptor testDescriptor);

85

86

/**

87

* Called when execution of a test or container is skipped.

88

* @param testDescriptor the skipped test descriptor

89

* @param reason the reason for skipping

90

*/

91

void executionSkipped(TestDescriptor testDescriptor, String reason);

92

93

/**

94

* Called when execution of a test or container starts.

95

* @param testDescriptor the test descriptor being executed

96

*/

97

void executionStarted(TestDescriptor testDescriptor);

98

99

/**

100

* Called when execution of a test or container finishes.

101

* @param testDescriptor the test descriptor that finished

102

* @param testExecutionResult the execution result

103

*/

104

void executionFinished(TestDescriptor testDescriptor, TestExecutionResult testExecutionResult);

105

106

/**

107

* Called when a reporting entry is published during test execution.

108

* @param testDescriptor the test descriptor publishing the entry

109

* @param entry the report entry with key-value data

110

*/

111

void reportingEntryPublished(TestDescriptor testDescriptor, ReportEntry entry);

112

113

/**

114

* Called when a file entry is published during test execution.

115

* @param testDescriptor the test descriptor publishing the file

116

* @param fileEntry the file entry attachment

117

*/

118

void fileEntryPublished(TestDescriptor testDescriptor, FileEntry fileEntry);

119

120

/**

121

* No-operation listener implementation.

122

*/

123

EngineExecutionListener NOOP = new EngineExecutionListener() {

124

// All methods have empty implementations

125

};

126

}

127

```

128

129

**Usage Example:**

130

131

```java

132

private void executeTest(TestDescriptor testDescriptor, EngineExecutionListener listener) {

133

listener.executionStarted(testDescriptor);

134

135

try {

136

// Execute the actual test logic

137

Object testInstance = createTestInstance(testDescriptor);

138

Method testMethod = getTestMethod(testDescriptor);

139

140

// Publish reporting entry before execution

141

ReportEntry entry = ReportEntry.from("phase", "execution");

142

listener.reportingEntryPublished(testDescriptor, entry);

143

144

// Execute test method

145

testMethod.invoke(testInstance);

146

147

// Report successful completion

148

listener.executionFinished(testDescriptor, TestExecutionResult.successful());

149

150

} catch (AssertionError e) {

151

// Test failed

152

listener.executionFinished(testDescriptor, TestExecutionResult.failed(e));

153

} catch (Exception e) {

154

// Test aborted due to unexpected error

155

listener.executionFinished(testDescriptor, TestExecutionResult.aborted(e));

156

}

157

}

158

```

159

160

### Reporting Infrastructure

161

162

Classes for publishing structured reporting data and file attachments during test execution.

163

164

```java { .api }

165

/**

166

* Time-stamped key-value pairs for structured reporting during test execution.

167

*/

168

public final class ReportEntry {

169

/**

170

* Create a report entry from a map of key-value pairs.

171

* @param keyValuePairs map of keys to values

172

* @return ReportEntry with current timestamp

173

*/

174

public static ReportEntry from(Map<String, String> keyValuePairs);

175

176

/**

177

* Create a report entry from a single key-value pair.

178

* @param key the report key

179

* @param value the report value

180

* @return ReportEntry with current timestamp

181

*/

182

public static ReportEntry from(String key, String value);

183

184

/**

185

* Get the key-value pairs for this report entry.

186

* @return unmodifiable map of key-value pairs

187

*/

188

public Map<String, String> getKeyValuePairs();

189

190

/**

191

* Get the timestamp when this entry was created.

192

* @return creation timestamp

193

*/

194

public LocalDateTime getTimestamp();

195

}

196

197

/**

198

* File attachment for test execution reporting.

199

*/

200

public final class FileEntry {

201

/**

202

* Create a file entry from a path and media type.

203

* @param path path to the file

204

* @param mediaType media type of the file

205

* @return FileEntry instance

206

*/

207

public static FileEntry from(Path path, String mediaType);

208

209

/**

210

* Create a file entry from a path with content type detection.

211

* @param path path to the file

212

* @return FileEntry with detected media type

213

*/

214

public static FileEntry from(Path path);

215

216

/**

217

* Get the file path.

218

* @return path to the file

219

*/

220

public Path getPath();

221

222

/**

223

* Get the media type.

224

* @return media type of the file

225

*/

226

public String getMediaType();

227

}

228

```

229

230

**Usage Example:**

231

232

```java

233

// Publish structured reporting data

234

Map<String, String> data = Map.of(

235

"test.type", "integration",

236

"database.url", "jdbc:h2:mem:test",

237

"execution.time", "1.234s"

238

);

239

ReportEntry entry = ReportEntry.from(data);

240

listener.reportingEntryPublished(testDescriptor, entry);

241

242

// Publish file attachments

243

Path screenshotPath = captureScreenshot();

244

FileEntry fileEntry = FileEntry.from(screenshotPath, "image/png");

245

listener.fileEntryPublished(testDescriptor, fileEntry);

246

```

247

248

### Output Directory Provider

249

250

Interface for providing output directories where test engines can write files during execution.

251

252

```java { .api }

253

/**

254

* Provider for output directories where test engines can write execution artifacts.

255

*/

256

public interface OutputDirectoryProvider {

257

/**

258

* Get the default output directory for the current test execution.

259

* @return path to the default output directory

260

*/

261

Path getDefaultOutputDirectory();

262

263

/**

264

* Get a subdirectory within the default output directory.

265

* @param subdirectoryName name of the subdirectory

266

* @return path to the subdirectory (created if necessary)

267

*/

268

Path getOutputDirectory(String subdirectoryName);

269

270

/**

271

* Get an output directory for a specific test descriptor.

272

* @param testDescriptor the test descriptor

273

* @param subdirectoryName optional subdirectory name

274

* @return path to the output directory for the test

275

*/

276

Path getOutputDirectory(TestDescriptor testDescriptor, String subdirectoryName);

277

}

278

```

279

280

### Dynamic Test Registration

281

282

Support for registering tests dynamically during execution, enabling parameterized and data-driven test patterns.

283

284

**Usage Example:**

285

286

```java

287

// In a test engine's execute method

288

private void executeDynamicContainer(TestDescriptor containerDescriptor,

289

EngineExecutionListener listener) {

290

listener.executionStarted(containerDescriptor);

291

292

// Generate dynamic tests based on data

293

List<TestData> testData = loadTestData();

294

295

for (TestData data : testData) {

296

// Create dynamic test descriptor

297

UniqueId dynamicId = containerDescriptor.getUniqueId()

298

.append("dynamic", data.getName());

299

TestDescriptor dynamicTest = createDynamicTestDescriptor(dynamicId, data);

300

301

// Register dynamic test

302

containerDescriptor.addChild(dynamicTest);

303

listener.dynamicTestRegistered(dynamicTest);

304

305

// Execute the dynamic test

306

executeDynamicTest(dynamicTest, data, listener);

307

}

308

309

listener.executionFinished(containerDescriptor, TestExecutionResult.successful());

310

}

311

```

312

313

### Configuration Integration

314

315

Integration with the configuration system for accessing execution parameters.

316

317

**Usage Example:**

318

319

```java

320

@Override

321

public void execute(ExecutionRequest request) {

322

ConfigurationParameters config = request.getConfigurationParameters();

323

324

// Get configuration values

325

boolean parallelExecution = config.getBoolean("junit.jupiter.execution.parallel.enabled")

326

.orElse(false);

327

328

int timeout = config.get("test.timeout", Integer::parseInt)

329

.orElse(30);

330

331

String environment = config.get("test.environment")

332

.orElse("development");

333

334

// Use configuration in execution logic

335

if (parallelExecution) {

336

executeInParallel(request);

337

} else {

338

executeSequentially(request);

339

}

340

}

341

```