refactoring scenario-tests #126

Merged
hsh-michaelhoennig merged 7 commits from feature/refactoring-scenario-tests into master 2024-11-29 14:03:35 +01:00
5 changed files with 61 additions and 40 deletions
Showing only changes of commit 0ae0131ef7 - Show all commits

View File

@ -444,7 +444,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test @Test
@Order(4301) @Order(4301)
@Requires("Membership: M-3101000 - Test AG") @Requires("Membership: M-3101000 - Test AG")
@Produces("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") @Produces("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
void shouldSubscribeCoopAssets() { void shouldSubscribeCoopAssets() {
new CreateCoopAssetsDepositTransaction(scenarioTest) new CreateCoopAssetsDepositTransaction(scenarioTest)
.given("memberNumber", "M-3101000") .given("memberNumber", "M-3101000")
@ -468,8 +468,8 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test @Test
@Order(4303) @Order(4303)
@Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") @Requires("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
@Produces("Coop-Assets M-3101000 - Test AG - DISBURSAL Transaction") @Produces("Coop-Assets: M-3101000 - Test AG - DISBURSAL Transaction")
void shouldDisburseCoopAssets() { void shouldDisburseCoopAssets() {
new CreateCoopAssetsDisbursalTransaction(scenarioTest) new CreateCoopAssetsDisbursalTransaction(scenarioTest)
.given("memberNumber", "M-3101000") .given("memberNumber", "M-3101000")
@ -482,8 +482,8 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test @Test
@Order(4304) @Order(4304)
@Requires("Coop-Assets M-3101000 - Test AG - DEPOSIT Transaction") @Requires("Coop-Assets: M-3101000 - Test AG - DEPOSIT Transaction")
@Produces(explicitly = "Coop-Assets M-3101000 - Test AG - TRANSFER Transaction", implicitly = "Membership M-4303000 - New AG") @Produces(explicitly = "Coop-Assets: M-3101000 - Test AG - TRANSFER Transaction", implicitly = "Membership: M-4303000 - New AG")
void shouldTransferCoopAssets() { void shouldTransferCoopAssets() {
new CreateCoopAssetsTransferTransaction(scenarioTest) new CreateCoopAssetsTransferTransaction(scenarioTest)
.given("transferringMemberNumber", "M-3101000") .given("transferringMemberNumber", "M-3101000")
@ -497,7 +497,7 @@ class HsOfficeScenarioTests extends ScenarioTest {
@Test @Test
@Order(4305) @Order(4305)
@Requires("Coop-Assets M-3101000 - Test AG - TRANSFER Transaction") @Requires("Coop-Assets: M-3101000 - Test AG - TRANSFER Transaction")
void shouldRevertCoopAssetsTransferIncludingRelatedAssetAdoption() { void shouldRevertCoopAssetsTransferIncludingRelatedAssetAdoption() {
new CreateCoopAssetsRevertTransferTransaction(scenarioTest) new CreateCoopAssetsRevertTransferTransaction(scenarioTest)
.given("transferringMemberNumber", "M-3101000") .given("transferringMemberNumber", "M-3101000")

View File

@ -19,7 +19,7 @@ public class CreateCoopAssetsTransferTransaction extends CreateCoopAssetsTransac
.given("emailAddress", "board-of-directors@new-ag.example.org") .given("emailAddress", "board-of-directors@new-ag.example.org")
); );
requires("Membership: New AG", alias -> new CreateMembership(testSuite) requires("Membership: %{adoptingMemberNumber} - New AG", alias -> new CreateMembership(testSuite)
.given("memberNumber", toPartnerNumber("%{adoptingMemberNumber}")) .given("memberNumber", toPartnerNumber("%{adoptingMemberNumber}"))
.given("partnerName", "New AG") .given("partnerName", "New AG")
.given("validFrom", "2024-11-15") .given("validFrom", "2024-11-15")

View File

@ -1,10 +1,15 @@
package net.hostsharing.hsadminng.test.scenarios; package net.hostsharing.hsadminng.test.scenarios;
import lombok.experimental.UtilityClass;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.HashSet;
import java.util.Set;
import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.Arrays.asList;
@Target(METHOD) @Target(METHOD)
@Retention(RUNTIME) @Retention(RUNTIME)
@ -13,4 +18,29 @@ public @interface Produces {
String explicitly() default ""; // same as value String explicitly() default ""; // same as value
String[] implicitly() default {}; String[] implicitly() default {};
boolean permanent() default true; // false means that the object gets deleted again in the process boolean permanent() default true; // false means that the object gets deleted again in the process
@UtilityClass
final class Aggregator {
public static Set<String> producedAliases(final Produces producesAnnot) {
return allOf(
producesAnnot.value(),
producesAnnot.explicitly(),
producesAnnot.implicitly());
}
private Set<String> allOf(final String value, final String explicitly, final String[] implicitly) {
final var all = new HashSet<String>();
if (!value.isEmpty()) {
all.add(value);
}
if (!explicitly.isEmpty()) {
all.add(explicitly);
}
all.addAll(asList(implicitly));
return all;
}
}
} }

View File

@ -15,24 +15,22 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.test.web.server.LocalServerPort;
import org.testcontainers.shaded.org.apache.commons.lang3.ObjectUtils;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.Stack; import java.util.Stack;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream; import static java.util.Arrays.stream;
import static java.util.Optional.ofNullable; import static java.util.Optional.ofNullable;
import static net.hostsharing.hsadminng.test.scenarios.Produces.Aggregator.producedAliases;
import static net.hostsharing.hsadminng.test.scenarios.TemplateResolver.Resolver.DROP_COMMENTS; import static net.hostsharing.hsadminng.test.scenarios.TemplateResolver.Resolver.DROP_COMMENTS;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -56,7 +54,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
@Override @Override
public String toString() { public String toString() {
return ObjectUtils.toString(uuid); return Objects.toString(uuid);
} }
} }
@ -77,7 +75,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
@SneakyThrows @SneakyThrows
@BeforeEach @BeforeEach
void init(final TestInfo testInfo) { void beforeScenario(final TestInfo testInfo) {
createHostsharingPerson(); createHostsharingPerson();
try { try {
testInfo.getTestMethod().ifPresent(currentTestMethod -> { testInfo.getTestMethod().ifPresent(currentTestMethod -> {
@ -91,7 +89,20 @@ public abstract class ScenarioTest extends ContextBasedTest {
} }
@AfterEach @AfterEach
void cleanup() { // final TestInfo testInfo void afterScenario(final TestInfo testInfo) { // final TestInfo testInfo
testInfo.getTestMethod() .ifPresent(currentTestMethod -> {
// FIXME: extract to method
final var producesAnnot = currentTestMethod.getAnnotation(Produces.class);
if (producesAnnot != null && producesAnnot.permanent()) {
final var testMethodProduces = producedAliases(producesAnnot);
testMethodProduces.forEach(declaredAlias ->
assertThat(knowVariables().containsKey(declaredAlias))
.as("@Producer method " + currentTestMethod.getName() +
" did declare but not produce \"" + declaredAlias + "\"")
.isTrue() );
}
});
properties.clear(); properties.clear();
testReport.close(); testReport.close();
} }
@ -122,10 +133,7 @@ public abstract class ScenarioTest extends ContextBasedTest {
if (testMethodRequires != null) { if (testMethodRequires != null) {
for (Method potentialProducerMethod : getPotentialProducerMethods()) { for (Method potentialProducerMethod : getPotentialProducerMethods()) {
final var producesAnnot = potentialProducerMethod.getAnnotation(Produces.class); final var producesAnnot = potentialProducerMethod.getAnnotation(Produces.class);
final var testMethodProduces = allOf( final var testMethodProduces = producedAliases(producesAnnot);
producesAnnot.value(),
producesAnnot.explicitly(),
producesAnnot.implicitly());
// @formatter:off // @formatter:off
if ( // that method can produce something required if ( // that method can produce something required
testMethodProduces.contains(testMethodRequires) && testMethodProduces.contains(testMethodRequires) &&
@ -141,10 +149,6 @@ public abstract class ScenarioTest extends ContextBasedTest {
// and finally we call the producer method // and finally we call the producer method
invokeProducerMethod(this, potentialProducerMethod); invokeProducerMethod(this, potentialProducerMethod);
assertThat(knowVariables().containsKey(testMethodRequires))
.as("@Producer method " + potentialProducerMethod.getName() + " did declare but not produce \"" + testMethodRequires + "\"")
.isTrue();
} }
// @formatter:on // @formatter:on
} }
@ -191,18 +195,6 @@ public abstract class ScenarioTest extends ContextBasedTest {
} }
} }
private Set<String> allOf(final String value, final String explicitly, final String[] implicitly) {
final var all = new HashSet<String>();
if (!value.isEmpty()) {
all.add(value);
}
if (!explicitly.isEmpty()) {
all.add(explicitly);
}
all.addAll(asList(implicitly));
return all;
}
static boolean containsAlias(final String alias) { static boolean containsAlias(final String alias) {
return aliases.containsKey(alias); return aliases.containsKey(alias);
} }

View File

@ -71,10 +71,8 @@ public abstract class UseCase<T extends UseCase<?>> {
} }
public final void requires(final String alias, final Function<String, UseCase<?>> useCaseFactory) { public final void requires(final String alias, final Function<String, UseCase<?>> useCaseFactory) {
if (!ScenarioTest.containsAlias(alias)) {
requirements.put(alias, useCaseFactory); requirements.put(alias, useCaseFactory);
} }
}
public final HttpResponse doRun() { public final HttpResponse doRun() {
if (introduction != null) { if (introduction != null) {
@ -89,8 +87,9 @@ public abstract class UseCase<T extends UseCase<?>> {
testReport.printLine(""); testReport.printLine("");
testReport.silent(() -> testReport.silent(() ->
requirements.forEach((alias, factory) -> { requirements.forEach((alias, factory) -> {
if (!ScenarioTest.containsAlias(alias)) { final var resolvedAlias = ScenarioTest.resolve(alias, DROP_COMMENTS);
factory.apply(alias).run().keepAs(alias); if (!ScenarioTest.containsAlias(resolvedAlias)) {
factory.apply(resolvedAlias).run().keepAs(resolvedAlias);
} }
}) })
); );