From e2a87fd80b4ffbcf896312f6da58874044add786 Mon Sep 17 00:00:00 2001 From: Jana S Date: Mon, 20 Jan 2025 09:13:16 +0000 Subject: [PATCH 1/2] override runner tag --- .../filter/GherkinTagFiltererAdapter.java | 20 +++++ .../com/pdsl/gherkin/filter/TagFilterer.java | 13 +++ .../JUnit4RecognizerParamsConverter.java | 2 +- .../java/com/pdsl/runners/PdslTestParams.java | 21 ++++- .../pdsl/runners/SharedTestSuiteVisitor.java | 19 +++- .../junit/PdslGherkinJUnit4Runner.java | 1 - .../testcases/PreorderTestCaseFactory.java | 22 +++-- .../PdslSharedInvocationContextProvider.java | 5 +- .../engine/descriptor/PdslTestParameter.java | 87 +++++++++++++++++-- .../java/jupiter/JupiterTagFilteringTest.java | 7 +- .../jupiter/OverrideRunnerTagViaCLITest.java | 86 ++++++++++++++++++ .../java/jupiter/PdslTestParameterTest.java | 49 +++++++++++ .../uat/java/sut/TaggedScenarioRunner.java | 34 ++++---- 13 files changed, 328 insertions(+), 38 deletions(-) create mode 100644 src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java create mode 100644 src/main/java/com/pdsl/gherkin/filter/TagFilterer.java create mode 100644 src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java create mode 100644 src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java diff --git a/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java b/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java new file mode 100644 index 0000000..bb18084 --- /dev/null +++ b/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java @@ -0,0 +1,20 @@ +package com.pdsl.gherkin.filter; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +public class GherkinTagFiltererAdapter implements TagFilterer { + + private final GherkinTagFilterer gherkinTagFilterer; + + public GherkinTagFiltererAdapter(GherkinTagFilterer gherkinTagFilterer) { + this.gherkinTagFilterer = gherkinTagFilterer; + } + + @Override + public boolean tagExpressionMatches(Collection tags, String tagExpression) { + return gherkinTagFilterer.tagExpressionMatchesPickle(new HashSet<>(tags), tagExpression); + } +} \ No newline at end of file diff --git a/src/main/java/com/pdsl/gherkin/filter/TagFilterer.java b/src/main/java/com/pdsl/gherkin/filter/TagFilterer.java new file mode 100644 index 0000000..4f50e47 --- /dev/null +++ b/src/main/java/com/pdsl/gherkin/filter/TagFilterer.java @@ -0,0 +1,13 @@ +package com.pdsl.gherkin.filter; + +import java.util.Collection; +import java.util.Set; + +/** + * Determines if a test case derived from a gherkin file (i.e., a pickle) matches a particular tag + * expression. + */ +public interface TagFilterer { + + boolean tagExpressionMatches(Collection tags, String tagExpression); +} \ No newline at end of file diff --git a/src/main/java/com/pdsl/runners/JUnit4RecognizerParamsConverter.java b/src/main/java/com/pdsl/runners/JUnit4RecognizerParamsConverter.java index 22e671a..64a547d 100644 --- a/src/main/java/com/pdsl/runners/JUnit4RecognizerParamsConverter.java +++ b/src/main/java/com/pdsl/runners/JUnit4RecognizerParamsConverter.java @@ -179,7 +179,7 @@ public InterpreterObj get() { private static PdslTestParams getPdslTestParams( PdslTestDto pdslTestDto, PdslConfiguration pdslConfiguration) { - return new PdslTestParams( + return PdslTestParams.from( getRecognizerLexer(pdslTestDto, pdslConfiguration), getRecognizerParser(pdslTestDto, pdslConfiguration), getInterpreterParams(pdslTestDto, pdslConfiguration), diff --git a/src/main/java/com/pdsl/runners/PdslTestParams.java b/src/main/java/com/pdsl/runners/PdslTestParams.java index cb06384..3f3bad5 100644 --- a/src/main/java/com/pdsl/runners/PdslTestParams.java +++ b/src/main/java/com/pdsl/runners/PdslTestParams.java @@ -1,9 +1,11 @@ package com.pdsl.runners; +import com.pdsl.gherkin.filter.TagFilterer; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Parser; import java.util.List; +import org.junit.jupiter.engine.descriptor.PdslTestParameter; /** * A container for parameters useful for any framework implementing PDSL. @@ -17,15 +19,26 @@ * @param excludesResources the tests to ignore */ public record PdslTestParams ( + Class lexerRecognizerClass, + Class parserRecognizerClass, + InterpreterParam[] interpreters, + List tags, + String[] includesResources, + String[] excludesResources, + TagFilterer tagFilterer, + String tagExpression) { + public static final String DEFAULT_ALL_RULE = "polymorphicDslAllRules"; + public static final String DEFAULT_SYNTAX_RULE = "polymorphicDslSyntaxCheck"; + + public static PdslTestParams from( Class lexerRecognizerClass, Class parserRecognizerClass, InterpreterParam[] interpreters, List tags, String[] includesResources, - String[] excludesResources) { - public static final String DEFAULT_ALL_RULE = "polymorphicDslAllRules"; - public static final String DEFAULT_SYNTAX_RULE = "polymorphicDslSyntaxCheck"; - + String[] excludesResources){ + return new PdslTestParams(lexerRecognizerClass,parserRecognizerClass,interpreters,tags,includesResources,excludesResources,(tags1, tagExpression) -> true,""); + } /** * A visitor used to extend the behavior of the PdslTestParams obje3ct without modifying * the record itself. diff --git a/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java b/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java index b8fe896..9a92396 100644 --- a/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java +++ b/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java @@ -2,15 +2,19 @@ import com.google.common.base.Preconditions; import com.pdsl.executors.InterpreterObj; +import com.pdsl.gherkin.filter.TagFilterer; import com.pdsl.specifications.TestResourceFinder; import com.pdsl.specifications.TestResourceFinderGenerator; import com.pdsl.specifications.TestSpecification; import com.pdsl.specifications.TestSpecificationFactory; +import com.pdsl.testcases.DefaultTaggedTestCase; import com.pdsl.testcases.SharedTestSuite; +import com.pdsl.testcases.TaggedTestCase; import com.pdsl.testcases.TestCase; import com.pdsl.testcases.TestCaseFactory; import com.pdsl.transformers.DefaultPolymorphicDslPhraseFilter; import com.pdsl.transformers.PolymorphicDslPhraseFilter; +import java.util.stream.Collectors; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Parser; @@ -27,6 +31,7 @@ */ public class SharedTestSuiteVisitor implements RecognizerParams.RecognizerParamsOperation { + @Override public SharedTestSuite recognizerParamsOperation(RecognizerParams recognizerParams) { Preconditions.checkNotNull(recognizerParams.applicationName(), "Application name cannot be null"); @@ -39,6 +44,7 @@ public SharedTestSuite recognizerParamsOperation(RecognizerParams recognizerPara recognizerParams.pdslTestParams().forEach(interpreter -> Preconditions.checkNotNull(interpreter, "No null objects can be in the interpreter array!")); // Create a Shared Test Suite List> testCasesPerInterpreters = new ArrayList<>(); + List matchedTestCases = new ArrayList<>(); List interpreterObjs = new ArrayList<>(); for (PdslTestParams params : recognizerParams.pdslTestParams()) { @@ -58,8 +64,19 @@ public SharedTestSuite recognizerParamsOperation(RecognizerParams recognizerPara Collection specifications = getSpecifications(parser, recognizerParams, params, testResources); // Convert the specificaitons into test cases List testCasesForSingleInterpreter = new ArrayList<>(getTestCases(recognizerParams.providers().testCaseFactoryProvider().get(), specifications)); - testCasesPerInterpreters.add(testCasesForSingleInterpreter); + for (TestCase testcase : testCasesForSingleInterpreter) { + if (testcase instanceof TaggedTestCase) { + TaggedTestCase test = (TaggedTestCase) testcase; + //Filter test cases by tags using the injected TagFilterer + boolean anyMatchedTag = params.tagFilterer().tagExpressionMatches(test.getTags(), params.tagExpression()); + if (anyMatchedTag) { + matchedTestCases.add(testcase); + } + } + } + testCasesPerInterpreters.add(matchedTestCases); interpreterObjs.add(parser.interpreterProvider().get()); + } } return SharedTestSuite.of(testCasesPerInterpreters, interpreterObjs); diff --git a/src/main/java/com/pdsl/runners/junit/PdslGherkinJUnit4Runner.java b/src/main/java/com/pdsl/runners/junit/PdslGherkinJUnit4Runner.java index f116eef..15a1d42 100644 --- a/src/main/java/com/pdsl/runners/junit/PdslGherkinJUnit4Runner.java +++ b/src/main/java/com/pdsl/runners/junit/PdslGherkinJUnit4Runner.java @@ -23,7 +23,6 @@ public class PdslGherkinJUnit4Runner extends BlockJUnit4ClassRunner { public PdslGherkinJUnit4Runner(Class testClass) throws InitializationError { super(testClass); - System.out.print("JS23001 : 50"); pdslGherkinApplication = testClass.getAnnotation(PdslGherkinApplication.class); Preconditions.checkNotNull(pdslGherkinApplication, String.format("Class run with %s must be annotated with %s!", getClass().getSimpleName(), PdslConfiguration.class.getSimpleName())); diff --git a/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java b/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java index a4a460d..49a5c62 100644 --- a/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java +++ b/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java @@ -1,5 +1,6 @@ package com.pdsl.testcases; +import com.pdsl.gherkin.filter.TagFilterer; import com.pdsl.specifications.PolymorphicDslTransformationException; import com.pdsl.specifications.TaggedTestSpecification; import com.pdsl.specifications.TestSpecification; @@ -26,16 +27,18 @@ public static final class DefaultProvider implements Provider { public PreorderTestCaseFactory get() { return INSTANCE; } - } + } public static final class DefaultSupplier implements Supplier { @Override public TestCaseFactory get() { return INSTANCE; } + } + @Override public Collection processTestSpecification(Collection testSpecifications) { Collection testCases = new ArrayList<>(testSpecifications.size()); // Will likely need to be resized regardless @@ -73,13 +76,16 @@ private List recursiveWalkAndCreateOnLeaf(TestSpecification testSpecif } return testCases; } else { - TestCase testCase = new DefaultPdslTestCase(testSpecification.getName(), childTestBodyFragments, testSpecification.getOriginalTestResource()); - if (!tags.isEmpty()) { - testCase = new DefaultTaggedTestCase(testCase, tags); - } - List singleTestCase = new ArrayList<>(1); - singleTestCase.add(testCase); - return singleTestCase; + TestCase testCase = new DefaultPdslTestCase(testSpecification.getName(), childTestBodyFragments, testSpecification.getOriginalTestResource()); + if (!tags.isEmpty()) { + testCase = new DefaultTaggedTestCase(testCase, tags); + } + + + + List singleTestCase = new ArrayList<>(1); + singleTestCase.add(testCase); + return singleTestCase; } } diff --git a/src/main/java/org/junit/jupiter/engine/descriptor/PdslSharedInvocationContextProvider.java b/src/main/java/org/junit/jupiter/engine/descriptor/PdslSharedInvocationContextProvider.java index ae93fe7..2412949 100644 --- a/src/main/java/org/junit/jupiter/engine/descriptor/PdslSharedInvocationContextProvider.java +++ b/src/main/java/org/junit/jupiter/engine/descriptor/PdslSharedInvocationContextProvider.java @@ -150,7 +150,10 @@ private static List convert(Collection parame getInterpreterParams(config, p), List.of(p.getTagExpression()), p.getIncludesResources(), - p.getExcludesResources()); + p.getExcludesResources(), + p.getTagFilterer(), + p.getTagExpression() + ); params.add(pdslTestParams); } return params; diff --git a/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java b/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java index 12ecd42..d018039 100644 --- a/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java +++ b/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java @@ -1,6 +1,10 @@ package org.junit.jupiter.engine.descriptor; import com.google.common.base.Preconditions; +import com.pdsl.gherkin.filter.GherkinTagFiltererAdapter; +import com.pdsl.gherkin.filter.GherkinTagsVisitorImpl; +import com.pdsl.gherkin.filter.TagFilterer; +import java.util.logging.Logger; import org.antlr.v4.runtime.Lexer; import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.tree.ParseTreeListener; @@ -23,6 +27,7 @@ */ public class PdslTestParameter { + private static final Logger logger = Logger.getLogger(PdslTestParameter.class.getName()); private final Optional> recognizedByParser; private final Optional> recognizedByLexer; private final Class parser; @@ -35,9 +40,10 @@ public class PdslTestParameter { private final String[] excludesResources; private final String startRule; private final Optional recognizerRule; + private final TagFilterer tagFilterer; private PdslTestParameter(Builder builder) { - Preconditions.checkArgument((builder.listener.isPresent() + Preconditions.checkArgument((builder.listener.isPresent() ^ builder.visitor.isPresent() ^ builder.interpreterParams.isPresent()), "You can only have one of a visitor, listener or list of interpreterDtos!"); this.parser = builder.parser; @@ -52,6 +58,7 @@ private PdslTestParameter(Builder builder) { this.recognizedByLexer = builder.recognizedByLexer; this.recognizedByParser = builder.recognizedByParser; this.interpreterParams = builder.interpreterParams; + this.tagFilterer = builder.tagFilterer; } public Optional> getInterpreters() { return interpreterParams; } @@ -100,7 +107,11 @@ public Optional getRecognizerRule() { return recognizerRule; } - public static class Builder { + public TagFilterer getTagFilterer() { + return tagFilterer; + } + + public static class Builder { private Class parser; private Class lexer; private Optional> recognizedByParser = Optional.empty(); @@ -114,6 +125,15 @@ public static class Builder { private Optional recognizerRule = Optional.empty(); private Optional> interpreterParams = Optional.empty(); + private TagFilterer tagFilterer = new GherkinTagFiltererAdapter(new GherkinTagsVisitorImpl()); + + public Builder withTagFilterer(TagFilterer tagFilterer) { + this.tagFilterer = tagFilterer; + return this; + } + + + public Builder( Class lexer, Class parser, @@ -185,12 +205,20 @@ public Builder withVisitor(Supplier> visitor) { return this; } - public Builder withTagExpression(String str) { - Preconditions.checkNotNull(str, "Tag expression cannot be null!"); - this.tagExpression = str; - return this; + public Builder withTagExpression(String str) { + Preconditions.checkNotNull(str, "Tag expression cannot be null!"); + String commandLineTags = System.getProperty("tags"); + if(commandLineTags != null && !commandLineTags.isEmpty()) { + this.tagExpression = commandLineTags; + logger.info("Overriding runner tags with tags provided in the command line {%s}".formatted(commandLineTags) ); + logger.info("Ignoring provided tag expression {%s}".formatted(str) ); + } else { + this.tagExpression =str; } + return this; + } + public Builder withIncludedResources(String[] resources) { this.includesResources = resources; return this; @@ -218,5 +246,52 @@ public PdslTestParameter build() { return new PdslTestParameter(this); } } + public static PdslTestParameter createTestParameter(Supplier parseTreeListenerSupplier, + Class lexerClass, + Class parserClass, + String[] includedResources) { + String defaultTagExpression = "@comment_tag#2"; + String commandLineTags = System.getProperty("tags"); // Get the value + + String effectiveTagExpression = (commandLineTags != null && !commandLineTags.isEmpty()) + ? commandLineTags + : defaultTagExpression; + + return new PdslTestParameter.Builder(parseTreeListenerSupplier, lexerClass, parserClass) + .withTagExpression(effectiveTagExpression) + .withIncludedResources(includedResources) + .build(); + } + + /** + * I've introduced a static factory method createTestParameter. This method handles the logic for + * overriding the tag expression. This keeps the builder focused on building objects and separates + * the configuration logic. + */ + public static PdslTestParameter createTestParameter( + Supplier parseTreeListenerSupplier, + Class lexerClass, + Class parserClass, + String[] includedResources, String defaultTagExpression) { + // retrieves the value passed from the command line (e.g., -Dtags="@smoke"). + String commandLineTags = System.getProperty("tags"); + // handles the logic for overriding the tag expression + String effectiveTagExpression = (commandLineTags != null && !commandLineTags.isEmpty()) + ? commandLineTags + : defaultTagExpression; + + // // String effectiveTagExpression = defaultTagExpression; // Use default if invalid format + // if (commandLineTags != null && !commandLineTags.isEmpty()) { + // String pattern = "^(?:@\\w+(?: and | or )?)*@\\w+$"; + // if (Pattern.matches(pattern, commandLineTags)) { + // // ... logic to build effectiveTagExpression from commandLineTags (as shown above) ... + // } + // } + + return new PdslTestParameter.Builder(parseTreeListenerSupplier, lexerClass, parserClass) + .withTagExpression(effectiveTagExpression) + .withIncludedResources(includedResources) + .build(); + } } diff --git a/src/test/java/com/pdsl/uat/java/jupiter/JupiterTagFilteringTest.java b/src/test/java/com/pdsl/uat/java/jupiter/JupiterTagFilteringTest.java index 0efd48a..6138305 100644 --- a/src/test/java/com/pdsl/uat/java/jupiter/JupiterTagFilteringTest.java +++ b/src/test/java/com/pdsl/uat/java/jupiter/JupiterTagFilteringTest.java @@ -32,11 +32,16 @@ private static class PdslExtension extends PdslGherkinInvocationContextProvider @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { + String defaultTagExpression = "@comment_tag#2"; + String commandLineTags = System.getProperty("tags"); + String effectiveTagExpression = (commandLineTags != null && !commandLineTags.isEmpty()) + ? commandLineTags + : defaultTagExpression; return getInvocationContext(PdslConfigParameter.createGherkinPdslConfig( List.of( new PdslTestParameter.Builder(parseTreeListenerSupplier, AllGrammarsLexer.class, AllGrammarsParser.class) - .withTagExpression("@comment_tag#2") + .withTagExpression(effectiveTagExpression) .withIncludedResources(new String[] {"tags.feature"}) .build() ) diff --git a/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java b/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java new file mode 100644 index 0000000..1ef1730 --- /dev/null +++ b/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java @@ -0,0 +1,86 @@ +package com.pdsl.uat.java.jupiter; + +import com.pdsl.executors.InterpreterObj; +import com.pdsl.grammars.AllGrammarsLexer; +import com.pdsl.grammars.AllGrammarsParser; +import com.pdsl.grammars.AllGrammarsParserBaseVisitor; +import com.pdsl.grammars.InterpreterAllLexer; +import com.pdsl.grammars.InterpreterAllParser; +import com.pdsl.grammars.MultiInterpreter2Parser; +import com.pdsl.grammars.MultiInterpreter2Parser.ExecuteSentenceContext; +import com.pdsl.grammars.MultiInterpreter2Parser.ParserTwoAllRulesContext; +import com.pdsl.grammars.MultiInterpreter2ParserVisitor; +import com.pdsl.grammars.MultiInterpreterParser.ExecutedByAllParsersContext; +import com.pdsl.grammars.MultiInterpreterParser.FirstInterpreterContext; +import com.pdsl.grammars.MultiInterpreterParser.IgnoreInterpreterContext; +import com.pdsl.grammars.MultiInterpreterParser.ParseSentenceContext; +import com.pdsl.grammars.MultiInterpreterParser.ParsedByAllInterpretersContext; +import com.pdsl.grammars.MultiInterpreterParser.ParserOneAllRulesContext; +import com.pdsl.grammars.MultiInterpreterParser.RecognizeInterpreterContext; +import com.pdsl.grammars.MultiInterpreterParserVisitor; +import com.pdsl.grammars.MultiInterpreterRecognizerLexer; +import com.pdsl.grammars.MultiInterpreterRecognizerParser; +import java.nio.file.Paths; +import java.util.List; +import java.util.logging.Logger; +import java.util.stream.Stream; +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.TestTemplate; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.TestTemplateInvocationContext; +import org.junit.jupiter.engine.descriptor.Interpreter; +import org.junit.jupiter.engine.descriptor.PdslConfigParameter; +import org.junit.jupiter.engine.descriptor.PdslExecutable; +import org.junit.jupiter.engine.descriptor.PdslSharedInvocationContextProvider; +import org.junit.jupiter.engine.descriptor.PdslTestParameter; + +public class OverrideRunnerTagViaCLITest { + + private static int totalRunTests = 0; + + @TestTemplate + @ExtendWith(PdslExtension.class) + public void pdslGherkinTestFrameworkResources(PdslExecutable executable) { + totalRunTests++; + } + + @AfterAll + public static void executeAfterAll(){ + Assertions.assertEquals(1,totalRunTests); + } + + private static class PdslExtension extends PdslSharedInvocationContextProvider { + + public Stream provideTestTemplateInvocationContexts( + ExtensionContext context) { + System.setProperty("tags", "@ex_tag1"); + Stream contexts = getInvocationContext( + PdslConfigParameter.createGherkinPdslConfig( + List.of( + new PdslTestParameter.Builder( + List.of( + new Interpreter(AllGrammarsLexer.class, AllGrammarsParser.class, + new InterpreterObj(new AllGrammarsParserBaseVisitor<>(), + "polymorphicDslAllRules")) + )) + .withIncludedResources(new String[]{"tags.feature"}) + .withRecognizer(AllGrammarsLexer.class, AllGrammarsParser.class) + .withTagExpression("@feature_tag1") + .build() + + )) + .withRecognizerRule("polymorphicDslAllRules") + .withResourceRoot( + Paths.get("src/test/resources/testdata/good/") + .toUri()) + .build()) + .stream(); + System.clearProperty("tags"); + return contexts; + } + } + +} diff --git a/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java b/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java new file mode 100644 index 0000000..fd8c83d --- /dev/null +++ b/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java @@ -0,0 +1,49 @@ +package com.pdsl.uat.java.jupiter; + +import java.util.function.Supplier; +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.Parser; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.engine.descriptor.PdslTestParameter; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + + +public class PdslTestParameterTest { + + @Test + void testCommandLineOverride() { + System.setProperty("tags", "@smoke"); + PdslTestParameter params = PdslTestParameter.createTestParameter( + mock(Supplier.class), + Lexer.class, + Parser.class, + new String[]{"tags.feature"}, "@comment_tag#2"); + + assertEquals("@smoke", params.getTagExpression()); + } + + @Test + void testDefaultTag() { + System.clearProperty("tags"); // to Ensure no command-line tag is set + PdslTestParameter params = PdslTestParameter.createTestParameter( + mock(Supplier.class), + Lexer.class, + Parser.class, + new String[]{"tags.feature"}, "@comment_tag#2"); + assertEquals("@comment_tag#2", params.getTagExpression()); + } + + @Test + void testMultipleTagsAndOr() { + System.setProperty("tags", "@smoke and @unit or @sample"); + PdslTestParameter params = PdslTestParameter.createTestParameter( + mock(Supplier.class), + Lexer.class, + Parser.class, + new String[]{"tags.feature", "@comment_tag#2"} + ); + // TODO: Assertions to verify the effectiveTagExpression + } +} \ No newline at end of file diff --git a/src/test/java/com/pdsl/uat/java/sut/TaggedScenarioRunner.java b/src/test/java/com/pdsl/uat/java/sut/TaggedScenarioRunner.java index 7e198d4..dff2819 100644 --- a/src/test/java/com/pdsl/uat/java/sut/TaggedScenarioRunner.java +++ b/src/test/java/com/pdsl/uat/java/sut/TaggedScenarioRunner.java @@ -2,6 +2,7 @@ import com.pdsl.runners.PdslGherkinApplication; import com.pdsl.runners.PdslTest; +import com.pdsl.runners.RecognizedBy; import com.pdsl.runners.junit.PdslGherkinJUnit4Runner; import org.antlr.v4.runtime.tree.ParseTreeListener; import org.junit.runner.RunWith; @@ -12,26 +13,29 @@ @RunWith(PdslGherkinJUnit4Runner.class) @PdslGherkinApplication( - applicationName = "Polymorphic DSL Test Framework", - context = "User Acceptance Testing", - resourceRoot = "src/test/resources/framework_specifications/features/java" + applicationName = "Polymorphic DSL Test Framework", + context = "User Acceptance Testing", + resourceRoot = "src/test/resources/framework_specifications/features/java" ) public class TaggedScenarioRunner { - @PdslTest( - parser = AllGrammarsParser.class, - lexer = AllGrammarsLexer.class, - tags = "@TaggedScenario", - listener = TaggedScenarioRunner.Listener.class - ) - public void tagFiltering_runsOnlySubsetOfScenarios(){} + @PdslTest( + parser = AllGrammarsParser.class, + lexer = AllGrammarsLexer.class, + tags = "@TaggedScenario", + listener = TaggedScenarioRunner.Listener.class + ) + @RecognizedBy(recognizerRule = "polymorphicDslAllRules", dslRecognizerParser = AllGrammarsParser.class, dslRecognizerLexer = AllGrammarsLexer.class) + public void tagFiltering_runsOnlySubsetOfScenarios() { + } - public static final class Listener implements Provider { - @Override - public ParseTreeListener get() { - return new AllGrammarsParserBaseListener(); - } + public static final class Listener implements Provider { + + @Override + public ParseTreeListener get() { + return new AllGrammarsParserBaseListener(); } + } } From 25fab3ff5674269a098849bb014ebc22c700ca7f Mon Sep 17 00:00:00 2001 From: Jana S Date: Mon, 20 Jan 2025 09:50:19 +0000 Subject: [PATCH 2/2] clean up and added comments for understaing override of runner tags --- .../filter/GherkinTagFiltererAdapter.java | 22 ++++++ .../java/com/pdsl/runners/PdslTestParams.java | 8 +- .../pdsl/runners/SharedTestSuiteVisitor.java | 14 ++++ .../testcases/PreorderTestCaseFactory.java | 7 +- .../engine/descriptor/PdslTestParameter.java | 76 +++++-------------- .../jupiter/OverrideRunnerTagViaCLITest.java | 39 +++++----- .../java/jupiter/PdslTestParameterTest.java | 49 ------------ 7 files changed, 82 insertions(+), 133 deletions(-) delete mode 100644 src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java diff --git a/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java b/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java index bb18084..044f1d9 100644 --- a/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java +++ b/src/main/java/com/pdsl/gherkin/filter/GherkinTagFiltererAdapter.java @@ -5,14 +5,36 @@ import java.util.Set; import java.util.stream.Collectors; +/** + * This class adapts the `GherkinTagFilterer` interface to the `TagFilterer` interface. It provides + * a way to use the functionality of `GherkinTagFilterer` with code that expects a `TagFilterer`. + */ public class GherkinTagFiltererAdapter implements TagFilterer { + /** + * The instance of the `GherkinTagFilterer` to be adapted. + */ private final GherkinTagFilterer gherkinTagFilterer; + /** + * Constructor for the `GherkinTagFiltererAdapter`. + * + * @param gherkinTagFilterer The instance of the `GherkinTagFilterer` to be adapted. + */ public GherkinTagFiltererAdapter(GherkinTagFilterer gherkinTagFilterer) { this.gherkinTagFilterer = gherkinTagFilterer; } + /** + * This method checks whether a collection of tags matches a given tag expression. It converts the + * collection of tags to a `Set` using a `HashSet` and then delegates the logic to the + * `gherkinTagFilterer.tagExpressionMatchesPickle` method. + * + * @param tags The collection of tags to be checked. + * @param tagExpression The tag expression to match against. + * @return True if the tags match the tag expression, False otherwise. + */ + @Override public boolean tagExpressionMatches(Collection tags, String tagExpression) { return gherkinTagFilterer.tagExpressionMatchesPickle(new HashSet<>(tags), tagExpression); diff --git a/src/main/java/com/pdsl/runners/PdslTestParams.java b/src/main/java/com/pdsl/runners/PdslTestParams.java index 3f3bad5..c0616d2 100644 --- a/src/main/java/com/pdsl/runners/PdslTestParams.java +++ b/src/main/java/com/pdsl/runners/PdslTestParams.java @@ -37,7 +37,13 @@ public static PdslTestParams from( List tags, String[] includesResources, String[] excludesResources){ - return new PdslTestParams(lexerRecognizerClass,parserRecognizerClass,interpreters,tags,includesResources,excludesResources,(tags1, tagExpression) -> true,""); + + /* Creates a default tag filter that always returns true, effectively disabling tag filtering., + Empty tag expression as no filtering is applied */ + return new PdslTestParams( + lexerRecognizerClass, parserRecognizerClass, interpreters, + tags, includesResources, excludesResources, + (tags1, tagExpression) -> true, ""); } /** * A visitor used to extend the behavior of the PdslTestParams obje3ct without modifying diff --git a/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java b/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java index 9a92396..396770b 100644 --- a/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java +++ b/src/main/java/com/pdsl/runners/SharedTestSuiteVisitor.java @@ -63,18 +63,32 @@ public SharedTestSuite recognizerParamsOperation(RecognizerParams recognizerPara // test cases to create from each file, which parts to ignore, etc. Collection specifications = getSpecifications(parser, recognizerParams, params, testResources); // Convert the specificaitons into test cases + + /* + * Filters test cases based on tags and organizes them per interpreter. + * + * This code iterates through a collection of test cases for a single interpreter, + * filters them based on tags using a provided `TagFilterer`, and then adds the + * matched test cases to a list of test cases per interpreter. It also collects + * the interpreter objects. + */ List testCasesForSingleInterpreter = new ArrayList<>(getTestCases(recognizerParams.providers().testCaseFactoryProvider().get(), specifications)); for (TestCase testcase : testCasesForSingleInterpreter) { if (testcase instanceof TaggedTestCase) { + // Cast the TestCase to TaggedTestCase to access tag information. TaggedTestCase test = (TaggedTestCase) testcase; //Filter test cases by tags using the injected TagFilterer + // Check if any of the tags on the test case match the given tag expression. boolean anyMatchedTag = params.tagFilterer().tagExpressionMatches(test.getTags(), params.tagExpression()); + // If the test case's tags match the tag expression, add it to the matched test cases. if (anyMatchedTag) { matchedTestCases.add(testcase); } } } + // Add the list of matched test cases for the current interpreter to the overall list. testCasesPerInterpreters.add(matchedTestCases); + // Get the interpreter object from the parser provider and add it to the list of interpreter objects. interpreterObjs.add(parser.interpreterProvider().get()); } diff --git a/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java b/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java index 49a5c62..2a85265 100644 --- a/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java +++ b/src/main/java/com/pdsl/testcases/PreorderTestCaseFactory.java @@ -27,18 +27,16 @@ public static final class DefaultProvider implements Provider { public PreorderTestCaseFactory get() { return INSTANCE; } - } + public static final class DefaultSupplier implements Supplier { @Override public TestCaseFactory get() { return INSTANCE; } - } - @Override public Collection processTestSpecification(Collection testSpecifications) { Collection testCases = new ArrayList<>(testSpecifications.size()); // Will likely need to be resized regardless @@ -80,9 +78,6 @@ private List recursiveWalkAndCreateOnLeaf(TestSpecification testSpecif if (!tags.isEmpty()) { testCase = new DefaultTaggedTestCase(testCase, tags); } - - - List singleTestCase = new ArrayList<>(1); singleTestCase.add(testCase); return singleTestCase; diff --git a/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java b/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java index d018039..d0f9dc4 100644 --- a/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java +++ b/src/main/java/org/junit/jupiter/engine/descriptor/PdslTestParameter.java @@ -205,20 +205,25 @@ public Builder withVisitor(Supplier> visitor) { return this; } - public Builder withTagExpression(String str) { - Preconditions.checkNotNull(str, "Tag expression cannot be null!"); - String commandLineTags = System.getProperty("tags"); - if(commandLineTags != null && !commandLineTags.isEmpty()) { - this.tagExpression = commandLineTags; - logger.info("Overriding runner tags with tags provided in the command line {%s}".formatted(commandLineTags) ); - logger.info("Ignoring provided tag expression {%s}".formatted(str) ); - } else { - this.tagExpression =str; + public Builder withTagExpression(String str) { + Preconditions.checkNotNull(str, "Tag expression cannot be null!"); + // Check if there are tags specified using the system property "tags". + String commandLineTags = System.getProperty("tags"); + if (commandLineTags != null && !commandLineTags.isEmpty()) { + // If command-line tags are present, use them and log a message informing the user + // that the provided tag expression is being ignored. + this.tagExpression = commandLineTags; + logger.info("Overriding runner tags with tags provided in the command line {%s}".formatted( + commandLineTags)); + logger.info("Ignoring provided tag expression {%s}".formatted(str)); + } else { + // If no command-line tags are present, use the provided tag expression. + this.tagExpression = str; + } + + return this; } - return this; - } - public Builder withIncludedResources(String[] resources) { this.includesResources = resources; return this; @@ -246,52 +251,5 @@ public PdslTestParameter build() { return new PdslTestParameter(this); } } - public static PdslTestParameter createTestParameter(Supplier parseTreeListenerSupplier, - Class lexerClass, - Class parserClass, - String[] includedResources) { - String defaultTagExpression = "@comment_tag#2"; - String commandLineTags = System.getProperty("tags"); // Get the value - - String effectiveTagExpression = (commandLineTags != null && !commandLineTags.isEmpty()) - ? commandLineTags - : defaultTagExpression; - - return new PdslTestParameter.Builder(parseTreeListenerSupplier, lexerClass, parserClass) - .withTagExpression(effectiveTagExpression) - .withIncludedResources(includedResources) - .build(); - } - - /** - * I've introduced a static factory method createTestParameter. This method handles the logic for - * overriding the tag expression. This keeps the builder focused on building objects and separates - * the configuration logic. - */ - public static PdslTestParameter createTestParameter( - Supplier parseTreeListenerSupplier, - Class lexerClass, - Class parserClass, - String[] includedResources, String defaultTagExpression) { - // retrieves the value passed from the command line (e.g., -Dtags="@smoke"). - String commandLineTags = System.getProperty("tags"); - // handles the logic for overriding the tag expression - String effectiveTagExpression = (commandLineTags != null && !commandLineTags.isEmpty()) - ? commandLineTags - : defaultTagExpression; - - // // String effectiveTagExpression = defaultTagExpression; // Use default if invalid format - // if (commandLineTags != null && !commandLineTags.isEmpty()) { - // String pattern = "^(?:@\\w+(?: and | or )?)*@\\w+$"; - // if (Pattern.matches(pattern, commandLineTags)) { - // // ... logic to build effectiveTagExpression from commandLineTags (as shown above) ... - // } - // } - - return new PdslTestParameter.Builder(parseTreeListenerSupplier, lexerClass, parserClass) - .withTagExpression(effectiveTagExpression) - .withIncludedResources(includedResources) - .build(); - } } diff --git a/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java b/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java index 1ef1730..c586292 100644 --- a/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java +++ b/src/test/java/com/pdsl/uat/java/jupiter/OverrideRunnerTagViaCLITest.java @@ -4,27 +4,9 @@ import com.pdsl.grammars.AllGrammarsLexer; import com.pdsl.grammars.AllGrammarsParser; import com.pdsl.grammars.AllGrammarsParserBaseVisitor; -import com.pdsl.grammars.InterpreterAllLexer; -import com.pdsl.grammars.InterpreterAllParser; -import com.pdsl.grammars.MultiInterpreter2Parser; -import com.pdsl.grammars.MultiInterpreter2Parser.ExecuteSentenceContext; -import com.pdsl.grammars.MultiInterpreter2Parser.ParserTwoAllRulesContext; -import com.pdsl.grammars.MultiInterpreter2ParserVisitor; -import com.pdsl.grammars.MultiInterpreterParser.ExecutedByAllParsersContext; -import com.pdsl.grammars.MultiInterpreterParser.FirstInterpreterContext; -import com.pdsl.grammars.MultiInterpreterParser.IgnoreInterpreterContext; -import com.pdsl.grammars.MultiInterpreterParser.ParseSentenceContext; -import com.pdsl.grammars.MultiInterpreterParser.ParsedByAllInterpretersContext; -import com.pdsl.grammars.MultiInterpreterParser.ParserOneAllRulesContext; -import com.pdsl.grammars.MultiInterpreterParser.RecognizeInterpreterContext; -import com.pdsl.grammars.MultiInterpreterParserVisitor; -import com.pdsl.grammars.MultiInterpreterRecognizerLexer; -import com.pdsl.grammars.MultiInterpreterRecognizerParser; import java.nio.file.Paths; import java.util.List; -import java.util.logging.Logger; import java.util.stream.Stream; -import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.TestTemplate; @@ -37,16 +19,28 @@ import org.junit.jupiter.engine.descriptor.PdslSharedInvocationContextProvider; import org.junit.jupiter.engine.descriptor.PdslTestParameter; +/** + * This test class demonstrates how to override the tag expression set in the test + * with tags provided via the command line using the system property "tags". + */ public class OverrideRunnerTagViaCLITest { private static int totalRunTests = 0; + /** + * This test template uses the `PdslExtension` to configure and run the test. + * The purpose of this test is to verify that the total number of tests run is 1. + */ @TestTemplate @ExtendWith(PdslExtension.class) public void pdslGherkinTestFrameworkResources(PdslExecutable executable) { totalRunTests++; } + /** + * This method asserts that only one test was run. This verifies that the + * overridden tag expression from the command line took effect. + */ @AfterAll public static void executeAfterAll(){ Assertions.assertEquals(1,totalRunTests); @@ -54,6 +48,14 @@ public static void executeAfterAll(){ private static class PdslExtension extends PdslSharedInvocationContextProvider { + /** + * This method provides the test template invocation contexts. + * It sets the system property "tags" to "@ex_tag1" before creating the + * PdslConfigParameter and then clears the property afterwards. + * + * @param context The ExtensionContext for the test. + * @return A stream of TestTemplateInvocationContext objects. + */ public Stream provideTestTemplateInvocationContexts( ExtensionContext context) { System.setProperty("tags", "@ex_tag1"); @@ -78,6 +80,7 @@ public Stream provideTestTemplateInvocationContex .toUri()) .build()) .stream(); + // Clear command-line tags System.clearProperty("tags"); return contexts; } diff --git a/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java b/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java deleted file mode 100644 index fd8c83d..0000000 --- a/src/test/java/com/pdsl/uat/java/jupiter/PdslTestParameterTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.pdsl.uat.java.jupiter; - -import java.util.function.Supplier; -import org.antlr.v4.runtime.Lexer; -import org.antlr.v4.runtime.Parser; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.engine.descriptor.PdslTestParameter; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Mockito.mock; - - -public class PdslTestParameterTest { - - @Test - void testCommandLineOverride() { - System.setProperty("tags", "@smoke"); - PdslTestParameter params = PdslTestParameter.createTestParameter( - mock(Supplier.class), - Lexer.class, - Parser.class, - new String[]{"tags.feature"}, "@comment_tag#2"); - - assertEquals("@smoke", params.getTagExpression()); - } - - @Test - void testDefaultTag() { - System.clearProperty("tags"); // to Ensure no command-line tag is set - PdslTestParameter params = PdslTestParameter.createTestParameter( - mock(Supplier.class), - Lexer.class, - Parser.class, - new String[]{"tags.feature"}, "@comment_tag#2"); - assertEquals("@comment_tag#2", params.getTagExpression()); - } - - @Test - void testMultipleTagsAndOr() { - System.setProperty("tags", "@smoke and @unit or @sample"); - PdslTestParameter params = PdslTestParameter.createTestParameter( - mock(Supplier.class), - Lexer.class, - Parser.class, - new String[]{"tags.feature", "@comment_tag#2"} - ); - // TODO: Assertions to verify the effectiveTagExpression - } -} \ No newline at end of file