or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-chain-customization.mddev-mode-testing.mdindex.mdlogging-test-resources.mdprod-mode-testing.mdresults-utilities.mdunit-testing.md

build-chain-customization.mddocs/

0

# Build Chain Customization

1

2

Support for customizing Quarkus build chains during testing, including build steps, producers, and consumers for comprehensive build testing.

3

4

## ProdModeTestBuildStep

5

6

Abstract base class for creating custom build steps in production mode tests.

7

8

### Core API

9

10

```java { .api }

11

public abstract class ProdModeTestBuildStep implements BuildStep {

12

13

public ProdModeTestBuildStep(Map<String, Object> testContext);

14

public Map<String, Object> getTestContext();

15

}

16

```

17

18

## ProdModeTestBuildChainBuilderConsumer

19

20

Consumer for customizing build chains in production mode tests.

21

22

### Core API

23

24

```java { .api }

25

public class ProdModeTestBuildChainBuilderConsumer implements Consumer<BuildChainBuilder> {

26

27

public ProdModeTestBuildChainBuilderConsumer(String buildStepClassName,

28

List<String> producesClassNames, List<String> consumesClassNames,

29

Map<String, Object> testContext);

30

31

public void accept(BuildChainBuilder builder);

32

}

33

```

34

35

## ProdModeTestBuildChainCustomizerProducer

36

37

Function for producing build chain customizers.

38

39

### Core API

40

41

```java { .api }

42

public class ProdModeTestBuildChainCustomizerProducer implements Function<Map<String, Object>, List<Consumer<BuildChainBuilder>>> {

43

44

public List<Consumer<BuildChainBuilder>> apply(Map<String, Object> testContext);

45

}

46

```

47

48

## Usage Examples

49

50

### Creating Custom Build Steps

51

52

```java

53

import io.quarkus.test.ProdModeTestBuildStep;

54

import io.quarkus.deployment.builditem.BuildItem;

55

import io.quarkus.deployment.BuildContext;

56

57

public class MyCustomBuildStep extends ProdModeTestBuildStep {

58

59

public MyCustomBuildStep(Map<String, Object> testContext) {

60

super(testContext);

61

}

62

63

@Override

64

public void execute(BuildContext context) {

65

// Access test context

66

Map<String, Object> testContext = getTestContext();

67

String customValue = (String) testContext.get("customKey");

68

69

// Perform custom build logic

70

MyBuildItem buildItem = new MyBuildItem(customValue);

71

context.produce(buildItem);

72

}

73

}

74

75

// Custom build item

76

public class MyBuildItem extends BuildItem {

77

private final String value;

78

79

public MyBuildItem(String value) {

80

this.value = value;

81

}

82

83

public String getValue() {

84

return value;

85

}

86

}

87

```

88

89

### Using Build Steps in Tests

90

91

```java

92

import io.quarkus.test.QuarkusProdModeTest;

93

import org.junit.jupiter.api.extension.RegisterExtension;

94

import org.junit.jupiter.api.Test;

95

96

public class BuildChainCustomizationTest {

97

98

@RegisterExtension

99

static final QuarkusProdModeTest config = new QuarkusProdModeTest()

100

.withApplicationRoot(jar -> jar.addClasses(MyService.class))

101

.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(

102

MyCustomBuildStep.class,

103

List.of(MyBuildItem.class), // Produces

104

List.of(ApplicationArchivesBuildItem.class) // Consumes

105

));

106

107

@Test

108

public void testCustomBuildStep() {

109

// Test that custom build step was executed

110

// Build artifacts will include MyBuildItem

111

}

112

}

113

```

114

115

### Complex Build Step with Dependencies

116

117

```java

118

public class ComplexBuildStep extends ProdModeTestBuildStep {

119

120

public ComplexBuildStep(Map<String, Object> testContext) {

121

super(testContext);

122

}

123

124

@Override

125

public void execute(BuildContext context) {

126

// Consume required build items

127

ApplicationArchivesBuildItem archives = context.consume(ApplicationArchivesBuildItem.class);

128

FeatureBuildItem features = context.consume(FeatureBuildItem.class);

129

130

// Access test context for configuration

131

Map<String, Object> testContext = getTestContext();

132

boolean enableFeature = (Boolean) testContext.getOrDefault("enableFeature", false);

133

134

if (enableFeature) {

135

// Produce custom build items

136

context.produce(new CustomFeatureBuildItem());

137

context.produce(new AdditionalBeanBuildItem(MyCustomBean.class));

138

}

139

140

// Modify existing build items if needed

141

for (ApplicationArchive archive : archives.getAllApplicationArchives()) {

142

// Process archive

143

}

144

}

145

}

146

```

147

148

### Multi-Step Build Chain

149

150

```java

151

public class FirstBuildStep extends ProdModeTestBuildStep {

152

public FirstBuildStep(Map<String, Object> testContext) {

153

super(testContext);

154

}

155

156

@Override

157

public void execute(BuildContext context) {

158

context.produce(new IntermediateBuildItem("processed-data"));

159

}

160

}

161

162

public class SecondBuildStep extends ProdModeTestBuildStep {

163

public SecondBuildStep(Map<String, Object> testContext) {

164

super(testContext);

165

}

166

167

@Override

168

public void execute(BuildContext context) {

169

IntermediateBuildItem intermediate = context.consume(IntermediateBuildItem.class);

170

String processedData = intermediate.getData();

171

172

// Final processing

173

context.produce(new FinalBuildItem(processedData + "-final"));

174

}

175

}

176

177

// Test with multiple build steps

178

@RegisterExtension

179

static final QuarkusProdModeTest config = new QuarkusProdModeTest()

180

.withApplicationRoot(jar -> jar.addClasses(MyService.class))

181

.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(

182

FirstBuildStep.class,

183

List.of(IntermediateBuildItem.class),

184

List.of()

185

))

186

.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(

187

SecondBuildStep.class,

188

List.of(FinalBuildItem.class),

189

List.of(IntermediateBuildItem.class)

190

));

191

```

