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

engine-implementation.mddocs/

0

# Engine Implementation

1

2

Core TestEngine interface and related classes that provide the foundation for implementing custom test engines in the JUnit Platform.

3

4

## Capabilities

5

6

### TestEngine Interface

7

8

The main interface that all custom test engines must implement to integrate with the JUnit Platform launcher.

9

10

```java { .api }

11

/**

12

* Main interface for test engines. Provides engine identification, test discovery, and execution capabilities.

13

*/

14

public interface TestEngine {

15

/**

16

* Get the unique identifier for this test engine.

17

* @return the engine ID (must be unique across all engines)

18

*/

19

String getId();

20

21

/**

22

* Discover tests from the provided discovery request.

23

* @param discoveryRequest the discovery request containing selectors and filters

24

* @param uniqueId the unique ID for the engine's root descriptor

25

* @return the root test descriptor containing discovered tests

26

*/

27

TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId);

28

29

/**

30

* Execute the tests described by the execution request.

31

* @param request the execution request containing test descriptors and configuration

32

*/

33

void execute(ExecutionRequest request);

34

35

/**

36

* Get the Maven group ID of this engine.

37

* @return optional group ID for engine metadata

38

*/

39

default Optional<String> getGroupId() {

40

return Optional.empty();

41

}

42

43

/**

44

* Get the Maven artifact ID of this engine.

45

* Default implementation tries to get module name first, then implementation title from package attributes.

46

* @return optional artifact ID for engine metadata

47

*/

48

default Optional<String> getArtifactId() {

49

Optional<String> moduleName = ModuleUtils.getModuleName(getClass());

50

if (moduleName.isPresent()) {

51

return moduleName;

52

}

53

return PackageUtils.getAttribute(getClass(), Package::getImplementationTitle);

54

}

55

56

/**

57

* Get the version of this engine.

58

* Default implementation tries "Engine-Version-" + getId() attribute first,

59

* then module or implementation version, defaulting to "DEVELOPMENT".

60

* @return optional version for engine metadata

61

*/

62

default Optional<String> getVersion() {

63

Optional<String> standalone = PackageUtils.getAttribute(getClass(), "Engine-Version-" + getId());

64

if (standalone.isPresent()) {

65

return standalone;

66

}

67

return Optional.of(PackageUtils.getModuleOrImplementationVersion(getClass()).orElse("DEVELOPMENT"));

68

}

69

}

70

```

71

72

**Usage Example:**

73

74

```java

75

import org.junit.platform.engine.*;

76

import org.junit.platform.engine.discovery.*;

77

import org.junit.platform.engine.support.descriptor.EngineDescriptor;

78

import org.junit.platform.commons.util.ModuleUtils;

79

import org.junit.platform.commons.util.PackageUtils;

80

81

public class CustomTestEngine implements TestEngine {

82

public static final String ENGINE_ID = "custom-engine";

83

84

@Override

85

public String getId() {

86

return ENGINE_ID;

87

}

88

89

@Override

90

public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) {

91

EngineDescriptor engineDescriptor = new EngineDescriptor(uniqueId, "Custom Engine");

92

93

// Process class selectors

94

discoveryRequest.getSelectorsByType(ClassSelector.class)

95

.forEach(selector -> {

96

Class<?> testClass = selector.getJavaClass();

97

if (isTestClass(testClass)) {

98

TestDescriptor classDescriptor = createClassDescriptor(testClass, engineDescriptor);

99

engineDescriptor.addChild(classDescriptor);

100

101

// Discover test methods within the class

102

discoverTestMethods(testClass, classDescriptor);

103

}

104

});

105

106

return engineDescriptor;

107

}

108

109

@Override

110

public void execute(ExecutionRequest request) {

111

TestDescriptor rootDescriptor = request.getRootTestDescriptor();

112

EngineExecutionListener listener = request.getEngineExecutionListener();

113

ConfigurationParameters config = request.getConfigurationParameters();

114

115

executeDescriptor(rootDescriptor, listener, config);

116

}

117

118

private void executeDescriptor(TestDescriptor descriptor,

119

EngineExecutionListener listener,

120

ConfigurationParameters config) {

121

listener.executionStarted(descriptor);

122

123

try {

124

if (descriptor.getType() == TestDescriptor.Type.TEST) {

125

// Execute actual test logic

126

executeTest(descriptor, config);

127

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

128

} else {

129

// Execute children for containers

130

descriptor.getChildren().forEach(child ->

131

executeDescriptor(child, listener, config));

132

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

133

}

134

} catch (Exception e) {

135

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

136

}

137

}

138

}

139

```

140

141

### TestExecutionResult

