From 8e0bd06af672c0989e2365287bdd95f18ceb8609 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Fri, 13 Jan 2023 15:54:44 +0000 Subject: [PATCH 1/5] Filled out usage documentation --- assert/assert-junit5/README.md | 2 +- .../test/flow/doc/DependencyTest.java | 110 ++++++++++++++++++ message/message-core/README.md | 15 ++- message/message-http/README.md | 22 +++- message/message-json/README.md | 21 +++- message/message-sql/README.md | 22 +++- message/message-text/README.md | 21 +++- message/message-web/README.md | 13 ++- message/message-xml/README.md | 21 +++- report/report-core/README.md | 4 + .../test/flow/report/QuietFiles.java | 29 +++-- validation/validation-junit4/README.md | 38 ++++++ validation/validation-junit5/README.md | 26 ++++- 13 files changed, 325 insertions(+), 19 deletions(-) create mode 100644 doc/src/test/java/com/mastercard/test/flow/doc/DependencyTest.java diff --git a/assert/assert-junit5/README.md b/assert/assert-junit5/README.md index 670f15e839..56639684d5 100644 --- a/assert/assert-junit5/README.md +++ b/assert/assert-junit5/README.md @@ -22,7 +22,7 @@ It provides the `Flocessor` class, which should be used as a generator for a [dy com.mastercard.test.flow - assert-junit4 + assert-junit5 ${flow.version} test diff --git a/doc/src/test/java/com/mastercard/test/flow/doc/DependencyTest.java b/doc/src/test/java/com/mastercard/test/flow/doc/DependencyTest.java new file mode 100644 index 0000000000..2c4c704664 --- /dev/null +++ b/doc/src/test/java/com/mastercard/test/flow/doc/DependencyTest.java @@ -0,0 +1,110 @@ +package com.mastercard.test.flow.doc; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.stream.Collectors.joining; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import org.junit.jupiter.api.DynamicNode; +import org.junit.jupiter.api.TestFactory; + +import com.mastercard.test.flow.report.QuietFiles; + +/** + * Checks that the documented maven dependency declarations are accurate + */ +@SuppressWarnings("static-method") +class DependencyTest { + + private static Pattern DEP = Pattern.compile( "(.*)", Pattern.DOTALL ); + private static Pattern GRP = Pattern.compile( "(.*)" ); + private static Pattern RTF = Pattern.compile( "(.*)" ); + private static Pattern VRS = Pattern.compile( "(.*)" ); + + /** + * Checks that all of the suggested dependency declarations in the readmes + * accurately target an artifact from this project + * + * @return per-markdown-file tests + */ + @TestFactory + Stream markdown() { + PomData root = new PomData( null, Paths.get( "../pom.xml" ) ); + Set allowed = new TreeSet<>(); + Map dirPoms = new TreeMap<>(); + root.visit( pd -> { + allowed.add( pd.groupId() + ":" + pd.artifactId() ); + dirPoms.put( pd.dirPath(), pd ); + } ); + String allowedString = allowed.stream().collect( joining( "\n " ) ); + + Set used = new TreeSet<>(); + + return Stream.concat( + Util.markdownFiles() + .map( path -> dynamicTest( path.toString(), () -> { + String content = new String( QuietFiles.readAllBytes( path ), UTF_8 ); + Matcher depM = DEP.matcher( content ); + while( depM.find() ) { + Matcher grpM = GRP.matcher( depM.group( 1 ) ); + assertTrue( grpM.find(), "groupId found in " + depM.group( 0 ) ); + + Matcher rtfM = RTF.matcher( depM.group( 1 ) ); + assertTrue( rtfM.find(), "artifactId found in " + depM.group( 0 ) ); + + Matcher vrsM = VRS.matcher( depM.group( 1 ) ); + assertTrue( vrsM.find(), "version found in " + depM.group( 0 ) ); + assertEquals( "${flow.version}", vrsM.group( 1 ), + "Version element in\n" + depM.group( 0 ) ); + + String dep = grpM.group( 1 ) + ":" + rtfM.group( 1 ); + used.add( dep ); + + if( "README.md".equals( path.getFileName().toString() ) ) { + PomData pom = dirPoms.get( path.getParent() ); + assertNotNull( pom, "pom associated with readme" ); + assertEquals( + pom.groupId() + ":" + pom.artifactId(), + dep, + String.format( + "Documented dependency%n%s%nmatches associated pom", + depM.group() ) ); + } + + assertTrue( allowed.contains( dep ), + String.format( + "Dependency '%s' taken from dependency%n%s%nfound in allowed set:%n%s", + dep, depM.group(), allowedString ) ); + } + } ) ), + Stream.of( dynamicTest( "Documented dependencies", () -> { + assertEquals( "" + + "com.mastercard.test.flow:assert-junit4\n" + + "com.mastercard.test.flow:assert-junit5\n" + + "com.mastercard.test.flow:builder\n" + + "com.mastercard.test.flow:message-core\n" + + "com.mastercard.test.flow:message-http\n" + + "com.mastercard.test.flow:message-json\n" + + "com.mastercard.test.flow:message-sql\n" + + "com.mastercard.test.flow:message-text\n" + + "com.mastercard.test.flow:message-web\n" + + "com.mastercard.test.flow:message-xml\n" + + "com.mastercard.test.flow:model\n" + + "com.mastercard.test.flow:validation-junit4\n" + + "com.mastercard.test.flow:validation-junit5", + used.stream().collect( joining( "\n" ) ) ); + } ) ) ); + } +} diff --git a/message/message-core/README.md b/message/message-core/README.md index c0e60c44cc..3dc093cb6c 100644 --- a/message/message-core/README.md +++ b/message/message-core/README.md @@ -9,4 +9,17 @@ Message implementation utilities * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +You'll only need to consume this artifact directly if you're implementing your own `Message` type. + +```xml + + + com.mastercard.test.flow + message-core + ${flow.version} + +``` \ No newline at end of file diff --git a/message/message-http/README.md b/message/message-http/README.md index dc5b430183..d22ddf1ca7 100644 --- a/message/message-http/README.md +++ b/message/message-http/README.md @@ -9,4 +9,24 @@ HypterText Transfer Protocol messages * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +```xml + + + com.mastercard.test.flow + message-http + ${flow.version} + +``` + +The unit tests [`HttpReqTest`][HttpReqTest] and [`HttpResTest`][HttpResTest] contain examples of the usage of the message types supplied by this module. + + + +[HttpReqTest]: src/test/java/com/mastercard/test/flow/msg/http/HttpReqTest.java +[HttpResTest]: src/test/java/com/mastercard/test/flow/msg/http/HttpResTest.java + + diff --git a/message/message-json/README.md b/message/message-json/README.md index 2462a01bf3..6680cb749e 100644 --- a/message/message-json/README.md +++ b/message/message-json/README.md @@ -9,4 +9,23 @@ JavaScript Object Notation Messages * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +```xml + + + com.mastercard.test.flow + message-json + ${flow.version} + +``` + +The unit test [`JsonTest`][JsonTest] contains examples of the usage of the message type supplied by this module. + + + +[JsonTest]: src/test/java/com/mastercard/test/flow/msg/json/JsonTest.java + + diff --git a/message/message-sql/README.md b/message/message-sql/README.md index 34862088ae..068d2ff0bc 100644 --- a/message/message-sql/README.md +++ b/message/message-sql/README.md @@ -9,4 +9,24 @@ Structured Query Language messages * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +```xml + + + com.mastercard.test.flow + message-sql + ${flow.version} + +``` + +The unit tests [`QueryTest`][sql.QueryTest] and [`ResultTest`][ResultTest] contain examples of the usage of the message types supplied by this module. + + + +[sql.QueryTest]: src/test/java/com/mastercard/test/flow/msg/sql/QueryTest.java +[ResultTest]: src/test/java/com/mastercard/test/flow/msg/sql/ResultTest.java + + diff --git a/message/message-text/README.md b/message/message-text/README.md index ea560e1597..501254c2f4 100644 --- a/message/message-text/README.md +++ b/message/message-text/README.md @@ -9,4 +9,23 @@ Freeform text Message * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +```xml + + + com.mastercard.test.flow + message-text + ${flow.version} + +``` + +The unit test [`TextTest`][TextTest] contains examples of the usage of the message type supplied by this module. + + + +[TextTest]: src/test/java/com/mastercard/test/flow/msg/txt/TextTest.java + + diff --git a/message/message-web/README.md b/message/message-web/README.md index 1a0c8a393e..b68430f44f 100644 --- a/message/message-web/README.md +++ b/message/message-web/README.md @@ -11,7 +11,18 @@ Browser interaction messages -## Example usage +## Usage + +```xml + + + com.mastercard.test.flow + message-web + ${flow.version} + +``` + +## Example Defining a form submission sequence: diff --git a/message/message-xml/README.md b/message/message-xml/README.md index cc1e8510f5..f6eee73a62 100644 --- a/message/message-xml/README.md +++ b/message/message-xml/README.md @@ -9,4 +9,23 @@ Extensible Markup Language Messages * [../message](..) Implementations of the Message interface - \ No newline at end of file + + +## Usage + +```xml + + + com.mastercard.test.flow + message-xml + ${flow.version} + +``` + +The unit test [`XMLTest`][XMLTest] contains examples of the usage of the message type supplied by this module. + + + +[XMLTest]: src/test/java/com/mastercard/test/flow/msg/xml/XMLTest.java + + diff --git a/report/report-core/README.md b/report/report-core/README.md index 8b6ad8bb62..e8e9a1c036 100644 --- a/report/report-core/README.md +++ b/report/report-core/README.md @@ -11,6 +11,10 @@ Report input/output +## Usage + +It is unlikely that you'll need to depend directly on this module, it will be transitively supplied by [`assert-junit4`](../../assert/assert-junit4) or [`assert-junit5`](../../assert/assert-junit5). + ## Functionality This module provides an object model for the data in an execution report along with facilities for writing and reading that data to and from storage. diff --git a/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java b/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java index 70f7b1a621..d24869f9c5 100644 --- a/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java +++ b/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java @@ -34,7 +34,7 @@ interface FailureProne { * {@link UncheckedIOException} * * @param The return type - * @param op The operation + * @param op The operation * @return The return value */ static T wrap( FailureProne op ) { @@ -77,9 +77,9 @@ else if( Files.isDirectory( path ) ) { /** * @see Files#createDirectories(Path, FileAttribute...) - * @param dir the directory to create + * @param dir the directory to create * @param attr an optional list of file attributes to set atomically when - * creating the directory + * creating the directory */ public static void createDirectories( Path dir, FileAttribute... attr ) { wrap( () -> Files.createDirectories( dir, attr ) ); @@ -87,12 +87,12 @@ public static void createDirectories( Path dir, FileAttribute... attr ) { /** * @see Files#createTempFile(String, String, FileAttribute...) - * @param prefix the prefix string to be used in generating the file's name; - * may be null - * @param suffix the suffix string to be used in generating the file's name; - * may be null, in which case ".tmp" is used + * @param prefix the prefix string to be used in generating the file's name; may + * be null + * @param suffix the suffix string to be used in generating the file's name; may + * be null, in which case ".tmp" is used * @param attributes an optional list of file attributes to set atomically when - * creating the file + * creating the file * @return the path to the newly created file that did not exist before this * method was invoked */ @@ -103,8 +103,8 @@ public static Path createTempFile( String prefix, String suffix, /** * @see Files#write(Path, byte[], OpenOption...) - * @param path The path to write to - * @param bytes The data to write + * @param path The path to write to + * @param bytes The data to write * @param options options specifying how the file is opened * @return the path */ @@ -129,4 +129,13 @@ public static Stream lines( Path path ) { public static Stream list( Path dir ) { return wrap( () -> Files.list( dir ) ); } + + /** + * @see Files#readAllBytes(Path) + * @param path The path to read + * @return The bytes of the file at that location + */ + public static byte[] readAllBytes( Path path ) { + return wrap( () -> Files.readAllBytes( path ) ); + } } diff --git a/validation/validation-junit4/README.md b/validation/validation-junit4/README.md index 34866d847c..833acc0329 100644 --- a/validation/validation-junit4/README.md +++ b/validation/validation-junit4/README.md @@ -10,3 +10,41 @@ Junit4 validation components * [../validation](..) Checking model consistency + +## Usage + +```xml + + + + com.mastercard.test.flow + validation-junit4 + ${flow.version} + +``` + +The `Validator` implementation provided by this module can used in a [parameterised test](https://junit.org/junit4/javadoc/4.12/org/junit/runners/Parameterized.html): + +```java +@RunWith(Parameterized.class) +public class MyTest { + @Parameters(name = "{0}") + public static Collection flows() { + return new Validator() + .checking( MY_SYSTEM_MODEL ) + .with( AbstractValidator.defaultChecks() ) + .parameters(); + } + + @Parameter(0) + public String name; + + @Parameter(1) + public Runnable check; + + @Test + public void test() { + check.run(); + } +} +``` diff --git a/validation/validation-junit5/README.md b/validation/validation-junit5/README.md index 89db68a084..8dd063dc89 100644 --- a/validation/validation-junit5/README.md +++ b/validation/validation-junit5/README.md @@ -9,4 +9,28 @@ Junit5 validation components * [../validation](..) Checking model consistency - \ No newline at end of file + + +## Usage + +```xml + + + + com.mastercard.test.flow + validation-junit5 + ${flow.version} + +``` + +The `Validator` implementation provided by this module can used in a [dynamic test](https://junit.org/junit5/docs/current/user-guide/#writing-tests-dynamic-tests): + +```java +@TestFactory +Stream checks() { + return new Validator() + .checking( MY_SYSTEM_MODEL ) + .with( AbstractValidator.defaultChecks() ) + .tests(); +} +``` From bd7afcc06072eebd2f1ccd2f0036f0e898fc4bc4 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Fri, 13 Jan 2023 16:12:59 +0000 Subject: [PATCH 2/5] tweak --- message/message-web/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/message/message-web/README.md b/message/message-web/README.md index b68430f44f..2161c9514d 100644 --- a/message/message-web/README.md +++ b/message/message-web/README.md @@ -22,8 +22,6 @@ Browser interaction messages ``` -## Example - Defining a form submission sequence: @@ -145,4 +143,4 @@ if( assrt.expected().request() instanceof WebSequence Note how: * The actual URL for the page is populated at runtime on a `child()` of the request sequence. This means that the runtime-sourced data will be highlighted in the full diff view of the execution report. - * We're grabbing the full page source in the extracted results, but we're also masking it as not interesting. This allows users to see the page source in the execution report, but doesn't consign us to slavishly tracking every non-functional change to the HTML in the test suite. + * We're grabbing the full page source in the extracted results, but we're also masking it as not interesting. This allows users to see the page source in the execution report, but doesn't condemn us to exhaustively tracking every non-functional change to the HTML in the test suite. From d6c89c47c794305faa7a7ffc19964443690206ab Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Fri, 13 Jan 2023 16:14:11 +0000 Subject: [PATCH 3/5] format --- .../test/flow/report/QuietFiles.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java b/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java index d24869f9c5..d59b0c31c6 100644 --- a/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java +++ b/report/report-core/src/main/java/com/mastercard/test/flow/report/QuietFiles.java @@ -34,7 +34,7 @@ interface FailureProne { * {@link UncheckedIOException} * * @param The return type - * @param op The operation + * @param op The operation * @return The return value */ static T wrap( FailureProne op ) { @@ -77,9 +77,9 @@ else if( Files.isDirectory( path ) ) { /** * @see Files#createDirectories(Path, FileAttribute...) - * @param dir the directory to create + * @param dir the directory to create * @param attr an optional list of file attributes to set atomically when - * creating the directory + * creating the directory */ public static void createDirectories( Path dir, FileAttribute... attr ) { wrap( () -> Files.createDirectories( dir, attr ) ); @@ -87,12 +87,12 @@ public static void createDirectories( Path dir, FileAttribute... attr ) { /** * @see Files#createTempFile(String, String, FileAttribute...) - * @param prefix the prefix string to be used in generating the file's name; may - * be null - * @param suffix the suffix string to be used in generating the file's name; may - * be null, in which case ".tmp" is used + * @param prefix the prefix string to be used in generating the file's name; + * may be null + * @param suffix the suffix string to be used in generating the file's name; + * may be null, in which case ".tmp" is used * @param attributes an optional list of file attributes to set atomically when - * creating the file + * creating the file * @return the path to the newly created file that did not exist before this * method was invoked */ @@ -103,8 +103,8 @@ public static Path createTempFile( String prefix, String suffix, /** * @see Files#write(Path, byte[], OpenOption...) - * @param path The path to write to - * @param bytes The data to write + * @param path The path to write to + * @param bytes The data to write * @param options options specifying how the file is opened * @return the path */ From aab2b8674060be271585b9b7fa389aa3aba6c0b2 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Fri, 13 Jan 2023 16:20:11 +0000 Subject: [PATCH 4/5] simplify! --- message/message-http/README.md | 2 +- message/message-json/README.md | 2 +- message/message-sql/README.md | 2 +- message/message-text/README.md | 2 +- message/message-xml/README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/message/message-http/README.md b/message/message-http/README.md index d22ddf1ca7..aee5035921 100644 --- a/message/message-http/README.md +++ b/message/message-http/README.md @@ -22,7 +22,7 @@ HypterText Transfer Protocol messages ``` -The unit tests [`HttpReqTest`][HttpReqTest] and [`HttpResTest`][HttpResTest] contain examples of the usage of the message types supplied by this module. +The unit tests [`HttpReqTest`][HttpReqTest] and [`HttpResTest`][HttpResTest] contain usage examples for the message types supplied by this module. diff --git a/message/message-json/README.md b/message/message-json/README.md index 6680cb749e..e5dede767e 100644 --- a/message/message-json/README.md +++ b/message/message-json/README.md @@ -22,7 +22,7 @@ JavaScript Object Notation Messages ``` -The unit test [`JsonTest`][JsonTest] contains examples of the usage of the message type supplied by this module. +The unit test [`JsonTest`][JsonTest] contains usage examples for the message type supplied by this module. diff --git a/message/message-sql/README.md b/message/message-sql/README.md index 068d2ff0bc..344341dd30 100644 --- a/message/message-sql/README.md +++ b/message/message-sql/README.md @@ -22,7 +22,7 @@ Structured Query Language messages ``` -The unit tests [`QueryTest`][sql.QueryTest] and [`ResultTest`][ResultTest] contain examples of the usage of the message types supplied by this module. +The unit tests [`QueryTest`][sql.QueryTest] and [`ResultTest`][ResultTest] contain usage examples for the message types supplied by this module. diff --git a/message/message-text/README.md b/message/message-text/README.md index 501254c2f4..7aa1d90c02 100644 --- a/message/message-text/README.md +++ b/message/message-text/README.md @@ -22,7 +22,7 @@ Freeform text Message ``` -The unit test [`TextTest`][TextTest] contains examples of the usage of the message type supplied by this module. +The unit test [`TextTest`][TextTest] contains usage examples for the message type supplied by this module. diff --git a/message/message-xml/README.md b/message/message-xml/README.md index f6eee73a62..5c909c3c9f 100644 --- a/message/message-xml/README.md +++ b/message/message-xml/README.md @@ -22,7 +22,7 @@ Extensible Markup Language Messages ``` -The unit test [`XMLTest`][XMLTest] contains examples of the usage of the message type supplied by this module. +The unit test [`XMLTest`][XMLTest] contains usage examples for the message type supplied by this module. From 254487e764571e66d1ce516a5c9fa79a847f6885 Mon Sep 17 00:00:00 2001 From: Ryan McNally Date: Fri, 13 Jan 2023 16:34:02 +0000 Subject: [PATCH 5/5] killed mutant --- .../com/mastercard/test/flow/report/QuietFilesTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/report/report-core/src/test/java/com/mastercard/test/flow/report/QuietFilesTest.java b/report/report-core/src/test/java/com/mastercard/test/flow/report/QuietFilesTest.java index 787fb5bb4b..fcf3d3f0f1 100644 --- a/report/report-core/src/test/java/com/mastercard/test/flow/report/QuietFilesTest.java +++ b/report/report-core/src/test/java/com/mastercard/test/flow/report/QuietFilesTest.java @@ -141,15 +141,18 @@ void deleteDir() throws Exception { } /** - * File writing + * File writing and reading * * @throws Exception if pre-emptive cleanup fails */ @Test - void write() throws Exception { + void writeRead() throws Exception { Path f = Paths.get( "target/write" ); Files.deleteIfExists( f ); Path r = QuietFiles.write( f, "hello!".getBytes( UTF_8 ) ); assertEquals( f, r ); + + assertEquals( "hello!", new String( QuietFiles.readAllBytes( f ), UTF_8 ) ); } + }