This is an automated email from the ASF dual-hosted git repository.
veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git
The following commit(s) were added to refs/heads/master by this push:
new b6f2dd17f Remove the old matrix test suite framework
b6f2dd17f is described below
commit b6f2dd17f259cfae2aea70e939732f4e2b86dd95
Author: Andreas Veithen-Knowles <[email protected]>
AuthorDate: Sun Mar 29 09:02:56 2026 +0100
Remove the old matrix test suite framework
---
testing/matrix-testsuite/migration.md | 523 ---------------------
.../axiom/testutils/suite/MatrixTestCase.java | 57 ---
.../testutils/suite/MatrixTestSuiteBuilder.java | 60 ---
3 files changed, 640 deletions(-)
diff --git a/testing/matrix-testsuite/migration.md
b/testing/matrix-testsuite/migration.md
deleted file mode 100644
index 709adb107..000000000
--- a/testing/matrix-testsuite/migration.md
+++ /dev/null
@@ -1,523 +0,0 @@
-<!--
- ~ Licensed to the Apache Software Foundation (ASF) under one
- ~ or more contributor license agreements. See the NOTICE file
- ~ distributed with this work for additional information
- ~ regarding copyright ownership. The ASF licenses this file
- ~ to you under the Apache License, Version 2.0 (the
- ~ "License"); you may not use this file except in compliance
- ~ with the License. You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing,
- ~ software distributed under the License is distributed on an
- ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- ~ KIND, either express or implied. See the License for the
- ~ specific language governing permissions and limitations
- ~ under the License.
- -->
-
-# Migration guide: MatrixTestSuiteBuilder → MatrixTestNode
-
-This document describes how to migrate a test suite from the old
-`MatrixTestSuiteBuilder` / `MatrixTestCase` pattern (JUnit 3) to the new
-`MatrixTestNode` pattern (JUnit 5 + Guice).
-
-There are two common shapes:
-
-- **Reusable API test suites** — the test suite is defined in one module and
- consumed by one or more implementation modules. These use `InjectorNode` at
- the root to bind implementation-level objects. See the `saaj-testsuite`
- module for a completed example.
-- **Self-contained test suites** — the test case, suite structure, and consumer
- live in a single class. After migration, these are split into a test case
- class (e.g. `StAXPivotTransformerTestCase`) and a suite class (e.g.
- `StAXPivotTransformerTest`). They typically don't need `InjectorNode`
- at all; fan-out nodes with `MatrixTest` leaves are sufficient. See
- `StAXPivotTransformerTest` / `StAXPivotTransformerTestCase` in
- `components/core-streams` for an example.
-
-The step-by-step guide below focuses on reusable API test suites. For
-self-contained suites, see the [simplified
migration](#simplified-migration-for-self-contained-tests)
-section at the end.
-
-## Prerequisites
-
-The module being migrated must depend on:
-
-```xml
-<dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter</artifactId>
-</dependency>
-<dependency>
- <groupId>com.google.inject</groupId>
- <artifactId>guice</artifactId>
-</dependency>
-```
-
-These are already declared in the root POM's `<dependencyManagement>`.
-
-## Step-by-step migration
-
-### 1. Update the test case base class
-
-The domain-specific base class (e.g. `SAAJTestCase`) currently:
-
-- Extends `MatrixTestCase`
-- Accepts all dimension values and implementation objects via constructor
- parameters
-- Calls `addTestParameter(name, value)` in the constructor
-
-**Change it to:**
-
-- Extend `junit.framework.TestCase` directly
-- Declare dependencies as `@Inject` fields (using `com.google.inject.Inject`)
-- Remove the constructor entirely (or make it no-arg)
-- Remove all `addTestParameter()` calls
-
-**Before:**
-
-```java
-public abstract class SAAJTestCase extends MatrixTestCase {
- protected final SAAJImplementation saajImplementation;
- protected final SOAPSpec spec;
-
- public SAAJTestCase(SAAJImplementation saajImplementation, SOAPSpec spec) {
- this.saajImplementation = saajImplementation;
- this.spec = spec;
- addTestParameter("spec", spec.getName());
- }
-
- protected final MessageFactory newMessageFactory() throws SOAPException {
- return
spec.getAdapter(FactorySelector.class).newMessageFactory(saajImplementation);
- }
-}
-```
-
-**After:**
-
-```java
-public abstract class SAAJTestCase extends TestCase {
- @Inject protected SAAJImplementation saajImplementation;
- @Inject protected SOAPSpec spec;
-
- protected final MessageFactory newMessageFactory() throws SOAPException {
- return
spec.getAdapter(FactorySelector.class).newMessageFactory(saajImplementation);
- }
-}
-```
-
-### 2. Update each test case class
-
-Each test case class currently accepts constructor parameters and forwards them
-to the base class.
-
-**Remove the constructor.** The `runTest()` method stays unchanged. Any imports
-of the implementation class and dimension types that were only used in the
-constructor can be removed.
-
-**Before:**
-
-```java
-public class TestAddChildElementReification extends SAAJTestCase {
- public TestAddChildElementReification(SAAJImplementation
saajImplementation, SOAPSpec spec) {
- super(saajImplementation, spec);
- }
-
- @Override
- protected void runTest() throws Throwable {
- // ... test logic unchanged ...
- }
-}
-```
-
-**After:**
-
-```java
-public class TestAddChildElementReification extends SAAJTestCase {
- @Override
- protected void runTest() throws Throwable {
- // ... test logic unchanged ...
- }
-}
-```
-
-### 3. Replace the suite builder with a suite factory
-
-The old `*TestSuiteBuilder` class extends `MatrixTestSuiteBuilder` and
overrides
-`addTests()` to register test instances for each dimension combination.
-
-**Replace it** with a class that has a static factory method returning a
-`MatrixTestNode`. The factory method:
-
-1. Creates an `InjectorNode` with a Guice module that binds
- implementation-level objects. Pass a single `Module` directly (convenience
- constructor) or an `ImmutableList<Module>` when you need multiple modules.
- The child node is a single `MatrixTestNode`; use `ParentNode` when you need
- to group multiple children.
-2. Creates fan-out nodes for each dimension.
-3. Adds `MatrixTest` leaf nodes as children of the fan-out nodes at
construction
- time.
-
-Use `FanOutNode` for each dimension, supplying:
-- an `ImmutableList<T>` of values (e.g. from `Multiton.getInstances()`),
-- a `Binding<T>` lambda that configures the Guice binding for each value,
-- a `ParameterBinding<? super T>` lambda that registers test parameters for
- display and filtering,
-- a single `MatrixTestNode` child; use `ParentNode` to group multiple children.
-
-**Before:**
-
-```java
-public class SAAJTestSuiteBuilder extends MatrixTestSuiteBuilder {
- private final SAAJImplementation saajImplementation;
-
- public SAAJTestSuiteBuilder(SAAJMetaFactory metaFactory) {
- saajImplementation = new SAAJImplementation(metaFactory);
- }
-
- @Override
- protected void addTests() {
- addTests(SOAPSpec.SOAP11);
- addTests(SOAPSpec.SOAP12);
- }
-
- private void addTests(SOAPSpec spec) {
- addTest(new TestAddChildElementReification(saajImplementation, spec));
- addTest(new TestGetOwnerDocument(saajImplementation, spec));
- // ...
- }
-}
-```
-
-**After:**
-
-```java
-public class SAAJTestSuite {
- public static MatrixTestNode create(SAAJMetaFactory metaFactory) {
- return new InjectorNode(
- binder ->
- binder.bind(SAAJImplementation.class)
- .toInstance(new
SAAJImplementation(metaFactory)),
- new FanOutNode<>(
- Multiton.getInstances(SOAPSpec.class),
- Binding.singleton(Key.get(SOAPSpec.class)),
- (params, value) -> params.addTestParameter("spec",
value.getName()),
- new ParentNode(
- new
MatrixTest(TestAddChildElementReification.class),
- new MatrixTest(TestGetOwnerDocument.class))));
- }
-}
-```
-
-Key differences:
-
-- Test classes are registered **once** as `MatrixTest` instances, passed as
- children to the appropriate fan-out node at construction time, rather than
once
- per dimension combination.
-- Dimension values are listed via `Multiton.getInstances()` (or an explicit
list)
- in the fan-out node, not iterated manually.
-- No constructor arguments are passed to test classes.
-
-### 4. Replace the consumer test class
-
-The old consumer class uses JUnit 3's `static suite()` method.
-
-**Replace it** with a JUnit 5 class that has a `@TestFactory` method returning
-`Stream<DynamicNode>`. By convention, the method should be called `tests`.
-
-**Before:**
-
-```java
-public class SAAJRITest extends TestCase {
- public static TestSuite suite() throws Exception {
- return new SAAJTestSuiteBuilder(new SAAJMetaFactoryImpl()).build();
- }
-}
-```
-
-**After:**
-
-```java
-public class SAAJRITest {
- @TestFactory
- public Stream<DynamicNode> tests() {
- return SAAJTestSuite.create(new SAAJMetaFactoryImpl())
- .toDynamicNodes();
- }
-}
-```
-
-### 5. Migrate exclusions
-
-If the old consumer called `exclude()` on the builder, convert those calls to
-`MatrixTestFilters.builder().add(...)` entries.
-
-**Before:**
-
-```java
-SAAJTestSuiteBuilder builder = new SAAJTestSuiteBuilder(factory);
-builder.exclude(TestGetOwnerDocument.class, "(spec=soap12)");
-builder.exclude(TestSomething.class);
-builder.exclude("(parser=StAX)");
-return builder.build();
-```
-
-**After:**
-
-```java
-MatrixTestFilters excludes = MatrixTestFilters.builder()
- .add(TestGetOwnerDocument.class, "(spec=soap12)")
- .add(TestSomething.class)
- .add("(parser=StAX)")
- .build();
-return MyTestSuite.create(factory).toDynamicNodes(excludes);
-```
-
-The filter syntax and semantics are identical.
-
-### 6. Update dependencies in pom.xml
-
-Add `junit-jupiter` and `guice` to the module's `<dependencies>`. If the module
-uses `Multiton.getInstances()`, also add a dependency on the `multiton` module.
-
-Remove any dependency on `junit:junit` if no code in the module still uses
JUnit 3
-or 4 APIs directly. (Note: test case classes still extend
-`junit.framework.TestCase`, which comes from `junit:junit` transitively through
-`matrix-testsuite`.)
-
-### 7. Delete the old builder class
-
-The old `*TestSuiteBuilder` class can be deleted once the new `*TestSuite`
factory
-is in place and all consumers have been updated.
-
-## Simplified migration for self-contained tests
-
-When the test case, suite builder, and consumer are all in a single class (i.e.
-the class extends `MatrixTestCase` and has a `static suite()` method), the
-migration is simpler because there is no separate base class or suite factory.
-However, the result must be **two** classes:
-
-- A **test case class** (e.g. `StAXPivotTransformerTestCase`) that extends
- `TestCase` and contains the test logic. Name it with a `*TestCase` suffix
- (not `*Test`) so that Maven Surefire does not try to run it directly as a
- JUnit 3/4 test.
-- A **suite class** (e.g. `StAXPivotTransformerTest`) with a `@TestFactory`
- method that builds the fan-out tree and returns `Stream<DynamicNode>`. Name
- it with a `*Test` suffix so that Maven Surefire discovers and runs it.
-
-Steps:
-
-1. Rename the class to a `*TestCase` suffix. Change it to extend `TestCase`
- directly and declare dimension values as `@Inject` fields instead of
- constructor parameters.
-2. Remove the constructor and all `addTestParameter()` calls.
-3. Remove the `static suite()` method.
-4. Create a new suite class with a `*Test` suffix. Add a `@TestFactory`
- **instance** method called `tests` that builds the fan-out tree and calls
- `toDynamicNodes()` on the root node.
- No `InjectorNode` is needed unless you have additional bindings beyond the
- dimension values.
-
-Note: the `@TestFactory` method **must not be static** — JUnit 5 requires it
-to be an instance method.
-
-**Before:**
-
-```java
-public class StAXPivotTransformerTest extends MatrixTestCase {
- private final XSLTImplementation xsltImplementation;
- private final XMLSample sample;
-
- public StAXPivotTransformerTest(
- XSLTImplementation xsltImplementation, XMLSample sample) {
- this.xsltImplementation = xsltImplementation;
- this.sample = sample;
- addTestParameter("xslt", xsltImplementation.getName());
- addTestParameter("sample", sample.getName());
- }
-
- @Override
- protected void runTest() throws Throwable {
- // ... test logic ...
- }
-
- public static TestSuite suite() {
- return new MatrixTestSuiteBuilder() {
- @Override
- protected void addTests() {
- for (XSLTImplementation xsltImplementation :
- getInstances(XSLTImplementation.class)) {
- for (XMLSample sample : getInstances(XMLSample.class)) {
- addTest(new
StAXPivotTransformerTest(xsltImplementation, sample));
- }
- }
- }
- }.build();
- }
-}
-```
-
-**After** (`StAXPivotTransformerTestCase.java` — test logic):
-
-```java
-public class StAXPivotTransformerTestCase extends TestCase {
- @Inject private XSLTImplementation xsltImplementation;
- @Inject private XMLSample sample;
-
- @Override
- protected void runTest() throws Throwable {
- // ... test logic unchanged ...
- }
-}
-```
-
-**After** (`StAXPivotTransformerTest.java` — JUnit 5 suite):
-
-```java
-public class StAXPivotTransformerTest {
- @TestFactory
- public Stream<DynamicNode> tests() {
- return new FanOutNode<>(
- Multiton.getInstances(XSLTImplementation.class),
- Binding.singleton(Key.get(XSLTImplementation.class)),
- (params, value) -> params.addTestParameter("xslt",
value.getName()),
- new FanOutNode<>(
- Multiton.getInstances(XMLSample.class),
- Binding.singleton(Key.get(XMLSample.class)),
- (params, value) ->
- params.addTestParameter("sample",
value.getName()),
- new
MatrixTest(StAXPivotTransformerTestCase.class)))
- .toDynamicNodes();
- }
-}
-```
-
-Note that filtering logic (e.g. skipping values based on a condition like
-`xsltImplementation.supportsStAXSource()`) that was previously expressed as
-`if` guards in the `addTests()` loop should be handled by filtering the
-`ImmutableList` of values passed to the `FanOutNode` (e.g.
-`.stream().filter(...).collect(ImmutableList.toImmutableList())`).
-
-## Tips and lessons learned
-
-### Injecting primitive types
-
-Guice can inject primitive types such as `boolean` directly — there is no need
-to use the boxed wrapper type. On the binding side, use the boxed type
-(`Boolean.class`) since `boolean.class` is not a valid Guice key:
-
-```java
-Binding.singleton(Key.get(Boolean.class, Names.named("deep")))
-```
-
-Or, if you need to write the binding manually:
-
-```java
-binder.bind(Boolean.class)
- .annotatedWith(Names.named("deep"))
- .toInstance(value);
-```
-
-On the injection side, a primitive field works fine:
-
-```java
-@Inject @Named("deep") private boolean deep;
-```
-
-### Use `@Named` to disambiguate primitive bindings
-
-When a test case (or its fan-out tree) involves more than one dimension of the
-same primitive type, Guice cannot distinguish the bindings by type alone. Use
-`@Named` (from `com.google.inject.name.Named`) on both the `@Inject` field and
-the corresponding `FanOutNode` binding (via `Names.named(...)`) to
disambiguate.
-This also applies when a single primitive dimension exists — the annotation
-makes the binding self-documenting and avoids conflicts if another dimension of
-the same type is added later.
-
-See the `dom-testsuite` module for an example with two boolean dimensions
-(`"deep"` and `"newChildHasSiblings"`).
-
-### Constructor injection as an alternative to field injection
-
-The examples above use `@Inject` on fields, but in some cases it is necessary
-or more convenient to use **constructor injection** instead. This is the case
-when the base test case class stores dependencies in `final` fields set by
-the constructor. Converting those fields to non-final `@Inject` fields would
-require changing how the class and its subclasses are structured, which may
-not be desirable.
-
-With constructor injection, the existing constructor chain is preserved:
subclass
-constructors receive dependencies as parameters and pass them up via
`super(…)`.
-To make this work with Guice, simply add `@Inject` to the subclass constructor
-(there is no need to annotate the base class constructor). Guice will then
inject
-the parameters when creating the test instance.
-
-**Base test case class** (no `@Inject` needed here — constructor stays as-is):
-
-```java
-public abstract class WritableBlobTestCase extends TestCase {
- private final WritableBlobFactory<?> factory;
- private final State initialState;
-
- public WritableBlobTestCase(WritableBlobFactory<?> factory, State
initialState) {
- this.factory = factory;
- this.initialState = initialState;
- }
- // ...
-}
-```
-
-**Simple subclass** — add `@Inject` to the constructor:
-
-```java
-public class TestAvailable extends WritableBlobTestCase {
- @Inject
- public TestAvailable(WritableBlobFactory<?> factory) {
- super(factory, State.NEW);
- }
- // ...
-}
-```
-
-**Subclass with `@Named` parameter** — use `@Named` on the constructor
-parameter just as you would on a field:
-
-```java
-public class TestMarkReset extends SizeSensitiveWritableBlobTestCase {
- @Inject
- public TestMarkReset(WritableBlobFactory<?> factory, @Named("size") int
size) {
- super(factory, State.NEW, size);
- }
- // ...
-}
-```
-
-See the `blob` module (`WritableBlobTestCase` hierarchy) for a complete
-example.
-
-## Checklist
-
-### Reusable API test suites
-
-- [ ] Base test case class: extends `TestCase`, uses `@Inject` fields, no
- constructor
-- [ ] All test case classes: constructor removed, `runTest()` unchanged
-- [ ] Suite factory class: creates `InjectorNode` with Guice module, builds
- immutable fan-out tree with `MatrixTest` leaves supplied at construction
- time; uses `ParentNode` to group multiple children
-- [ ] Consumer test class: uses `@TestFactory` returning `Stream<DynamicNode>`
-- [ ] Exclusions: converted to `MatrixTestFilters.builder()` calls
-- [ ] `pom.xml`: `junit-jupiter`, `guice`, and (if needed) `multiton` added
-- [ ] Old builder class deleted
-- [ ] Tests pass: `mvn clean test -pl <module> -am`
-
-### Self-contained test suites
-
-- [ ] Test case class: renamed to `*TestCase` suffix, extends `TestCase`, uses
- `@Inject` fields, no constructor, `static suite()` removed
-- [ ] Suite class: named with `*Test` suffix, has `@TestFactory` instance
- method `tests()` building fan-out tree and calling `toDynamicNodes()`
-- [ ] `pom.xml`: `junit-jupiter`, `guice`, and (if needed) `multiton` added
-- [ ] Tests pass: `mvn clean test -pl <module> -am`
diff --git
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestCase.java
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestCase.java
deleted file mode 100644
index 6ca34cb00..000000000
---
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestCase.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.axiom.testutils.suite;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import junit.framework.TestCase;
-
-/** A test case that can be executed multiple times with different parameters.
*/
-public abstract class MatrixTestCase extends TestCase implements
TestParameterTarget {
- private final Map<String, String> parameters = new HashMap<>();
-
- public MatrixTestCase() {
- setName(getClass().getName());
- }
-
- @Override
- public final void addTestParameter(String name, String value) {
- setName(getName() + " [" + name + "=" + value + "]");
- parameters.put(name, value);
- }
-
- @Override
- public final void addTestParameter(String name, boolean value) {
- addTestParameter(name, String.valueOf(value));
- }
-
- @Override
- public final void addTestParameter(String name, int value) {
- addTestParameter(name, String.valueOf(value));
- }
-
- public final Map<String, String> getTestParameters() {
- return parameters;
- }
-
- // Force subclasses to override the runTest method:
- @Override
- protected abstract void runTest() throws Throwable;
-}
diff --git
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestSuiteBuilder.java
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestSuiteBuilder.java
deleted file mode 100644
index 4ca84af81..000000000
---
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/MatrixTestSuiteBuilder.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.axiom.testutils.suite;
-
-import junit.framework.TestSuite;
-
-/**
- * Builds a matrix test suite. This is an abstract class. Subclasses are
expected to implement the
- * {@link #addTests()} method to generate a set of {@link MatrixTestCase}
instances. For each type
- * of {@link MatrixTestCase}, the {@link #addTests()} method should add
instances for all allowed
- * parameter values. The resulting set can then be filtered using LDAP filter
expressions.
- */
-public abstract class MatrixTestSuiteBuilder {
- private final MatrixTestFilters.Builder excludesBuilder =
MatrixTestFilters.builder();
- private MatrixTestFilters excludes;
- private TestSuite suite;
-
- public final void exclude(Class<? extends MatrixTestCase> testClass,
String filter) {
- excludesBuilder.add(testClass, filter);
- }
-
- public final void exclude(Class<? extends MatrixTestCase> testClass) {
- excludesBuilder.add(testClass);
- }
-
- public final void exclude(String filter) {
- excludesBuilder.add(filter);
- }
-
- protected abstract void addTests();
-
- public final TestSuite build() {
- excludes = excludesBuilder.build();
- suite = new TestSuite();
- addTests();
- return suite;
- }
-
- protected final void addTest(MatrixTestCase test) {
- if (!excludes.test(test.getClass(), test.getTestParameters())) {
- suite.addTest(test);
- }
- }
-}