142

143

Encapsulates the result of executing a test or container, including success, failure, or abortion status.

144

145

```java { .api }

146

/**

147

* Result of executing a test or container.

148

*/

149

public final class TestExecutionResult {

150

/**

151

* Create a successful execution result.

152

* @return successful result

153

*/

154

public static TestExecutionResult successful();

155

156

/**

157

* Create a failed execution result.

158

* @param throwable the cause of failure

159

* @return failed result with throwable

160

*/

161

public static TestExecutionResult failed(Throwable throwable);

162

163

/**

164

* Create an aborted execution result.

165

* @param throwable the cause of abortion

166

* @return aborted result with throwable

167

*/

168

public static TestExecutionResult aborted(Throwable throwable);

169

170

/**

171

* Get the execution status.

172

* @return the status (SUCCESSFUL, FAILED, or ABORTED)

173

*/

174

public Status getStatus();

175

176

/**

177

* Get the throwable associated with this result.

178

* @return optional throwable for failed/aborted results

179

*/

180

public Optional<Throwable> getThrowable();

181

182

/**

183

* Execution status enumeration.

184

*/

185

public enum Status { SUCCESSFUL, ABORTED, FAILED }

186

}

187

```

188

189

### UniqueId

190

191

Encapsulates the creation, parsing, and display of unique identifiers for test descriptors within the engine hierarchy.

192

193

```java { .api }

194

/**

195

* Unique identifier for test descriptors, supporting hierarchical structure.

196

*/

197

public final class UniqueId implements Serializable, Cloneable {

198

/**

199

* Parse a unique ID from string representation.

200

* @param uniqueId string representation of unique ID

201

* @return parsed UniqueId

202

*/

203

public static UniqueId parse(String uniqueId);

204

205

/**

206

* Create a root unique ID for an engine.

207

* @param engineId the engine identifier

208

* @return root UniqueId for the engine

209

*/

210

public static UniqueId forEngine(String engineId);

211

212

/**

213

* Create a root unique ID with custom type and value.

214

* @param type the segment type

215

* @param value the segment value

216

* @return root UniqueId

217

*/

218

public static UniqueId root(String type, String value);

219

220

/**

221

* Append a new segment to this unique ID.

222

* @param type the segment type

223

* @param value the segment value

224

* @return new UniqueId with appended segment

225

*/

226

public UniqueId append(String type, String value);

227

228

/**

229

* Get all segments of this unique ID.

230

* @return immutable list of segments

231

*/

232

public List<Segment> getSegments();

233

234

/**

235

* Get the engine ID if this is an engine-level unique ID.

236

* @return optional engine ID

237

*/

238

public Optional<String> getEngineId();

239

240

/**

241

* Individual segment of a unique ID.

242

*/

243

public static final class Segment {

244

public String getType();

245

public String getValue();

246

}

247

}

248

```

249

250

**Usage Example:**

251

252

```java

253

// Create engine root ID

254

UniqueId engineId = UniqueId.forEngine("my-engine");

255

256

// Build hierarchical IDs

257

UniqueId classId = engineId.append("class", "com.example.TestClass");

258

UniqueId methodId = classId.append("method", "testMethod");

259

260

// Parse from string

261

UniqueId parsed = UniqueId.parse("[engine:my-engine]/[class:com.example.TestClass]/[method:testMethod]");

262

```

263

264

### TestTag

265

266

Immutable value object representing tags for categorizing and filtering tests.

267

268

```java { .api }

269

/**

270

* Immutable value object for test tags.

271

*/

272

public final class TestTag implements Serializable {

273

/**

274

* Validate tag name syntax.

275

* @param name the tag name to validate

276

* @return true if valid, false otherwise

277

*/

278

public static boolean isValid(String name);

279

280

/**

281

* Create a test tag.

282

* @param name the tag name (must be valid)

283

* @return TestTag instance

284

*/

285

public static TestTag create(String name);

286

287

/**

288

* Get the tag name.

289

* @return the tag name

290

*/

291

public String getName();

292

293

/**

294

* Set of characters not allowed in tag names.

295

*/

296

public static final Set<Character> RESERVED_CHARACTERS;

297

}

298

```

299

300

### TestSource Interface

301

302

Marker interface for representing the source location of tests (classes, methods, files, etc.).

303

304

```java { .api }

305

/**

306

* Marker interface for test source locations.

307

*/

308

public interface TestSource extends Serializable {

309

// Marker interface - implementations provide specific source types

310

}

311

```

312

313

Common TestSource implementations are provided in the `org.junit.platform.engine.support.descriptor` package for classes, methods, files, directories, URIs, and other source types.