192

193

### Conditional Build Steps

194

195

```java

196

public class ConditionalBuildStep extends ProdModeTestBuildStep {

197

198

public ConditionalBuildStep(Map<String, Object> testContext) {

199

super(testContext);

200

}

201

202

@Override

203

public void execute(BuildContext context) {

204

Map<String, Object> testContext = getTestContext();

205

206

// Check conditions from test context

207

String environment = (String) testContext.get("environment");

208

boolean debugMode = (Boolean) testContext.getOrDefault("debug", false);

209

210

if ("production".equals(environment)) {

211

context.produce(new ProductionOptimizationBuildItem());

212

} else if ("development".equals(environment)) {

213

context.produce(new DevelopmentToolsBuildItem());

214

}

215

216

if (debugMode) {

217

context.produce(new DebugInfoBuildItem());

218

}

219

}

220

}

221

222

// Usage in test

223

@RegisterExtension

224

static final QuarkusProdModeTest config = new QuarkusProdModeTest()

225

.withApplicationRoot(jar -> jar.addClasses(MyService.class))

226

.addBuildChainCustomizerEntries(new QuarkusProdModeTest.BuildChainCustomizerEntry(

227

ConditionalBuildStep.class,

228

List.of(ProductionOptimizationBuildItem.class, DevelopmentToolsBuildItem.class, DebugInfoBuildItem.class),

229

List.of()

230

));

231

232

@Test

233

public void testProductionMode() {

234

// Test context will be passed to build step

235

// Build step will produce ProductionOptimizationBuildItem

236

}

237

```

238

239

### Build Step with Resource Processing

240

241

```java

242

public class ResourceProcessingBuildStep extends ProdModeTestBuildStep {

243

244

public ResourceProcessingBuildStep(Map<String, Object> testContext) {

245

super(testContext);

246

}

247

248

@Override

249

public void execute(BuildContext context) {

250

ApplicationArchivesBuildItem archives = context.consume(ApplicationArchivesBuildItem.class);

251

252

for (ApplicationArchive archive : archives.getAllApplicationArchives()) {

253

// Process resources in the archive

254

Path resourcesPath = archive.getArchiveRoot().resolve("META-INF/resources");

255

256

if (Files.exists(resourcesPath)) {

257

try {

258

Files.walk(resourcesPath)

259

.filter(Files::isRegularFile)

260

.forEach(this::processResource);

261

} catch (IOException e) {

262

throw new RuntimeException("Failed to process resources", e);

263

}

264

}

265

}

266

267

// Produce build item indicating resources were processed

268

context.produce(new ProcessedResourcesBuildItem());

269

}

270

271

private void processResource(Path resourcePath) {

272

// Custom resource processing logic

273

Map<String, Object> testContext = getTestContext();

274

String processingMode = (String) testContext.get("resourceProcessingMode");

275

276

// Process based on mode

277

if ("minify".equals(processingMode)) {

278

// Minify resource

279

} else if ("optimize".equals(processingMode)) {

280

// Optimize resource

281

}

282

}

283

}

284

```

285

286

### Testing Build Step Execution

287

288

```java

289

@Test

290

public void testBuildStepExecution() {

291

// Test that custom build steps were executed correctly

292

// This can be verified through:

293

294

// 1. Checking build logs

295

String buildOutput = config.getStartupConsoleOutput();

296

assertTrue(buildOutput.contains("MyCustomBuildStep executed"));

297

298

// 2. Examining build artifacts (if accessible)

299

// 3. Testing runtime behavior that depends on build step output

300

// 4. Using test context to pass verification flags

301

}

302

303

@Test

304

public void testBuildStepWithContext() {

305

// Test context is automatically passed to build steps

306

// You can verify build step behavior by examining the results

307

308

// The build step can access test context and modify behavior accordingly

309

// This allows for parameterized build testing

310

}

311

```

312

313

## Build Item Examples

314

315

```java

316

// Simple build item

317

public class MyBuildItem extends BuildItem {

318

private final String data;

319

320

public MyBuildItem(String data) {

321

this.data = data;

322

}

323

324

public String getData() {

325

return data;

326

}

327

}

328

329

// Complex build item with multiple properties

330

public class ConfigurationBuildItem extends BuildItem {

331

private final Map<String, String> properties;

332

private final List<String> features;

333

334

public ConfigurationBuildItem(Map<String, String> properties, List<String> features) {

335

this.properties = Collections.unmodifiableMap(properties);

336

this.features = Collections.unmodifiableList(features);

337

}

338

339

public Map<String, String> getProperties() {

340

return properties;

341

}

342

343

public List<String> getFeatures() {

344

return features;

345

}

346

}

347

```

348

349

## Best Practices

350

351

### Build Step Design

352

353

1. **Keep build steps focused**: Each build step should have a single responsibility

354

2. **Use test context effectively**: Pass configuration and test data through test context

355

3. **Handle dependencies correctly**: Declare all consumed and produced build items

356

4. **Error handling**: Provide clear error messages for build failures

357

358

### Testing Build Chains

359

360

1. **Verify build item production**: Ensure build steps produce expected build items

361

2. **Test build item consumption**: Verify that build steps properly consume dependencies

362

3. **Integration testing**: Test complete build chains with multiple steps

363

4. **Performance testing**: Measure build step execution time for complex operations