From 60c5b8e34ea385dfc76561a108eb3c214afe7673 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sat, 4 Nov 2017 16:45:19 +0100 Subject: [PATCH 01/46] Jenkins Build Pipeline --- Jenkinsfile | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..49c0ca3 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,39 @@ +def gradle(tasks) { + sh "./gradlew --info -s --no-daemon $tasks" +} + +properties([ + pipelineTriggers([ + [$class: 'GitHubPushTrigger'] + ]) +]) + +timestamps { + + node { + + stage('Clean Checkout') { + checkout scm + // Clean build: ensure no unversioned files disturbing the build + sh "git clean -x -d -f" + } + + stage('Build & Test') { + + try { + + gradle '-x signArchives clean build' + + } finally { + + junit '**/build/test-results/*.xml' + + archiveArtifacts artifacts: 'build/documentation.zip' + + } + + } + + } + +} From ed31905a28a0c3dd1d754cf2faaac08cad9af085 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sat, 4 Nov 2017 16:47:39 +0100 Subject: [PATCH 02/46] Jenkins Build Pipeline: archive artifacts --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 49c0ca3..063ef08 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -28,7 +28,7 @@ timestamps { junit '**/build/test-results/*.xml' - archiveArtifacts artifacts: 'build/documentation.zip' + archiveArtifacts artifacts: 'build/libs/scenarioo-*.jar, build/**/*.xsd, LICENSE.txt, README.md' } From cdb2c9e0e3be78271d147d42a6c8f38c83ef4e79 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sat, 4 Nov 2017 16:51:07 +0100 Subject: [PATCH 03/46] Jenkins Build Pipeline: correct build report location --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 063ef08..91f44fe 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -26,7 +26,7 @@ timestamps { } finally { - junit '**/build/test-results/*.xml' + junit '**/build/test-results/test/*.xml' archiveArtifacts artifacts: 'build/libs/scenarioo-*.jar, build/**/*.xsd, LICENSE.txt, README.md' From c68905b060f452bf1ae54a0eb2cbe93ab354ede9 Mon Sep 17 00:00:00 2001 From: Christoph Gross Date: Wed, 21 Mar 2018 00:03:25 +0100 Subject: [PATCH 04/46] Fixes #10, broken build after checkout because of missing certificate configuration. Taken from: https://github.com/stianh/gradle-jaxb-plugin/commit/ff912752fe7d83013497305fe038652b530b6866 This enables other developers to locally do a gradle install of their own versions without being stopped because the build want to sign the artifacts first. To enable signing now, one must set the project property sign, like this: gradle -Psign --- build.gradle | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 590537a..46c09da 100644 --- a/build.gradle +++ b/build.gradle @@ -1,21 +1,21 @@ /* scenarioo-api * Copyright (C) 2014, scenarioo.org Development Team - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * As a special exception, the copyright holders of this library give you - * permission to link this library with independent modules, according + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules, according * to the GNU General Public License with "Classpath" exception as provided * in the LICENSE file that accompanied this code. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -29,11 +29,11 @@ apply plugin: 'java' apply plugin: 'maven' apply plugin: 'signing' -sourceCompatibility=1.6 -targetCompatibility=1.6 +sourceCompatibility = 1.6 +targetCompatibility = 1.6 repositories { - mavenCentral() + mavenCentral() } dependencies { @@ -59,8 +59,10 @@ artifacts { archives javadocJar, sourcesJar } -signing { - sign configurations.archives +if (project.hasProperty('sign')) { + signing { + sign configurations.archives + } } tasks.withType(Javadoc) { @@ -70,7 +72,11 @@ tasks.withType(Javadoc) { uploadArchives { repositories { mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } + if (project.hasProperty('sign')) { + beforeDeployment { + MavenDeployment deployment -> signing.signPom(deployment) + } + } repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { authentication(userName: ossrhUsername, password: ossrhPassword) @@ -124,4 +130,4 @@ cleanEclipse.dependsOn = cleanEclipse.taskDependencies.values - cleanEclipseJdt task wrapper(type: Wrapper) { gradleVersion = '3.3' -} \ No newline at end of file +} From 6f37ce3cf9692ba7c164e805c862d274863f45a2 Mon Sep 17 00:00:00 2001 From: Christoph Gross Date: Wed, 21 Mar 2018 00:07:27 +0100 Subject: [PATCH 05/46] Set sign flag in Jenkinsfile. --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 91f44fe..2249650 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,7 @@ timestamps { try { - gradle '-x signArchives clean build' + gradle '-Psign -x signArchives clean build' } finally { From 2465f28ebfebbf16f6a1abf9062b8034f801baad Mon Sep 17 00:00:00 2001 From: adiherzog Date: Wed, 21 Mar 2018 09:41:21 +0100 Subject: [PATCH 06/46] Add the -Psign parameter in the documentation --- docs/upload-to-maven-central.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/upload-to-maven-central.md b/docs/upload-to-maven-central.md index 2b3ea55..3fbadb1 100644 --- a/docs/upload-to-maven-central.md +++ b/docs/upload-to-maven-central.md @@ -1,19 +1,21 @@ # Upload to maven central + ## Snapshot -1. You will need to specify the following properties in your gradle.properties located in your gradle home directory: -``` -signing.keyId=BDCAAE60 -signing.password=#private key goes here# -signing.secretKeyRingFile=#secret key file goes here# -ossrhUsername=scenarioo -ossrhPassword=#sonatype password goes here# -``` +1. You will need to specify the following properties in your `gradle.properties` located in your gradle home directory: + + ``` + signing.keyId=BDCAAE60 + signing.password=#private key goes here# + signing.secretKeyRingFile=#secret key file goes here# + ossrhUsername=scenarioo + ossrhPassword=#sonatype password goes here# + ``` -2. Change the version appropriately in the build.gradle -3. `gradlew clean uploadArchives` +2. Change the version appropriately in the `build.gradle` +3. `gradlew clean uploadArchives -Psign` ## Releases -Same steps as for snapshot releases and -4. Promote build to maven central: -http://central.sonatype.org/pages/releasing-the-deployment.html \ No newline at end of file + +Same steps as for snapshot releases and then promote build to maven central: +http://central.sonatype.org/pages/releasing-the-deployment.html From af6b02d28326cd41e32ac6d716e0a96fa53dcd8d Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Tue, 8 May 2018 09:44:07 +0200 Subject: [PATCH 07/46] Update Gradle Wrapper to 4.7 --- gradle/wrapper/gradle-wrapper.jar | Bin 53638 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 68 +++++++++++++---------- gradlew.bat | 14 ++--- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e8c6bf7bb47dff6b81c2cf7a349eb7e912c9fbe2..5ad52a294e609f55eb13793a2abab7d9f5442949 100644 GIT binary patch delta 24991 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 O0Z)NNP!@m%f&LF)CR1Ag delta 24406 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 T-JGz}aWWDrAn|NFPiy}NYfIXW diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2d70463..60f3222 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Feb 11 10:28:39 CET 2017 +#Mon May 07 18:56:43 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip diff --git a/gradlew b/gradlew index 97fac78..4453cce 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -6,12 +6,30 @@ ## ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then @@ -150,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 8a0b282..f955316 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,10 +46,9 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line From 6d1ba8617745fb16658a6aa0a12f29638c2ede0f Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Tue, 8 May 2018 09:56:35 +0200 Subject: [PATCH 08/46] Update Gradle Wrapper to 4.7. cleanEclipse.taskDependencies.values is no longer supported with Gradle 4.7. Since we no longer support Eclipse, we remove this section. --- build.gradle | 6 +----- gradle/wrapper/gradle-wrapper.jar | Bin 54208 -> 54208 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 46c09da..fa9afa9 100644 --- a/build.gradle +++ b/build.gradle @@ -124,10 +124,6 @@ task generateSchema(type: JavaExec) { jar.dependsOn generateSchema -// Prevent Eclipse "Gradle -> Refresh All" to execute cleanEclipseJdt, -// because it would delete our version of the org.eclipse.jdt.ui.prefs file. -cleanEclipse.dependsOn = cleanEclipse.taskDependencies.values - cleanEclipseJdt - task wrapper(type: Wrapper) { - gradleVersion = '3.3' + gradleVersion = '4.7' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5ad52a294e609f55eb13793a2abab7d9f5442949..cd4fa588049e2ad3913c883f60681bd38e154c04 100644 GIT binary patch delta 26 gcmX@GocX|V<_*z@m>2r3*c^9AND#!BTzuIV0Hlcv@&Et; delta 26 gcmX@GocX|V<_*z@m_?^A-yC;HND#!BTzuIV0G;0pY5)KL diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 60f3222..d6c2285 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon May 07 18:56:43 CEST 2018 +#Tue May 08 09:53:02 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip From 1998ab6992bafef55d4729135efed5036b2a4819 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Thu, 24 May 2018 23:38:31 +0200 Subject: [PATCH 09/46] #14 Fix loading of builds and branches to not fail just because one build or branch is somehow corrupt, ignore it in this case and log an error. --- .../org/scenarioo/api/ScenarioDocuReader.java | 42 +++++++-------- .../api/util/xml/ScenarioDocuXMLFileUtil.java | 53 +++++++++++++++---- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/scenarioo/api/ScenarioDocuReader.java b/src/main/java/org/scenarioo/api/ScenarioDocuReader.java index 96a37ce..41620aa 100644 --- a/src/main/java/org/scenarioo/api/ScenarioDocuReader.java +++ b/src/main/java/org/scenarioo/api/ScenarioDocuReader.java @@ -1,21 +1,21 @@ /* scenarioo-api * Copyright (C) 2014, scenarioo.org Development Team - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * As a special exception, the copyright holders of this library give you - * permission to link this library with independent modules, according + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules, according * to the GNU General Public License with "Classpath" exception as provided * in the LICENSE file that accompanied this code. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -40,28 +40,28 @@ * Gives access to the geenrated scenario docu files in the filesystem. */ public class ScenarioDocuReader { - + private final ScenarioDocuFiles docuFiles; - + public ScenarioDocuReader(final File rootDirectory) { this.docuFiles = new ScenarioDocuFiles(rootDirectory); } - + public Branch loadBranch(final String branchName) { File file = docuFiles.getBranchFile(checkIdentifier(branchName)); return ScenarioDocuXMLFileUtil.unmarshal(Branch.class, file); } - + public List loadBranches() { List branchFiles = docuFiles.getBranchFiles(); - return ScenarioDocuXMLFileUtil.unmarshalListOfFiles(Branch.class, branchFiles); + return ScenarioDocuXMLFileUtil.unmarshalListOfFilesIgnoreInvalid(Branch.class, branchFiles); } - + public Build loadBuild(final String branchName, final String buildName) { File file = docuFiles.getBuildFile(checkIdentifier(branchName), checkIdentifier(buildName)); return ScenarioDocuXMLFileUtil.unmarshal(Build.class, file); } - + /** * This method was changed in in Version 2.0 of the API to return a list of ObjectFromDirectory<Build> instead * of a list of BuildLinks. This was done because BuildLinks belongs to the Server now and is not part of the API @@ -69,47 +69,47 @@ public Build loadBuild(final String branchName, final String buildName) { */ public List> loadBuilds(final String branchName) { List buildFiles = docuFiles.getBuildFiles(checkIdentifier(branchName)); - return ScenarioDocuXMLFileUtil.unmarshalListOfFilesWithDirNames(buildFiles, Build.class); + return ScenarioDocuXMLFileUtil.unmarshalListOfFilesWithDirNamesIgnoreInvalid(buildFiles, Build.class); } - + public List loadUsecases(final String branchName, final String buildName) { List files = docuFiles.getUseCaseFiles(checkIdentifier(branchName), checkIdentifier(buildName)); return ScenarioDocuXMLFileUtil.unmarshalListOfFiles(UseCase.class, files); } - + public UseCase loadUsecase(final String branchName, final String buildName, final String useCaseName) { File file = docuFiles.getUseCaseFile(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName)); return ScenarioDocuXMLFileUtil.unmarshal(UseCase.class, file); } - + public List loadScenarios(final String branchName, final String buildName, final String useCaseName) { List files = docuFiles.getScenarioFiles(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName)); return ScenarioDocuXMLFileUtil.unmarshalListOfFiles(Scenario.class, files); } - + public Scenario loadScenario(final String branchName, final String buildName, final String useCaseName, final String scenarioName) { File file = docuFiles.getScenarioFile(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName), checkIdentifier(scenarioName)); return ScenarioDocuXMLFileUtil.unmarshal(Scenario.class, file); } - + public List loadSteps(final String branchName, final String buildName, final String useCaseName, final String scenarioName) { List files = docuFiles.getStepFiles(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName), checkIdentifier(scenarioName)); return ScenarioDocuXMLFileUtil.unmarshalListOfFiles(Step.class, files); } - + public Step loadStep(final String branchName, final String buildName, final String useCaseName, final String scenarioName, final int stepIndex) { File file = docuFiles.getStepFile(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName), checkIdentifier(scenarioName), stepIndex); return ScenarioDocuXMLFileUtil.unmarshal(Step.class, file); } - + /** * Screenshot files are simply provided by path, the REST service will take care of streaming it. */ @@ -118,5 +118,5 @@ public File getScreenshotFile(final String branchName, final String buildName, f return new File(docuFiles.getScreenshotsDirectory(checkIdentifier(branchName), checkIdentifier(buildName), checkIdentifier(useCaseName), checkIdentifier(scenarioName)), imageName); } - + } diff --git a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java index 1d5a2d5..23198cb 100644 --- a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java +++ b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java @@ -1,21 +1,21 @@ /* scenarioo-api * Copyright (C) 2014, scenarioo.org Development Team - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * As a special exception, the copyright holders of this library give you - * permission to link this library with independent modules, according + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules, according * to the GNU General Public License with "Classpath" exception as provided * in the LICENSE file that accompanied this code. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.List; +import org.apache.log4j.Logger; import org.scenarioo.api.exception.ResourceNotFoundException; import org.scenarioo.api.files.ObjectFromDirectory; @@ -37,7 +38,9 @@ * Writing or reading of all ScenarioDocu entities to XML files and back */ public class ScenarioDocuXMLFileUtil { - + + private static final Logger LOGGER = Logger.getLogger(ScenarioDocuXMLFileUtil.class); + public static void marshal(final T object, final File destFile) { FileOutputStream fos = null; try { @@ -56,7 +59,7 @@ public static void marshal(final T object, final File destFile) { } } } - + public static T unmarshal(final Class targetClass, final File srcFile) { if (!srcFile.exists()) { throw new ResourceNotFoundException(srcFile.getAbsolutePath()); @@ -77,7 +80,19 @@ public static T unmarshal(final Class targetClass, final File srcFile) { } } } - + + public static List unmarshalListOfFilesIgnoreInvalid(final Class targetClass, final List files) { + List result = new ArrayList(); + for (File file : files) { + try { + result.add(unmarshal(targetClass, file)); + } catch (Throwable e) { + LOGGER.error("Could not parse invalid File: " + file.getAbsolutePath() + " - will ignore this object."); + } + } + return result; + } + public static List unmarshalListOfFiles(final Class targetClass, final List files) { List result = new ArrayList(); for (File file : files) { @@ -85,7 +100,7 @@ public static List unmarshalListOfFiles(final Class targetClass, final } return result; } - + /** * Read all passed files and unmarshall these to the given object type, also return the name of the directory the * object was loaded from. @@ -99,5 +114,23 @@ public static List> unmarshalListOfFilesWithDirNames( } return result; } - + + /** + * Read all passed files and unmarshall these to the given object type, also return the name of the directory the + * object was loaded from. + */ + public static List> unmarshalListOfFilesWithDirNamesIgnoreInvalid( + final List files, final Class targetClass, final Class... classesToBind) { + List> result = new ArrayList>(); + for (File file : files) { + try { + result.add(new ObjectFromDirectory(unmarshal(targetClass, file), file + .getParentFile().getName())); + } catch (Throwable e) { + LOGGER.error("Could not parse invalid File: " + file.getAbsolutePath() + " - will ignore this object."); + } + } + return result; + } + } From a56d4815c9d704bc8f5417c3154fa93673c4cce8 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Fri, 25 May 2018 00:07:32 +0200 Subject: [PATCH 10/46] #14 new version for the fix version --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fa9afa9..9c97c93 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ group = 'org.scenarioo' -version = '2.1.2-SNAPSHOT' +version = '2.1.3' apply plugin: 'eclipse' apply plugin: 'java' From a4b235df7d1ebd595cd70199880da83cc8084eb9 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Mon, 28 May 2018 09:56:13 +0200 Subject: [PATCH 11/46] #14 Prepare new reelase version 2.1.3 RC1 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index fa9afa9..774da19 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ group = 'org.scenarioo' -version = '2.1.2-SNAPSHOT' +version = '2.1.3-RC1' apply plugin: 'eclipse' apply plugin: 'java' From 812958a70c921ee6b848824e3f336bd47ee22e45 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Mon, 28 May 2018 09:56:46 +0200 Subject: [PATCH 12/46] #14 Make releasing of scenarioo done automaticaly by Jenkins CI for important branches --- Jenkinsfile | 8 +++++++- docs/release-new-api.md | 32 +++++++++++++++----------------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2249650..dcb1fd4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -22,7 +22,13 @@ timestamps { try { - gradle '-Psign -x signArchives clean build' + if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith("release")) { + // Upload a release or release candidate for important branches + gradle '-Psign -x signArchives clean build uploadArchives' + } else { + // Other branches: no publishing + gradle '-Psign -x signArchives clean build' + } } finally { diff --git a/docs/release-new-api.md b/docs/release-new-api.md index 3a94647..42d8536 100644 --- a/docs/release-new-api.md +++ b/docs/release-new-api.md @@ -8,20 +8,18 @@ The `scenarioo-java` repository has two branches: `develop` for developing the n Precondition: Before considering a release, make sure that the new version is well tested. If you are not 100% sure about the quality of the code, make a release candidate first and test it well in a realistic environment. -## Release to master branch - -1. Finalize the code in the `develop` branch of `scenarioo-java` by setting the correct version number in the `build.gradle` file. This version number must not exist yet in mavem central. Remove `SNAPSHOT` from the version number and add `-RCx` for release candidates where `x` is the RC number. -2. Make sure the build runs on the `develop` branch by running `./gradlew clean build`. Then commit to `develop`. -3. Now checkout the `master` branch and merge `develop` into it, commit. -4. Still on the `master` branch, add a tag with the release version number and push the tag. -5. Checkout `develop` again, change the version in `build.gradle` to the next `x.y.z-SNAPSHOT` version and commit. `x.y` corresponds to the last release version and `z` is incremented by one compared to the last release. - -## Release to maven repository - -1. Checkout the `master` branch tag that contains the release you just made. -2. Follow the steps [Publish release to maven central](upload-to-maven-central.md). -3. Change the version used in the webapplication (repository 'scenarioo' on appropriate branch) to use the newer version and commit. - -## Write release notes - -Write release notes for the new release on GitHub ([here](https://github.com/scenarioo/scenarioo-java/releases)) +1. Finalize the code in the `develop` branch of `scenarioo-java` by setting the correct version number in the `build.gradle` file. This version number must not exist yet in mavem central. Remove `SNAPSHOT` from the version number and add `-RCx` for release candidates where `x` is the RC number for further release candidate testing. +2. Everytime you push to develop our jenkins CI will automatically upload a new version of the release candidate to our sonatype maven repo (see also [Publish release to maven central](upload-to-maven-central.md)). +3. Make sure the changelog.md is updated for the new version + +## Final Release to master branch + +1. recondition: see Prepare Release above. +2. Set the final version number in develop or release branch (without `-SNAPSHOT` or `-RC`) in `build.gradle` and merge it to the develop branch (or the release branch). +3. The Jenkins CI will automatically publish the final release from that branch and under that version number for you to our sonatype maven repository (see also [Publish release to maven central](upload-to-maven-central.md) in case you want to do this manually). +4. Promote the final release to maven central: http://central.sonatype.org/pages/releasing-the-deployment.html +5. Add a tag with the release version number to the commit where you set that version number and push the tag. +6. **Write Release Notes** for the new release on GitHub ([here](https://github.com/scenarioo/scenarioo-java/releases)) +7. Merge the release branch to master. +8. **IMPORTANT - Increase Version to next snapshot version on Develop Branch:** Checkout `develop` again, change the version in `build.gradle` to the next `x.y.z-SNAPSHOT` version and commit. `x.y` corresponds to the last release version and `z` is incremented by one compared to the last release. +9. **Switch Scenarioo Viewer Webapp to newest version:** Go to repo `scenarioo` and change the version of the writer library used to the newest version and commit and push (--> PR to next release branch or to develop). From 9933f8f1afd63501d5241982398d98644f37ade6 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Mon, 28 May 2018 10:03:31 +0200 Subject: [PATCH 13/46] #14 Fix typo in docu --- docs/release-new-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-new-api.md b/docs/release-new-api.md index 42d8536..5cf9b3f 100644 --- a/docs/release-new-api.md +++ b/docs/release-new-api.md @@ -14,7 +14,7 @@ Precondition: Before considering a release, make sure that the new version is we ## Final Release to master branch -1. recondition: see Prepare Release above. +1. Precondition: see Prepare Release above. 2. Set the final version number in develop or release branch (without `-SNAPSHOT` or `-RC`) in `build.gradle` and merge it to the develop branch (or the release branch). 3. The Jenkins CI will automatically publish the final release from that branch and under that version number for you to our sonatype maven repository (see also [Publish release to maven central](upload-to-maven-central.md) in case you want to do this manually). 4. Promote the final release to maven central: http://central.sonatype.org/pages/releasing-the-deployment.html From d7f4ef3f0aa82f79215be6fb007f30b2c737132a Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Wed, 30 May 2018 17:59:24 +0200 Subject: [PATCH 14/46] scenarioo/scenarioo#675 Update link to versioned docu --- docs/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 02bee37..8409971 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -66,4 +66,4 @@ Capture step data from UI tests using one of three strategies ## More ... -* Just study the [Examples](http://scenarioo.org/docs/examples.html), there are a lot of comments in the code, that should help you a lot! +* Just study the [Examples in the Docu](http://scenarioo.org/docs/master/examples.html), there are a lot of comments in the code, that should help you a lot! From c4b3c5051fd8791e13c3db40d71312603ab03632 Mon Sep 17 00:00:00 2001 From: Adrian Herzog Date: Tue, 19 Jun 2018 17:56:51 +0200 Subject: [PATCH 15/46] Fix typo --- src/main/java/org/scenarioo/api/util/IdentifierSanitizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/scenarioo/api/util/IdentifierSanitizer.java b/src/main/java/org/scenarioo/api/util/IdentifierSanitizer.java index 76d7365..c28e387 100644 --- a/src/main/java/org/scenarioo/api/util/IdentifierSanitizer.java +++ b/src/main/java/org/scenarioo/api/util/IdentifierSanitizer.java @@ -3,7 +3,7 @@ import org.scenarioo.api.rules.CharacterChecker; /** - * Use this to make sure your identifiers are compilant with the Scenarioo APIs restrictions that are enforced in the + * Use this to make sure your identifiers are compliant with the Scenarioo APIs restrictions that are enforced in the * {@link CharacterChecker}. */ public class IdentifierSanitizer { From 26b930f47a99086df9b3160325249a79aafe62e0 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:28:10 +0100 Subject: [PATCH 16/46] Enable circleci for scenarioo java. --- .circleci/config.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..3637efc --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,22 @@ +version: 2 +jobs: + build: + + working_directory: ~/repo + + docker: + - image: circleci/openjdk:8-jdk-browsers + + steps: + + - checkout + - run: + name: Clean & install + command: | + mkdir -p test-results + ./gradlew clean build -x test --no-daemon + - run: + name: Tests + command: ./gradlew test + - store_test_results: + path: build/test-results/test From 297918aa39d805809fc80bca859e9e375a8c6c1b Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:34:28 +0100 Subject: [PATCH 17/46] Use different image. --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3637efc..0cc8914 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,7 +5,7 @@ jobs: working_directory: ~/repo docker: - - image: circleci/openjdk:8-jdk-browsers + - image: circleci/openjdk:8-jdk steps: @@ -13,7 +13,7 @@ jobs: - run: name: Clean & install command: | - mkdir -p test-results + mkdir -p test-results¯ ./gradlew clean build -x test --no-daemon - run: name: Tests From dcfc4aed42afa4feba5b6c735397c1c0d974f2c9 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:39:27 +0100 Subject: [PATCH 18/46] Store artifacts. --- .circleci/config.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0cc8914..934b8de 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -13,10 +13,14 @@ jobs: - run: name: Clean & install command: | - mkdir -p test-results¯ + mkdir -p test-results ./gradlew clean build -x test --no-daemon - run: name: Tests command: ./gradlew test - store_test_results: - path: build/test-results/test + path: build/test-results + + - store_artifacts: + path: build/libs + destination: / From 6bac8b213d429b610adec952d145a4977ff404ea Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:46:06 +0100 Subject: [PATCH 19/46] Collect even more artifacts. --- .circleci/config.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 934b8de..a03e4f3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,6 +21,13 @@ jobs: - store_test_results: path: build/test-results + - run: + name: Collect artifacts + command: | + cp -pR build/libs/* artifacts/libs || true + cp -pR build/**/*.xsd artifacts/schema || true + cp -pR LICENSE.txt artifacts/ + - store_artifacts: - path: build/libs + path: artifacts destination: / From 34291a15de6747f26bc8af248a5900b0e4e68bd2 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:48:04 +0100 Subject: [PATCH 20/46] Create dir first. --- .circleci/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index a03e4f3..7002429 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,6 +24,7 @@ jobs: - run: name: Collect artifacts command: | + mkdir -p artifacts/libs cp -pR build/libs/* artifacts/libs || true cp -pR build/**/*.xsd artifacts/schema || true cp -pR LICENSE.txt artifacts/ From d39c93c396c7e2f378bf19df7b72d9032d8ad8c8 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:54:10 +0100 Subject: [PATCH 21/46] Add schema. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7002429..d89aa6a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,7 +26,7 @@ jobs: command: | mkdir -p artifacts/libs cp -pR build/libs/* artifacts/libs || true - cp -pR build/**/*.xsd artifacts/schema || true + cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema || true cp -pR LICENSE.txt artifacts/ - store_artifacts: From 7ef0d582b595d56e1984d73fa0be9f4dbf7865b3 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:55:36 +0100 Subject: [PATCH 22/46] Correct name. --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d89aa6a..50fd70f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,7 +26,7 @@ jobs: command: | mkdir -p artifacts/libs cp -pR build/libs/* artifacts/libs || true - cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema || true + cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema/ || true cp -pR LICENSE.txt artifacts/ - store_artifacts: From 458f99d5eb76a55b5f4d899cfd24486e53a38b6f Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 14:57:08 +0100 Subject: [PATCH 23/46] Create folder first. --- .circleci/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 50fd70f..3b39f0c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,8 +25,9 @@ jobs: name: Collect artifacts command: | mkdir -p artifacts/libs + mkdir -p artifacts/schema cp -pR build/libs/* artifacts/libs || true - cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema/ || true + cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema || true cp -pR LICENSE.txt artifacts/ - store_artifacts: From 392ff6e0bd46156f089625665635ee9bacb935e2 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Wed, 21 Nov 2018 15:20:04 +0100 Subject: [PATCH 24/46] Not needed anymore. --- Jenkinsfile | 45 --------------------------------------------- 1 file changed, 45 deletions(-) delete mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index dcb1fd4..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,45 +0,0 @@ -def gradle(tasks) { - sh "./gradlew --info -s --no-daemon $tasks" -} - -properties([ - pipelineTriggers([ - [$class: 'GitHubPushTrigger'] - ]) -]) - -timestamps { - - node { - - stage('Clean Checkout') { - checkout scm - // Clean build: ensure no unversioned files disturbing the build - sh "git clean -x -d -f" - } - - stage('Build & Test') { - - try { - - if (env.BRANCH_NAME == "master" || env.BRANCH_NAME == "develop" || env.BRANCH_NAME.startsWith("release")) { - // Upload a release or release candidate for important branches - gradle '-Psign -x signArchives clean build uploadArchives' - } else { - // Other branches: no publishing - gradle '-Psign -x signArchives clean build' - } - - } finally { - - junit '**/build/test-results/test/*.xml' - - archiveArtifacts artifacts: 'build/libs/scenarioo-*.jar, build/**/*.xsd, LICENSE.txt, README.md' - - } - - } - - } - -} From 6c5692239c68726ae5a4da794d4937b58ec3ee1a Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Wed, 21 Nov 2018 17:54:34 +0100 Subject: [PATCH 25/46] Update release docu - because publishing of snapshots and releases currently not autoated --- docs/release-new-api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/release-new-api.md b/docs/release-new-api.md index 5cf9b3f..36d8e4c 100644 --- a/docs/release-new-api.md +++ b/docs/release-new-api.md @@ -9,14 +9,14 @@ The `scenarioo-java` repository has two branches: `develop` for developing the n Precondition: Before considering a release, make sure that the new version is well tested. If you are not 100% sure about the quality of the code, make a release candidate first and test it well in a realistic environment. 1. Finalize the code in the `develop` branch of `scenarioo-java` by setting the correct version number in the `build.gradle` file. This version number must not exist yet in mavem central. Remove `SNAPSHOT` from the version number and add `-RCx` for release candidates where `x` is the RC number for further release candidate testing. -2. Everytime you push to develop our jenkins CI will automatically upload a new version of the release candidate to our sonatype maven repo (see also [Publish release to maven central](upload-to-maven-central.md)). +2. You have to manually [Publish the signed snapshot to maven central](upload-to-maven-central.md)) this is currently not automated. 3. Make sure the changelog.md is updated for the new version ## Final Release to master branch 1. Precondition: see Prepare Release above. 2. Set the final version number in develop or release branch (without `-SNAPSHOT` or `-RC`) in `build.gradle` and merge it to the develop branch (or the release branch). -3. The Jenkins CI will automatically publish the final release from that branch and under that version number for you to our sonatype maven repository (see also [Publish release to maven central](upload-to-maven-central.md) in case you want to do this manually). +3. You have to manually [Publish the signed release to maven central](upload-to-maven-central.md)) this is currently not automated. 4. Promote the final release to maven central: http://central.sonatype.org/pages/releasing-the-deployment.html 5. Add a tag with the release version number to the commit where you set that version number and push the tag. 6. **Write Release Notes** for the new release on GitHub ([here](https://github.com/scenarioo/scenarioo-java/releases)) From 9267154c661b53ca72a311185bf04c25b1f87909 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Wed, 21 Nov 2018 19:21:16 +0100 Subject: [PATCH 26/46] #775 Log stacktraces for failures in gradle in circle ci --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3b39f0c..9a1fe62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,10 +14,10 @@ jobs: name: Clean & install command: | mkdir -p test-results - ./gradlew clean build -x test --no-daemon + ./gradlew clean build -x test --no-daemon -s - run: name: Tests - command: ./gradlew test + command: ./gradlew test -s - store_test_results: path: build/test-results From 58526267b823538b6449619376f9048b1d34f56d Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sun, 2 Dec 2018 21:06:21 +0100 Subject: [PATCH 27/46] scenarioo/scenarioo#775 Circle CI pipeline: I love yaml indentations :-) --- .circleci/config.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a1fe62..df8dbb2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,12 +12,12 @@ jobs: - checkout - run: name: Clean & install - command: | - mkdir -p test-results - ./gradlew clean build -x test --no-daemon -s + command: ./gradlew clean build -x test --no-daemon -s + - run: name: Tests command: ./gradlew test -s + - store_test_results: path: build/test-results @@ -26,6 +26,7 @@ jobs: command: | mkdir -p artifacts/libs mkdir -p artifacts/schema + cp -pR build/test-results artifacts || true cp -pR build/libs/* artifacts/libs || true cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema || true cp -pR LICENSE.txt artifacts/ From 9b0b12a5bae6ee15b495690cbb77dbf834d2604f Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sun, 2 Dec 2018 21:09:49 +0100 Subject: [PATCH 28/46] Revert "scenarioo/scenarioo#775 Circle CI pipeline: I love yaml indentations :-)" accidentialy commited This reverts commit 5852626 --- .circleci/config.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index df8dbb2..9a1fe62 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,12 +12,12 @@ jobs: - checkout - run: name: Clean & install - command: ./gradlew clean build -x test --no-daemon -s - + command: | + mkdir -p test-results + ./gradlew clean build -x test --no-daemon -s - run: name: Tests command: ./gradlew test -s - - store_test_results: path: build/test-results @@ -26,7 +26,6 @@ jobs: command: | mkdir -p artifacts/libs mkdir -p artifacts/schema - cp -pR build/test-results artifacts || true cp -pR build/libs/* artifacts/libs || true cp -pR build/resources/main/scenarioo-schemas/*.xsd artifacts/schema || true cp -pR LICENSE.txt artifacts/ From 771b6ab020cd08c3dae0359be6fee962ebe2e428 Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sat, 22 Dec 2018 15:21:08 +0100 Subject: [PATCH 29/46] #775 Remove probably not needed mkdir for test-results dir --- .circleci/config.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9a1fe62..fc60b08 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,9 +12,7 @@ jobs: - checkout - run: name: Clean & install - command: | - mkdir -p test-results - ./gradlew clean build -x test --no-daemon -s + command: ./gradlew clean build -x test --no-daemon -s - run: name: Tests command: ./gradlew test -s From 42b8152a55ad4f831322bd15764aee1db880338f Mon Sep 17 00:00:00 2001 From: Rolf Bruderer Date: Sat, 22 Dec 2018 15:23:37 +0100 Subject: [PATCH 30/46] scenarioo/scenarioo#775 Cleanup Circle CI config --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index fc60b08..80a6f4f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,12 +10,15 @@ jobs: steps: - checkout + - run: name: Clean & install command: ./gradlew clean build -x test --no-daemon -s + - run: name: Tests command: ./gradlew test -s + - store_test_results: path: build/test-results From d02ef62390c2b0082f6305fd6127cd2c8f8da0c6 Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Wed, 23 Jan 2019 13:47:18 +0100 Subject: [PATCH 31/46] #20 migrate tests to JUnit 5 without using Java 8 language features. --- build.gradle | 10 +- .../scenarioo/api/ForbiddenSlashesTest.java | 56 +++--- .../org/scenarioo/api/SaveScreenshotTest.java | 24 +-- .../api/ScenarioDocuWriterAndReaderTest.java | 175 +++++++++--------- .../java/org/scenarioo/api/TestConstants.java | 2 +- .../api/rules/CharacterCheckerTest.java | 26 +-- .../api/rules/DetailsCheckerTest.java | 14 +- .../api/util/IdentifierSanitizerTest.java | 14 +- .../model/docu/entities/LabelsTest.java | 16 +- 9 files changed, 172 insertions(+), 165 deletions(-) diff --git a/build.gradle b/build.gradle index 774da19..e129016 100644 --- a/build.gradle +++ b/build.gradle @@ -41,9 +41,17 @@ dependencies { compile 'commons-io:commons-io:1.3.2' compile 'commons-codec:commons-codec:1.2' compile 'log4j:log4j:1.2.17' - testCompile 'junit:junit:4.11' + testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' + testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.3.2' } +test { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed" + } +} task javadocJar(type: Jar) { classifier = 'javadoc' diff --git a/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java b/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java index 690d16a..14256e7 100644 --- a/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java +++ b/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java @@ -1,15 +1,15 @@ package org.scenarioo.api; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import static org.scenarioo.api.TestConstants.*; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.scenarioo.api.exception.IllegalCharacterException; import org.scenarioo.model.docu.entities.Page; import org.scenarioo.model.docu.entities.Scenario; @@ -37,7 +37,7 @@ *
  • object name
  • * */ -public class ForbiddenSlashesTest { +class ForbiddenSlashesTest { private static final String ILLEGAL_NAME = "/illegal"; private static final String LEGAL_NAME = "legal"; @@ -46,8 +46,8 @@ public class ForbiddenSlashesTest { private static ScenarioDocuWriter scenarioDocuWriter; private static ScenarioDocuReader scenarioDocuReader; - @BeforeClass - public static void beforeClass() { + @BeforeAll + static void beforeClass() { if (!dataDirectory.exists()) { dataDirectory.mkdirs(); } @@ -55,13 +55,13 @@ public static void beforeClass() { scenarioDocuReader = new ScenarioDocuReader(dataDirectory); } - @AfterClass - public static void cleanup() { + @AfterAll + static void cleanup() { deleteDirectory(TEST_ROOT_DIRECTORY); } @Test - public void creatingAScenarioDocuWriter_withAnIllegalBranchName_resultsInAnException() { + void creatingAScenarioDocuWriter_withAnIllegalBranchName_resultsInAnException() { try { new ScenarioDocuWriter(dataDirectory, ILLEGAL_NAME, LEGAL_NAME); fail(); @@ -71,7 +71,7 @@ public void creatingAScenarioDocuWriter_withAnIllegalBranchName_resultsInAnExcep } @Test - public void creatingAScenarioDocuWriter_withAnIllegalBuildName_resultsInAnException() { + void creatingAScenarioDocuWriter_withAnIllegalBuildName_resultsInAnException() { try { new ScenarioDocuWriter(dataDirectory, LEGAL_NAME, ILLEGAL_NAME); fail(); @@ -81,7 +81,7 @@ public void creatingAScenarioDocuWriter_withAnIllegalBuildName_resultsInAnExcept } @Test - public void writingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { + void writingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { try { scenarioDocuWriter.saveUseCase(getUseCaseWithIllegalName()); fail(); @@ -91,7 +91,7 @@ public void writingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { } @Test - public void writingAScenario_withAnIllegalUseCaseName_resultsInAnException() { + void writingAScenario_withAnIllegalUseCaseName_resultsInAnException() { try { scenarioDocuWriter.saveScenario(ILLEGAL_NAME, getScenarioWithName(LEGAL_NAME)); fail(); @@ -101,7 +101,7 @@ public void writingAScenario_withAnIllegalUseCaseName_resultsInAnException() { } @Test - public void writingAScenario_withAnIllegalScenarioName_resultsInAnException() { + void writingAScenario_withAnIllegalScenarioName_resultsInAnException() { try { scenarioDocuWriter.saveScenario(LEGAL_NAME, getScenarioWithName(ILLEGAL_NAME)); fail(); @@ -111,7 +111,7 @@ public void writingAScenario_withAnIllegalScenarioName_resultsInAnException() { } @Test - public void writingAStep_withAnIllegalUseCaseName_resultsInAnException() { + void writingAStep_withAnIllegalUseCaseName_resultsInAnException() { try { scenarioDocuWriter.saveStep(ILLEGAL_NAME, LEGAL_NAME, getStepWithPageName(LEGAL_NAME)); fail(); @@ -121,7 +121,7 @@ public void writingAStep_withAnIllegalUseCaseName_resultsInAnException() { } @Test - public void writingAStep_withAnIllegalScenarioName_resultsInAnException() { + void writingAStep_withAnIllegalScenarioName_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, ILLEGAL_NAME, getStepWithPageName(LEGAL_NAME)); fail(); @@ -131,7 +131,7 @@ public void writingAStep_withAnIllegalScenarioName_resultsInAnException() { } @Test - public void writingAStep_withAnIllegalPageName_resultsInAnException() { + void writingAStep_withAnIllegalPageName_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithPageName(ILLEGAL_NAME)); fail(); @@ -141,7 +141,7 @@ public void writingAStep_withAnIllegalPageName_resultsInAnException() { } @Test - public void writingAStep_withAnIllegalObjectTypeInMetadata_resultsInAnException() { + void writingAStep_withAnIllegalObjectTypeInMetadata_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInMetadata()); fail(); @@ -151,7 +151,7 @@ public void writingAStep_withAnIllegalObjectTypeInMetadata_resultsInAnException( } @Test - public void writingAStep_withAnIllegalObjectNameInMetadata_resultsInAnException() { + void writingAStep_withAnIllegalObjectNameInMetadata_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInMetadata()); fail(); @@ -161,7 +161,7 @@ public void writingAStep_withAnIllegalObjectNameInMetadata_resultsInAnException( } @Test - public void writingAStep_withAnIllegalObjectTypeInStepDescription_resultsInAnException() { + void writingAStep_withAnIllegalObjectTypeInStepDescription_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInStepDescription()); fail(); @@ -171,7 +171,7 @@ public void writingAStep_withAnIllegalObjectTypeInStepDescription_resultsInAnExc } @Test - public void writingAStep_withAnIllegalObjectNameInStepDescription_resultsInAnException() { + void writingAStep_withAnIllegalObjectNameInStepDescription_resultsInAnException() { try { scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInStepDescription()); fail(); @@ -181,7 +181,7 @@ public void writingAStep_withAnIllegalObjectNameInStepDescription_resultsInAnExc } @Test - public void readingAUseCase_withAnIllegalBranchName_resultsInAnException() { + void readingAUseCase_withAnIllegalBranchName_resultsInAnException() { try { scenarioDocuReader.loadUsecase(ILLEGAL_NAME, LEGAL_NAME, LEGAL_NAME); fail(); @@ -191,7 +191,7 @@ public void readingAUseCase_withAnIllegalBranchName_resultsInAnException() { } @Test - public void readingAUseCase_withAnIllegalBuildName_resultsInAnException() { + void readingAUseCase_withAnIllegalBuildName_resultsInAnException() { try { scenarioDocuReader.loadUsecase(LEGAL_NAME, ILLEGAL_NAME, LEGAL_NAME); fail(); @@ -201,7 +201,7 @@ public void readingAUseCase_withAnIllegalBuildName_resultsInAnException() { } @Test - public void readingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { + void readingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { try { scenarioDocuReader.loadUsecase(LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME); fail(); @@ -211,7 +211,7 @@ public void readingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { } @Test - public void readingAScenario_withAnIllegalScenarioName_resultsInAnException() { + void readingAScenario_withAnIllegalScenarioName_resultsInAnException() { try { scenarioDocuReader.loadScenario(LEGAL_NAME, LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME); fail(); @@ -221,18 +221,18 @@ public void readingAScenario_withAnIllegalScenarioName_resultsInAnException() { } @Test - public void readingAStep_withAnIllegalPageName_works() { + void readingAStep_withAnIllegalPageName_works() { // The server takes care of these illegal page names and sanitizes them // TODO [#331] Implement this test } @Test - public void readingAStep_withAnIllegalObjectType_isAllowedButDiscouraged() { + void readingAStep_withAnIllegalObjectType_isAllowedButDiscouraged() { // TODO [#330] Maybe we should also sanitize object names and object types as we do it for page names } @Test - public void readingAStep_withAnIllegalObjectName_isAllowedButDiscouraged() { + void readingAStep_withAnIllegalObjectName_isAllowedButDiscouraged() { // TODO [#330] Maybe we should also sanitize object names and object types as we do it for page names } diff --git a/src/test/java/org/scenarioo/api/SaveScreenshotTest.java b/src/test/java/org/scenarioo/api/SaveScreenshotTest.java index ff5f389..5bb628a 100644 --- a/src/test/java/org/scenarioo/api/SaveScreenshotTest.java +++ b/src/test/java/org/scenarioo/api/SaveScreenshotTest.java @@ -6,20 +6,20 @@ import java.io.IOException; import org.apache.commons.io.FileUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -public class SaveScreenshotTest { +class SaveScreenshotTest { private static final String pngFileName = "/scenarioo-icon-unittest.png"; private static byte[] imageAsByteArray; private ScenarioDocuWriter writer; - @BeforeClass - public static void loadImage() { + @BeforeAll + static void loadImage() { try { imageAsByteArray = FileUtils.readFileToByteArray(new File(SaveScreenshotTest.class.getResource(pngFileName) .getFile())); @@ -28,14 +28,14 @@ public static void loadImage() { } } - @Before - public void setUp() { + @BeforeEach + void setUp() { TEST_ROOT_DIRECTORY.mkdirs(); writer = new ScenarioDocuWriter(TEST_ROOT_DIRECTORY, TEST_BRANCH_NAME, TEST_BUILD_NAME); } @Test - public void savePngScreenshot() { + void savePngScreenshot() { writer.saveScreenshotAsPng(TEST_CASE_NAME, TEST_SCENARIO_NAME, TEST_STEP_INDEX, imageAsByteArray); writer.flush(); @@ -49,12 +49,12 @@ private void assertStoredFileContentEqualsOriginalImage() { try { fileAsByteArray = FileUtils.readFileToByteArray(file); } catch (IOException e) { - Assert.fail("Could not read file " + file); + Assertions.fail("Could not read file " + file); e.printStackTrace(); return; } - Assert.assertArrayEquals(imageAsByteArray, fileAsByteArray); + Assertions.assertArrayEquals(imageAsByteArray, fileAsByteArray); } } diff --git a/src/test/java/org/scenarioo/api/ScenarioDocuWriterAndReaderTest.java b/src/test/java/org/scenarioo/api/ScenarioDocuWriterAndReaderTest.java index e029f90..5e6ff23 100644 --- a/src/test/java/org/scenarioo/api/ScenarioDocuWriterAndReaderTest.java +++ b/src/test/java/org/scenarioo/api/ScenarioDocuWriterAndReaderTest.java @@ -22,7 +22,7 @@ package org.scenarioo.api; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import static org.scenarioo.api.TestConstants.*; import java.io.File; @@ -30,9 +30,9 @@ import java.util.Date; import org.apache.commons.io.FileUtils; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.scenarioo.api.files.ScenarioDocuFiles; import org.scenarioo.model.docu.entities.Branch; import org.scenarioo.model.docu.entities.Build; @@ -55,7 +55,7 @@ /** * Some smoke tests for the Scenarioo generator API. */ -public class ScenarioDocuWriterAndReaderTest { +class ScenarioDocuWriterAndReaderTest { private static final String TEST_DETAILS_VERSION_KEY = "version"; @@ -70,16 +70,16 @@ public class ScenarioDocuWriterAndReaderTest { */ private ScenarioDocuFiles docuFiles; - @Before - public void setUp() { + @BeforeEach + void setUp() { TEST_ROOT_DIRECTORY.mkdirs(); writer = new ScenarioDocuWriter(TEST_ROOT_DIRECTORY, TEST_BRANCH_NAME, TEST_BUILD_NAME); reader = new ScenarioDocuReader(TEST_ROOT_DIRECTORY); docuFiles = new ScenarioDocuFiles(TEST_ROOT_DIRECTORY); } - @AfterClass - public static void tearDown() { + @AfterAll + static void tearDown() { deleteDirectory(TEST_ROOT_DIRECTORY); } @@ -92,7 +92,7 @@ private static void deleteDirectory(final File testRootDirectory) { } @Test - public void write_and_read_branch_description() { + void write_and_read_branch_description() { // GIVEN: a typical branch Branch branch = new Branch(); @@ -105,13 +105,13 @@ public void write_and_read_branch_description() { // THEN: the branch can be loaded successfully and correctly Branch branchFromFile = reader.loadBranch(TEST_BRANCH_NAME); - assertEquals("expected branch name", TEST_BRANCH_NAME, branchFromFile.getName()); - assertEquals("expected branch description", branch.getDescription(), branchFromFile.getDescription()); + assertEquals(TEST_BRANCH_NAME, branchFromFile.getName(), "expected branch name"); + assertEquals(branch.getDescription(), branchFromFile.getDescription(), "expected branch description"); } @Test - public void write_and_read_build_description() { + void write_and_read_build_description() { // GIVEN: a typical build Build build = new Build(); @@ -127,17 +127,17 @@ public void write_and_read_build_description() { // THEN: the build can be loaded successfully and correctly Build buildFromFile = reader.loadBuild(TEST_BRANCH_NAME, TEST_BUILD_NAME); - assertEquals("expected build name", TEST_BUILD_NAME, buildFromFile.getName()); - assertEquals("expected date", build.getDate(), buildFromFile.getDate()); - assertEquals("expected revision", build.getRevision(), buildFromFile.getRevision()); - assertEquals("expected state", build.getStatus(), buildFromFile.getStatus()); - assertEquals("expected details properties", build.getDetails().getProperties(), buildFromFile.getDetails() - .getProperties()); + assertEquals(TEST_BUILD_NAME, buildFromFile.getName(), "expected build name"); + assertEquals(build.getDate(), buildFromFile.getDate(), "expected date"); + assertEquals(build.getRevision(), buildFromFile.getRevision(), "expected revision"); + assertEquals(build.getStatus(), buildFromFile.getStatus(), "expected state"); + assertEquals(build.getDetails().getProperties(), buildFromFile.getDetails() + .getProperties(), "expected details properties"); } @Test - public void write_and_read_case_description() { + void write_and_read_case_description() { // GIVEN: a typical use case UseCase usecase = new UseCase(); @@ -153,16 +153,16 @@ public void write_and_read_case_description() { // THEN: the usecase can be loaded successfully and correctly UseCase usecaseFromFile = reader.loadUsecase(TEST_BRANCH_NAME, TEST_BUILD_NAME, TEST_CASE_NAME); - assertEquals("expected case name", TEST_CASE_NAME, usecaseFromFile.getName()); - assertEquals("expected case desription", usecase.getDescription(), usecaseFromFile.getDescription()); - assertEquals("expected case state", usecase.getStatus(), usecaseFromFile.getStatus()); - assertEquals("expected details properties", usecase.getDetails().getProperties(), usecaseFromFile.getDetails() - .getProperties()); + assertEquals(TEST_CASE_NAME, usecaseFromFile.getName(), "expected case name"); + assertEquals(usecase.getDescription(), usecaseFromFile.getDescription(), "expected case desription"); + assertEquals(usecase.getStatus(), usecaseFromFile.getStatus(), "expected case state"); + assertEquals(usecase.getDetails().getProperties(), usecaseFromFile.getDetails() + .getProperties(), "expected details properties"); assertExpectedLabels(usecaseFromFile.getLabels(), "label1", "label2"); } @Test - public void write_and_read_scenario_description() { + void write_and_read_scenario_description() { // GIVEN: a typical scenario Scenario scenario = new Scenario(); @@ -179,11 +179,11 @@ public void write_and_read_scenario_description() { // THEN: the scenario can be loaded successfully and correctly Scenario scenarioFromFile = reader.loadScenario(TEST_BRANCH_NAME, TEST_BUILD_NAME, TEST_CASE_NAME, TEST_SCENARIO_NAME); - assertEquals("expected scneario name", TEST_SCENARIO_NAME, scenarioFromFile.getName()); - assertEquals("expected scenario desription", scenario.getDescription(), scenarioFromFile.getDescription()); - assertEquals("expected scenario state", scenario.getStatus(), scenarioFromFile.getStatus()); - assertEquals("expected scenario details properties", scenario.getDetails().getProperties(), scenarioFromFile - .getDetails().getProperties()); + assertEquals(TEST_SCENARIO_NAME, scenarioFromFile.getName(), "expected scneario name"); + assertEquals(scenario.getDescription(), scenarioFromFile.getDescription(), "expected scenario desription"); + assertEquals(scenario.getStatus(), scenarioFromFile.getStatus(), "expected scenario state"); + assertEquals(scenario.getDetails().getProperties(), scenarioFromFile + .getDetails().getProperties(), "expected scenario details properties"); assertExpectedLabels(scenarioFromFile.getLabels(), "label1", "label2"); } @@ -193,7 +193,7 @@ public void write_and_read_scenario_description() { * correctly. */ @Test - public void write_and_read_step_minimal() { + void write_and_read_step_minimal() { // GIVEN: a typical step with only minimal required fields beeing set Step step = new Step(); @@ -209,16 +209,15 @@ public void write_and_read_step_minimal() { // THEN: the step can be loaded successfully and correctly Step stepFromFile = reader.loadStep(TEST_BRANCH_NAME, TEST_BUILD_NAME, TEST_CASE_NAME, TEST_SCENARIO_NAME, TEST_STEP_INDEX); - assertEquals("expected step index", TEST_STEP_INDEX, stepFromFile.getStepDescription().getIndex()); - assertEquals("expected empty step title", "", stepFromFile.getStepDescription().getTitle()); - assertEquals("expected no status", "", stepFromFile.getStepDescription().getStatus()); - assertEquals("expected no step step description details properties", 0, stepFromFile.getStepDescription() - .getDetails() - .getProperties().size()); - assertEquals("expected no step metadata details properties", 0, stepFromFile.getMetadata().getDetails() - .getProperties().size()); - assertEquals("expected no labels", 0, stepFromFile.getStepDescription().getLabels().size()); - assertNull("expected no page", stepFromFile.getPage()); + assertEquals(TEST_STEP_INDEX, stepFromFile.getStepDescription().getIndex(), "expected step index"); + assertEquals("", stepFromFile.getStepDescription().getTitle(), "expected empty step title"); + assertEquals("", stepFromFile.getStepDescription().getStatus(), "expected no status"); + assertEquals(0, stepFromFile.getStepDescription().getDetails().getProperties().size(), + "expected no step step description details properties"); + assertEquals(0, stepFromFile.getMetadata().getDetails().getProperties().size(), + "expected no step metadata details properties"); + assertEquals(0, stepFromFile.getStepDescription().getLabels().size(), "expected no labels"); + assertNull(stepFromFile.getPage(), "expected no page"); } @@ -226,7 +225,7 @@ public void write_and_read_step_minimal() { * This test tests also all optional fields of a step, that they can be set and are loaded again properly. */ @Test - public void write_and_read_step_with_major_optional_fields() { + void write_and_read_step_with_major_optional_fields() { // GIVEN: a typical step with all major optional fields also beeing set Step step = new Step(); @@ -253,21 +252,22 @@ public void write_and_read_step_with_major_optional_fields() { // THEN: the step can be loaded successfully and correctly Step stepFromFile = reader.loadStep(TEST_BRANCH_NAME, TEST_BUILD_NAME, TEST_CASE_NAME, TEST_SCENARIO_NAME, TEST_STEP_INDEX); - assertEquals("expected step name", TEST_STEP_INDEX, stepFromFile.getStepDescription().getIndex()); - assertEquals("expected step desription", step.getStepDescription().getTitle(), stepFromFile - .getStepDescription().getTitle()); - assertEquals("expected step status", step.getStepDescription().getStatus(), stepFromFile.getStepDescription() - .getStatus()); - assertEquals("expected step description details properties", step.getStepDescription().getDetails() - .getProperties(), stepFromFile.getStepDescription().getDetails().getProperties()); + assertEquals(TEST_STEP_INDEX, stepFromFile.getStepDescription().getIndex(), "expected step name"); + assertEquals(step.getStepDescription().getTitle(), stepFromFile.getStepDescription().getTitle(), + "expected step desription"); + assertEquals(step.getStepDescription().getStatus(), stepFromFile.getStepDescription().getStatus(), + "expected step status"); + assertEquals(step.getStepDescription().getDetails().getProperties(), + stepFromFile.getStepDescription().getDetails().getProperties(), + "expected step description details properties"); assertExpectedLabels(stepFromFile.getStepDescription().getLabels(), "label1", "label2"); - assertEquals("expected step html", step.getHtml().getHtmlSource(), stepFromFile.getHtml().getHtmlSource()); + assertEquals(step.getHtml().getHtmlSource(), stepFromFile.getHtml().getHtmlSource(), "expected step html"); Page pageFromFile = stepFromFile.getPage(); - assertEquals("expected step page name", step.getPage().getName(), pageFromFile.getName()); + assertEquals(step.getPage().getName(), pageFromFile.getName(), "expected step page name"); assertExpectedLabels(pageFromFile.getLabels(), "page-label1", "page-label2"); - assertEquals("expected step visible text", "just some page text", stepFromFile.getMetadata().getVisibleText()); - assertEquals("expected step metadata details properties", step.getMetadata().getDetails().getProperties(), - stepFromFile.getMetadata().getDetails().getProperties()); + assertEquals("just some page text", stepFromFile.getMetadata().getVisibleText(), "expected step visible text"); + assertEquals(step.getMetadata().getDetails().getProperties(), + stepFromFile.getMetadata().getDetails().getProperties(), "expected step metadata details properties"); } @@ -275,7 +275,7 @@ public void write_and_read_step_with_major_optional_fields() { * Test adding screen annotations to a step (which is optional too) */ @Test - public void write_and_read_step_with_screen_annotations() { + void write_and_read_step_with_screen_annotations() { // GIVEN: a typical step with only minimal required fields beeing set and two screen annotations Step step = new Step(); @@ -293,7 +293,7 @@ public void write_and_read_step_with_screen_annotations() { // THEN: the step can be loaded successfully and correctly Step stepFromFile = reader.loadStep(TEST_BRANCH_NAME, TEST_BUILD_NAME, TEST_CASE_NAME, TEST_SCENARIO_NAME, TEST_STEP_INDEX); - assertEquals("expected number of screen annotations", 2, stepFromFile.getScreenAnnotations().size()); + assertEquals(2, stepFromFile.getScreenAnnotations().size(), "expected number of screen annotations"); assertMinimalScreenAnnotation(stepFromFile.getScreenAnnotations().get(0)); assertFullScreenAnnotation(stepFromFile.getScreenAnnotations().get(1)); @@ -303,7 +303,7 @@ public void write_and_read_step_with_screen_annotations() { * Tests writing and reading of a scenario docu file containing some basic collections that need to be supported. */ @Test - public void write_and_read_generic_collections_in_details() { + void write_and_read_generic_collections_in_details() { // GIVEN: any object containing collections in details Scenario scenario = new Scenario(); @@ -342,7 +342,7 @@ public void write_and_read_generic_collections_in_details() { * written. */ @Test - public void async_write_of_multiple_files_and_flush() { + void async_write_of_multiple_files_and_flush() { // GIVEN: a lot of large steps to write, that have not yet been written Step[] steps = new Step[10]; @@ -373,17 +373,17 @@ private ScreenAnnotation createMinimalScreenAnnotation() { } private void assertMinimalScreenAnnotation(final ScreenAnnotation screenAnnotation) { - assertEquals("Expected x coordinate", 100, screenAnnotation.getRegion().getX()); - assertEquals("Expected y coordinate", 150, screenAnnotation.getRegion().getY()); - assertEquals("Expected width", 90, screenAnnotation.getRegion().getWidth()); - assertEquals("Expected height", 10, screenAnnotation.getRegion().getHeight()); - assertEquals("Expected no text", "", screenAnnotation.getScreenText()); - assertEquals("Expected no description", "", screenAnnotation.getDescription()); - assertEquals("Expected default style", screenAnnotation.getStyle(), ScreenAnnotationStyle.DEFAULT); - assertNull("Expected no click action", screenAnnotation.getClickAction()); - assertNull("Expected no click action url", screenAnnotation.getClickActionUrl()); - assertNull("Expected no click action text", screenAnnotation.getClickActionText()); - assertEquals("Expected no details", 0, screenAnnotation.getDetails().size()); + assertEquals(100, screenAnnotation.getRegion().getX(), "Expected x coordinate"); + assertEquals(150, screenAnnotation.getRegion().getY(), "Expected y coordinate"); + assertEquals(90, screenAnnotation.getRegion().getWidth(), "Expected width"); + assertEquals(10, screenAnnotation.getRegion().getHeight(), "Expected height"); + assertEquals("", screenAnnotation.getScreenText(), "Expected no text"); + assertEquals("", screenAnnotation.getDescription(), "Expected no description"); + assertEquals(screenAnnotation.getStyle(), ScreenAnnotationStyle.DEFAULT, "Expected default style"); + assertNull(screenAnnotation.getClickAction(), "Expected no click action"); + assertNull(screenAnnotation.getClickActionUrl(), "Expected no click action url"); + assertNull(screenAnnotation.getClickActionText(), "Expected no click action text"); + assertEquals(0, screenAnnotation.getDetails().size(), "Expected no details"); } /** @@ -403,18 +403,18 @@ private ScreenAnnotation createFullScreenAnnotation() { } private void assertFullScreenAnnotation(final ScreenAnnotation screenAnnotation) { - assertEquals("Expected x coordinate", 200, screenAnnotation.getRegion().getX()); - assertEquals("Expected y coordinate", 150, screenAnnotation.getRegion().getY()); - assertEquals("Expected width", 90, screenAnnotation.getRegion().getWidth()); - assertEquals("Expected height", 20, screenAnnotation.getRegion().getHeight()); - assertEquals("Expected screen text", "just a text", screenAnnotation.getScreenText()); - assertEquals("Expected title", "title", screenAnnotation.getTitle()); - assertEquals("Expected description", "just a description", screenAnnotation.getDescription()); - assertEquals("Expected style", ScreenAnnotationStyle.CLICK, screenAnnotation.getStyle()); - assertEquals("Expected clickAction", ScreenAnnotationClickAction.TO_URL, screenAnnotation.getClickAction()); - assertEquals("Expected clickActionUrl", "http://just-an-url.com", screenAnnotation.getClickActionUrl()); - assertEquals("Expected clickActionText", "just a click action text", screenAnnotation.getClickActionText()); - assertEquals("Expected details", 1, screenAnnotation.getDetails().size()); + assertEquals(200, screenAnnotation.getRegion().getX(), "Expected x coordinate"); + assertEquals(150, screenAnnotation.getRegion().getY(), "Expected y coordinate"); + assertEquals(90, screenAnnotation.getRegion().getWidth(), "Expected width"); + assertEquals(20, screenAnnotation.getRegion().getHeight(), "Expected height"); + assertEquals("just a text", screenAnnotation.getScreenText(), "Expected screen text"); + assertEquals("title", screenAnnotation.getTitle(), "Expected title"); + assertEquals("just a description", screenAnnotation.getDescription(), "Expected description"); + assertEquals(ScreenAnnotationStyle.CLICK, screenAnnotation.getStyle(), "Expected style"); + assertEquals(ScreenAnnotationClickAction.TO_URL, screenAnnotation.getClickAction(), "Expected clickAction"); + assertEquals("http://just-an-url.com", screenAnnotation.getClickActionUrl(), "Expected clickActionUrl"); + assertEquals("just a click action text", screenAnnotation.getClickActionText(), "Expected clickActionText"); + assertEquals(1, screenAnnotation.getDetails().size(), "Expected details"); } private Step createBigDataStepForLoadTestAsyncWriting(final int index) { @@ -461,9 +461,8 @@ private StepHtml createBigHtml() { builder.append(""); builder.append("

    This is just a dummy html code with lot of content to generate a lot of big data to write for load testing.

    "); for (int i = 0; i < 1000; i++) { - builder.append("

    This is just a dummy html code with lot of content to generate a lot of big data to write for load testing.
    "); + builder.append("
    This is just a dummy html code with lot of content to generate a lot of big data to write for load testing.
    "); } builder.append(""); @@ -474,10 +473,10 @@ private StepHtml createBigHtml() { } private void assertExpectedLabels(final Labels labels, final String... expectedLabels) { - assertEquals("Expected number of labels", expectedLabels.length, labels.size()); + assertEquals(expectedLabels.length, labels.size(), "Expected number of labels"); for (String expectedLabel : expectedLabels) { - assertTrue("expected label '" + expectedLabel + "' to be contained in labels.", - labels.contains(expectedLabel)); + assertTrue(labels.contains(expectedLabel), + "expected label '" + expectedLabel + "' to be contained in labels."); } } } diff --git a/src/test/java/org/scenarioo/api/TestConstants.java b/src/test/java/org/scenarioo/api/TestConstants.java index 49fdc89..ab87264 100644 --- a/src/test/java/org/scenarioo/api/TestConstants.java +++ b/src/test/java/org/scenarioo/api/TestConstants.java @@ -2,7 +2,7 @@ import java.io.File; -public class TestConstants { +class TestConstants { public static final File TEST_ROOT_DIRECTORY = new File("tmpScenarioDocuUnitTestFiles"); public static final String TEST_BRANCH_NAME = "testBranch"; diff --git a/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java b/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java index 792841a..ad36d50 100644 --- a/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java +++ b/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java @@ -1,24 +1,24 @@ package org.scenarioo.api.rules; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.scenarioo.api.exception.IllegalCharacterException; -public class CharacterCheckerTest { +class CharacterCheckerTest { @Test - public void checkIdentifier_nullIdentifiers_areValid() { + void checkIdentifier_nullIdentifiers_areValid() { CharacterChecker.checkIdentifier(null); } @Test - public void checkIdentifier_stringsWithoutASlashOrBackslash_areValid() { + void checkIdentifier_stringsWithoutASlashOrBackslash_areValid() { CharacterChecker.checkIdentifier("Some5!*%&?+String"); } @Test - public void checkIdentifier_stringsWithASlash_resultInAnException() { + void checkIdentifier_stringsWithASlash_resultInAnException() { try { CharacterChecker.checkIdentifier("abc/def"); fail(); @@ -28,7 +28,7 @@ public void checkIdentifier_stringsWithASlash_resultInAnException() { } @Test - public void checkIdentifier_stringsWithABackslash_resultInAnException() { + void checkIdentifier_stringsWithABackslash_resultInAnException() { try { CharacterChecker.checkIdentifier("abc\\def"); fail(); @@ -38,13 +38,13 @@ public void checkIdentifier_stringsWithABackslash_resultInAnException() { } @Test - public void checkIdentifier_forValidIdentifiers_returnsTheIdentifier() { + void checkIdentifier_forValidIdentifiers_returnsTheIdentifier() { String identifier = "valid"; assertEquals(identifier, CharacterChecker.checkIdentifier(identifier)); } @Test - public void checkLabel_aNullLabel_resultsInAnException() { + void checkLabel_aNullLabel_resultsInAnException() { try { CharacterChecker.checkLabel(null); fail(); @@ -54,12 +54,12 @@ public void checkLabel_aNullLabel_resultsInAnException() { } @Test - public void checkLabel_aLabelContainingAllTypesOfAllowedCharacters_passesTheCheck() { + void checkLabel_aLabelContainingAllTypesOfAllowedCharacters_passesTheCheck() { CharacterChecker.checkLabel("abc_DEF-012 3456789"); } @Test - public void checkLabel_aLabelWithASlash_resultsInAnException() { + void checkLabel_aLabelWithASlash_resultsInAnException() { try { CharacterChecker.checkLabel("abc/def"); fail(); @@ -69,7 +69,7 @@ public void checkLabel_aLabelWithASlash_resultsInAnException() { } @Test - public void checkLabel_aLabelWithAnUmlaut_resultsInAnException() { + void checkLabel_aLabelWithAnUmlaut_resultsInAnException() { try { CharacterChecker.checkLabel("äuäää"); fail(); @@ -79,7 +79,7 @@ public void checkLabel_aLabelWithAnUmlaut_resultsInAnException() { } @Test - public void checkLabel_forValidLabels_returnsTheLabel() { + void checkLabel_forValidLabels_returnsTheLabel() { String label = "valid"; assertEquals(label, CharacterChecker.checkLabel(label)); } diff --git a/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java b/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java index bdd5c8e..99cec24 100644 --- a/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java +++ b/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java @@ -1,29 +1,29 @@ package org.scenarioo.api.rules; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.scenarioo.api.exception.IllegalCharacterException; import org.scenarioo.model.docu.entities.generic.Details; import org.scenarioo.model.docu.entities.generic.ObjectDescription; -public class DetailsCheckerTest { +class DetailsCheckerTest { private static final String ILLEGAL_IDENTIFIER = "/illegal"; private static final String LEGAL_IDENTIFIER = "legal"; @Test - public void ifDetailsIsNull_theCheckPasses() { + void ifDetailsIsNull_theCheckPasses() { DetailsChecker.checkIdentifiers(null); } @Test - public void ifAllIdentifiersAreValid_theCheckPasses() { + void ifAllIdentifiersAreValid_theCheckPasses() { DetailsChecker.checkIdentifiers(getDetailsWithValidIdentifiers()); } @Test - public void ifThereIsAnInvalidObjectType_anExceptionIsThrown() { + void ifThereIsAnInvalidObjectType_anExceptionIsThrown() { try { DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectType()); fail(); @@ -33,7 +33,7 @@ public void ifThereIsAnInvalidObjectType_anExceptionIsThrown() { } @Test - public void ifThereIsAnInvalidObjectName_anExceptionIsThrown() { + void ifThereIsAnInvalidObjectName_anExceptionIsThrown() { try { DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectName()); fail(); diff --git a/src/test/java/org/scenarioo/api/util/IdentifierSanitizerTest.java b/src/test/java/org/scenarioo/api/util/IdentifierSanitizerTest.java index 55719ea..59aaf37 100644 --- a/src/test/java/org/scenarioo/api/util/IdentifierSanitizerTest.java +++ b/src/test/java/org/scenarioo/api/util/IdentifierSanitizerTest.java @@ -1,23 +1,23 @@ package org.scenarioo.api.util; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class IdentifierSanitizerTest { +class IdentifierSanitizerTest { @Test - public void nullIdentifiersStayNull() { - assertEquals(null, IdentifierSanitizer.sanitize(null)); + void nullIdentifiersStayNull() { + assertNull(IdentifierSanitizer.sanitize(null)); } @Test - public void slashesAreReplacedWithUnderscores() { + void slashesAreReplacedWithUnderscores() { assertEquals("test_identifier__", IdentifierSanitizer.sanitize("test/identifier//")); } @Test - public void backslashesAreReplacedWithUnderscores() { + void backslashesAreReplacedWithUnderscores() { assertEquals("test_identifier__", IdentifierSanitizer.sanitize("test\\identifier\\\\")); } diff --git a/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java b/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java index 0744c39..7fdf92e 100644 --- a/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java +++ b/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java @@ -1,23 +1,23 @@ package org.scenarioo.model.docu.entities; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; import java.util.LinkedHashSet; import java.util.Set; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.scenarioo.api.exception.IllegalCharacterException; -public class LabelsTest { +class LabelsTest { @Test - public void singleLabelsCanBeAddedInAChainedFashion() { + void singleLabelsCanBeAddedInAChainedFashion() { Labels labels = new Labels().addLabel("test-1").addLabel("test-2"); assertEquals(2, labels.getLabels().size()); } @Test - public void aSetOfLabelCanBeSetAtOnce() { + void aSetOfLabelCanBeSetAtOnce() { Labels labels = new Labels(); Set labelsToSet = new LinkedHashSet(); labelsToSet.add("valid"); @@ -29,7 +29,7 @@ public void aSetOfLabelCanBeSetAtOnce() { } @Test - public void ifAnInvalidSingleLabelIsAdded_anExceptionIsThrown() { + void ifAnInvalidSingleLabelIsAdded_anExceptionIsThrown() { try { Labels labels = new Labels(); labels.addLabel("test-1").addLabel("test.2"); @@ -40,7 +40,7 @@ public void ifAnInvalidSingleLabelIsAdded_anExceptionIsThrown() { } @Test - public void ifASetOfLabelsContainingInvalidCharactersIsSet_anExceptionIsThrown() { + void ifASetOfLabelsContainingInvalidCharactersIsSet_anExceptionIsThrown() { try { Labels labels = new Labels(); Set labelsToSet = new LinkedHashSet(); @@ -54,7 +54,7 @@ public void ifASetOfLabelsContainingInvalidCharactersIsSet_anExceptionIsThrown() } @Test - public void ifANullSetOfLabelsIsSet_anExceptionIsThrown() { + void ifANullSetOfLabelsIsSet_anExceptionIsThrown() { try { Labels labels = new Labels(); labels.setLabels(null); From 19d557f15b03a4a917a0c1b7fb15e805eb328026 Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Wed, 23 Jan 2019 14:07:48 +0100 Subject: [PATCH 32/46] #20 set language level to Java 8 and migrate try/catch-tests to JUnit 5 assertThrows. This is an optional commit. If we decide not to increase the language level, then we can revert this commit and still merge the basic JUnit 5 migration. --- build.gradle | 4 +- .../scenarioo/api/ForbiddenSlashesTest.java | 143 ++++++------------ .../api/rules/CharacterCheckerTest.java | 45 ++---- .../api/rules/DetailsCheckerTest.java | 20 +-- .../model/docu/entities/LabelsTest.java | 38 ++--- 5 files changed, 87 insertions(+), 163 deletions(-) diff --git a/build.gradle b/build.gradle index e129016..eb4b8a8 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ apply plugin: 'java' apply plugin: 'maven' apply plugin: 'signing' -sourceCompatibility = 1.6 -targetCompatibility = 1.6 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java b/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java index 14256e7..d3e9057 100644 --- a/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java +++ b/src/test/java/org/scenarioo/api/ForbiddenSlashesTest.java @@ -62,162 +62,115 @@ static void cleanup() { @Test void creatingAScenarioDocuWriter_withAnIllegalBranchName_resultsInAnException() { - try { - new ScenarioDocuWriter(dataDirectory, ILLEGAL_NAME, LEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> new ScenarioDocuWriter(dataDirectory, ILLEGAL_NAME, LEGAL_NAME)); + assertException(e); } @Test void creatingAScenarioDocuWriter_withAnIllegalBuildName_resultsInAnException() { - try { - new ScenarioDocuWriter(dataDirectory, LEGAL_NAME, ILLEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> new ScenarioDocuWriter(dataDirectory, LEGAL_NAME, ILLEGAL_NAME)); + assertException(e); } @Test void writingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { - try { - scenarioDocuWriter.saveUseCase(getUseCaseWithIllegalName()); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveUseCase(getUseCaseWithIllegalName())); + assertException(e); } @Test void writingAScenario_withAnIllegalUseCaseName_resultsInAnException() { - try { - scenarioDocuWriter.saveScenario(ILLEGAL_NAME, getScenarioWithName(LEGAL_NAME)); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveScenario(ILLEGAL_NAME, getScenarioWithName(LEGAL_NAME))); + assertException(e); + } @Test void writingAScenario_withAnIllegalScenarioName_resultsInAnException() { - try { - scenarioDocuWriter.saveScenario(LEGAL_NAME, getScenarioWithName(ILLEGAL_NAME)); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveScenario(LEGAL_NAME, getScenarioWithName(ILLEGAL_NAME))); + assertException(e); } @Test void writingAStep_withAnIllegalUseCaseName_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(ILLEGAL_NAME, LEGAL_NAME, getStepWithPageName(LEGAL_NAME)); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(ILLEGAL_NAME, LEGAL_NAME, getStepWithPageName(LEGAL_NAME))); + assertException(e); } @Test void writingAStep_withAnIllegalScenarioName_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, ILLEGAL_NAME, getStepWithPageName(LEGAL_NAME)); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, ILLEGAL_NAME, getStepWithPageName(LEGAL_NAME))); + assertException(e); } @Test void writingAStep_withAnIllegalPageName_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithPageName(ILLEGAL_NAME)); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithPageName(ILLEGAL_NAME))); + assertException(e); } @Test void writingAStep_withAnIllegalObjectTypeInMetadata_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInMetadata()); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInMetadata())); + assertException(e); } @Test void writingAStep_withAnIllegalObjectNameInMetadata_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInMetadata()); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInMetadata())); + assertException(e); } @Test void writingAStep_withAnIllegalObjectTypeInStepDescription_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInStepDescription()); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectTypeInStepDescription())); + assertException(e); } @Test void writingAStep_withAnIllegalObjectNameInStepDescription_resultsInAnException() { - try { - scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInStepDescription()); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuWriter.saveStep(LEGAL_NAME, LEGAL_NAME, getStepWithIllegalObjectNameInStepDescription())); + assertException(e); } @Test void readingAUseCase_withAnIllegalBranchName_resultsInAnException() { - try { - scenarioDocuReader.loadUsecase(ILLEGAL_NAME, LEGAL_NAME, LEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuReader.loadUsecase(ILLEGAL_NAME, LEGAL_NAME, LEGAL_NAME)); assertException(e); - } } @Test void readingAUseCase_withAnIllegalBuildName_resultsInAnException() { - try { - scenarioDocuReader.loadUsecase(LEGAL_NAME, ILLEGAL_NAME, LEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuReader.loadUsecase(LEGAL_NAME, ILLEGAL_NAME, LEGAL_NAME)); + assertException(e); } @Test void readingAUseCase_withAnIllegalUseCaseName_resultsInAnException() { - try { - scenarioDocuReader.loadUsecase(LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuReader.loadUsecase(LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME)); + assertException(e); } @Test void readingAScenario_withAnIllegalScenarioName_resultsInAnException() { - try { - scenarioDocuReader.loadScenario(LEGAL_NAME, LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME); - fail(); - } catch (IllegalCharacterException e) { - assertException(e); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> scenarioDocuReader.loadScenario(LEGAL_NAME, LEGAL_NAME, LEGAL_NAME, ILLEGAL_NAME)); + assertException(e); } @Test diff --git a/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java b/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java index ad36d50..d18526a 100644 --- a/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java +++ b/src/test/java/org/scenarioo/api/rules/CharacterCheckerTest.java @@ -19,22 +19,16 @@ void checkIdentifier_stringsWithoutASlashOrBackslash_areValid() { @Test void checkIdentifier_stringsWithASlash_resultInAnException() { - try { - CharacterChecker.checkIdentifier("abc/def"); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Identifier abc/def contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> CharacterChecker.checkIdentifier("abc/def")); + assertEquals("Identifier abc/def contains illegal characters.", e.getMessage()); } @Test void checkIdentifier_stringsWithABackslash_resultInAnException() { - try { - CharacterChecker.checkIdentifier("abc\\def"); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Identifier abc\\def contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> CharacterChecker.checkIdentifier("abc\\def")); + assertEquals("Identifier abc\\def contains illegal characters.", e.getMessage()); } @Test @@ -45,12 +39,9 @@ void checkIdentifier_forValidIdentifiers_returnsTheIdentifier() { @Test void checkLabel_aNullLabel_resultsInAnException() { - try { - CharacterChecker.checkLabel(null); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Label null contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> CharacterChecker.checkLabel(null)); + assertEquals("Label null contains illegal characters.", e.getMessage()); } @Test @@ -60,22 +51,16 @@ void checkLabel_aLabelContainingAllTypesOfAllowedCharacters_passesTheCheck() { @Test void checkLabel_aLabelWithASlash_resultsInAnException() { - try { - CharacterChecker.checkLabel("abc/def"); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Label abc/def contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> CharacterChecker.checkLabel("abc/def")); + assertEquals("Label abc/def contains illegal characters.", e.getMessage()); } @Test void checkLabel_aLabelWithAnUmlaut_resultsInAnException() { - try { - CharacterChecker.checkLabel("äuäää"); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Label äuäää contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> CharacterChecker.checkLabel("äuäää")); + assertEquals("Label äuäää contains illegal characters.", e.getMessage()); } @Test diff --git a/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java b/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java index 99cec24..06f1ac3 100644 --- a/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java +++ b/src/test/java/org/scenarioo/api/rules/DetailsCheckerTest.java @@ -24,22 +24,18 @@ void ifAllIdentifiersAreValid_theCheckPasses() { @Test void ifThereIsAnInvalidObjectType_anExceptionIsThrown() { - try { - DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectType()); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Identifier /illegal contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectType())); + assertEquals("Identifier /illegal contains illegal characters.", e.getMessage()); + } @Test void ifThereIsAnInvalidObjectName_anExceptionIsThrown() { - try { - DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectName()); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Identifier /illegal contains illegal characters.", e.getMessage()); - } + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> DetailsChecker.checkIdentifiers(getDetailsWithInvalidObjectName())); + assertEquals("Identifier /illegal contains illegal characters.", e.getMessage()); + } private Details getDetailsWithInvalidObjectType() { diff --git a/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java b/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java index 7fdf92e..d0d6cc2 100644 --- a/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java +++ b/src/test/java/org/scenarioo/model/docu/entities/LabelsTest.java @@ -30,38 +30,28 @@ void aSetOfLabelCanBeSetAtOnce() { @Test void ifAnInvalidSingleLabelIsAdded_anExceptionIsThrown() { - try { - Labels labels = new Labels(); - labels.addLabel("test-1").addLabel("test.2"); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Label test.2 contains illegal characters.", e.getMessage()); - } + Labels labels = new Labels(); + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> labels.addLabel("test-1").addLabel("test.2")); + assertEquals("Label test.2 contains illegal characters.", e.getMessage()); } @Test void ifASetOfLabelsContainingInvalidCharactersIsSet_anExceptionIsThrown() { - try { - Labels labels = new Labels(); - Set labelsToSet = new LinkedHashSet(); - labelsToSet.add("valid"); - labelsToSet.add(".invalid"); - labels.setLabels(labelsToSet); - fail(); - } catch (IllegalCharacterException e) { - assertEquals("Label .invalid contains illegal characters.", e.getMessage()); - } + Labels labels = new Labels(); + Set labelsToSet = new LinkedHashSet(); + labelsToSet.add("valid"); + labelsToSet.add(".invalid"); + IllegalCharacterException e = assertThrows(IllegalCharacterException.class, + () -> labels.setLabels(labelsToSet)); + assertEquals("Label .invalid contains illegal characters.", e.getMessage()); } @Test void ifANullSetOfLabelsIsSet_anExceptionIsThrown() { - try { - Labels labels = new Labels(); - labels.setLabels(null); - fail(); - } catch (NullPointerException e) { - assertEquals("Labels must not be null.", e.getMessage()); - } + Labels labels = new Labels(); + NullPointerException e = assertThrows(NullPointerException.class, () -> labels.setLabels(null)); + assertEquals("Labels must not be null.", e.getMessage()); } } From 92bc9e7f30143fa63cd06a2be3f2e5620cffc456 Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Thu, 14 Feb 2019 07:25:20 +0100 Subject: [PATCH 33/46] #20 add Changelog with Breaking Change for next Release. --- docs/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/CHANGELOG.md diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000..3c1c82b --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,10 @@ +# Scenarioo Writer Library for Java Release Notes + +## Version 3.0.0 + +### Upgrade to Java 8 + +* [#725 - Migrate to JUnit 5](https://github.com/scenarioo/scenarioo-java/issues/20) + +With version 3, the Java Writer Library needs at least Java 8 to run. + From f9b62444cbe6cbcd8b1b1983ab129b93bb222c53 Mon Sep 17 00:00:00 2001 From: David Eggerschwiler Date: Wed, 8 May 2019 12:46:03 +0200 Subject: [PATCH 34/46] #20: Since increasing the Java version leads to a major change (see changelog), the version is increased to 3.0.0-SNAPSHOT. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index eb4b8a8..a7c411b 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ group = 'org.scenarioo' -version = '2.1.3-RC1' +version = '3.0.0-SNAPSHOT' apply plugin: 'eclipse' apply plugin: 'java' From 6924ffc92fc4729e338e1a70ac4e7578f7fad954 Mon Sep 17 00:00:00 2001 From: mi-we Date: Fri, 27 Sep 2019 11:16:38 +0200 Subject: [PATCH 35/46] #22 Source and target compatibility for Java 11 - Added JAXB dependencies that were removed from Java 11 - Needed to update Gradle version to 5.6 --- build.gradle | 20 ++- gradle/wrapper/gradle-wrapper.jar | Bin 54208 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 28 +++- gradlew.bat | 18 +- .../scenarioo-schemas/scenarioo-api.xsd | 158 +++++++++--------- 6 files changed, 133 insertions(+), 94 deletions(-) diff --git a/build.gradle b/build.gradle index a7c411b..902b09d 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ apply plugin: 'java' apply plugin: 'maven' apply plugin: 'signing' -sourceCompatibility = 1.8 -targetCompatibility = 1.8 +sourceCompatibility = 1.11 +targetCompatibility = 1.11 repositories { mavenCentral() @@ -43,6 +43,11 @@ dependencies { compile 'log4j:log4j:1.2.17' testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.3.2' + + //These libraries are no longer provided in Java 9+, thus we need to add them manually + compile 'javax.xml.bind:jaxb-api:2.3.1' + compile 'com.sun.xml.bind:jaxb-core:2.3.0.1' + compile 'com.sun.xml.bind:jaxb-impl:2.3.2' } test { @@ -54,12 +59,12 @@ test { } task javadocJar(type: Jar) { - classifier = 'javadoc' + archiveClassifier.set('javadoc') from javadoc } task sourcesJar(type: Jar) { - classifier = 'sources' + archiveClassifier.set('javadoc') from sourceSets.main.allSource } @@ -132,6 +137,9 @@ task generateSchema(type: JavaExec) { jar.dependsOn generateSchema -task wrapper(type: Wrapper) { - gradleVersion = '4.7' +wrapper { + distributionType = Wrapper.DistributionType.ALL + gradleVersion = "5.6" } + + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index cd4fa588049e2ad3913c883f60681bd38e154c04..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch literal 55616 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 - + - - - - + @@ -77,9 +74,14 @@ - + - + + + + + + @@ -96,43 +98,37 @@ - + - - - - - - - - - - - - - - - - + - + - + - + - - + + + + + + + + + + + - + - + @@ -147,19 +143,17 @@ - - - - - - - + - + - + + + + + @@ -174,11 +168,22 @@ - + + + - + + + + + + + + + + @@ -201,13 +206,12 @@ - + - - - - - + + + + @@ -222,45 +226,39 @@ - - - - + - - - - + - + - - - - - + + - + + + + + + + + + - + - - - - - - + @@ -277,15 +275,10 @@ - - - - - - - + - + + @@ -303,7 +296,14 @@ - + + + + + + + + From a2c0ac06ceb0f6a609721ec9e5de44fea29a4e3b Mon Sep 17 00:00:00 2001 From: mi-we Date: Fri, 27 Sep 2019 11:36:19 +0200 Subject: [PATCH 36/46] #22 Update documentation and changelog --- README.md | 10 ++++++++-- docs/CHANGELOG.md | 11 ++++++++--- docs/usage.md | 16 +++++++--------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2a33883..20ceb1d 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,16 @@ Scenarioo Writer API for Java to generate Scenarioo Documentations - http://www.scenarioo.org - ## Usage Scenarioo-Java is available on maven central: Include the latest version as a dependency in your favorite dependency management system: + +For Java 11+ applications, use: + +`compile 'org.scenarioo:scenarioo-java:3.0.0'` + +For versions below Java 11, use: + `compile 'org.scenarioo:scenarioo-java:2.1.1'` You will find more information in our [usage guide](docs/usage.md). @@ -13,4 +19,4 @@ You will find more information in our [usage guide](docs/usage.md). ## Development Refer to our -[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. \ No newline at end of file +[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3c1c82b..7ae0b0f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,9 +2,14 @@ ## Version 3.0.0 -### Upgrade to Java 8 +### Upgrade to Java 11 -* [#725 - Migrate to JUnit 5](https://github.com/scenarioo/scenarioo-java/issues/20) +* [#22 - Runtime errors when using the writer with Java 11](https://github.com/scenarioo/scenarioo-java/issues/22) +* [#20 - Migrate to JUnit 5](https://github.com/scenarioo/scenarioo-java/issues/20) -With version 3, the Java Writer Library needs at least Java 8 to run. +Users of Java version 11 and above need to use this version of the writer library. + +The writer library relies on JAXB to generate the XML files. +With the release of Java 11, JAXB along with other Java EE modules has been removed from the standard library. +Therefore a new version of scenarioo-java had to be built which supplies those dependencies out of the box. diff --git a/docs/usage.md b/docs/usage.md index 8409971..76b7671 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -7,17 +7,15 @@ The Scenarioo Writer Library for Java helps you produce correct Scenarioo docume The JAR is available on Maven Central: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.scenarioo%22 -We recommend to always use the latest version of the library or the highest available major version number that is equal or less to the major version number of the viewer web application you are using. +We recommend to always use the latest version of the library. -The following example shows the correct gradle dependency for using scenarioo in your Java project: - - repositories { - mavenCentral() - } +For Java 11+ applications, use: - dependencies { - compile 'org.scenarioo:scenarioo-java:2.1.1' - } +`compile 'org.scenarioo:scenarioo-java:3.0.0'` + +For versions below Java 11, use: + +`compile 'org.scenarioo:scenarioo-java:2.1.1'` ## Basic usage From f415e9793e639e734646d5a467b44f9c5b5cfb27 Mon Sep 17 00:00:00 2001 From: mi-we Date: Fri, 27 Sep 2019 13:38:16 +0200 Subject: [PATCH 37/46] Revert "#22 Update documentation and changelog" This reverts commit a2c0ac06 --- README.md | 10 ++-------- docs/CHANGELOG.md | 11 +++-------- docs/usage.md | 16 +++++++++------- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 20ceb1d..2a33883 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,10 @@ Scenarioo Writer API for Java to generate Scenarioo Documentations - http://www.scenarioo.org + ## Usage Scenarioo-Java is available on maven central: Include the latest version as a dependency in your favorite dependency management system: - -For Java 11+ applications, use: - -`compile 'org.scenarioo:scenarioo-java:3.0.0'` - -For versions below Java 11, use: - `compile 'org.scenarioo:scenarioo-java:2.1.1'` You will find more information in our [usage guide](docs/usage.md). @@ -19,4 +13,4 @@ You will find more information in our [usage guide](docs/usage.md). ## Development Refer to our -[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. +[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. \ No newline at end of file diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 7ae0b0f..3c1c82b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,14 +2,9 @@ ## Version 3.0.0 -### Upgrade to Java 11 +### Upgrade to Java 8 -* [#22 - Runtime errors when using the writer with Java 11](https://github.com/scenarioo/scenarioo-java/issues/22) -* [#20 - Migrate to JUnit 5](https://github.com/scenarioo/scenarioo-java/issues/20) +* [#725 - Migrate to JUnit 5](https://github.com/scenarioo/scenarioo-java/issues/20) -Users of Java version 11 and above need to use this version of the writer library. - -The writer library relies on JAXB to generate the XML files. -With the release of Java 11, JAXB along with other Java EE modules has been removed from the standard library. -Therefore a new version of scenarioo-java had to be built which supplies those dependencies out of the box. +With version 3, the Java Writer Library needs at least Java 8 to run. diff --git a/docs/usage.md b/docs/usage.md index 76b7671..8409971 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -7,15 +7,17 @@ The Scenarioo Writer Library for Java helps you produce correct Scenarioo docume The JAR is available on Maven Central: http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.scenarioo%22 -We recommend to always use the latest version of the library. +We recommend to always use the latest version of the library or the highest available major version number that is equal or less to the major version number of the viewer web application you are using. -For Java 11+ applications, use: +The following example shows the correct gradle dependency for using scenarioo in your Java project: + + repositories { + mavenCentral() + } -`compile 'org.scenarioo:scenarioo-java:3.0.0'` - -For versions below Java 11, use: - -`compile 'org.scenarioo:scenarioo-java:2.1.1'` + dependencies { + compile 'org.scenarioo:scenarioo-java:2.1.1' + } ## Basic usage From e37736dbf08c34b54ad016a1136773d742bdedaa Mon Sep 17 00:00:00 2001 From: mi-we Date: Fri, 27 Sep 2019 14:20:37 +0200 Subject: [PATCH 38/46] #22 Revert source/target compatibility to 1.8 - change from 1.6 to 1.8 compatibility is easier to maintain for users - build is still ready for Java 11 because JAXB dependencies are supplied --- README.md | 6 ++++-- build.gradle | 4 ++-- docs/CHANGELOG.md | 7 +++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2a33883..057dfd9 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,13 @@ Scenarioo Writer API for Java to generate Scenarioo Documentations - http://www. ## Usage Scenarioo-Java is available on maven central: Include the latest version as a dependency in your favorite dependency management system: -`compile 'org.scenarioo:scenarioo-java:2.1.1'` +`compile 'org.scenarioo:scenarioo-java:3.0.0'` + +Notice that at least Java 8 is required for version 3.0.0 of the writer library You will find more information in our [usage guide](docs/usage.md). ## Development Refer to our -[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. \ No newline at end of file +[Release new API](docs/release-new-api.md) documentation for more information how to build and release scenarioo-java. diff --git a/build.gradle b/build.gradle index 902b09d..1799dc5 100644 --- a/build.gradle +++ b/build.gradle @@ -29,8 +29,8 @@ apply plugin: 'java' apply plugin: 'maven' apply plugin: 'signing' -sourceCompatibility = 1.11 -targetCompatibility = 1.11 +sourceCompatibility = 1.8 +targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 3c1c82b..411f51f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -8,3 +8,10 @@ With version 3, the Java Writer Library needs at least Java 8 to run. +### Readiness for Java 11 + +* [#22 - Runtime errors when using the writer with Java 11](https://github.com/scenarioo/scenarioo-java/issues/22) + +Java 11 does not include Java EE libraries anymore. Since scenarioo-java relies on JAXB for writing the XML files, +we need to provide the dependencies out of the box. Users of Java 11+ should switch to this version, if they don't want +to supply the missing dependencies themselves. From 4b746b704651bb46cf6b04b15b394b55332b1ac1 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 10:38:37 +0200 Subject: [PATCH 39/46] Upgrade gradle to version 6.7.1. This streamlines scenarioo main and scenarioo-java. --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 1799dc5..2521f54 100644 --- a/build.gradle +++ b/build.gradle @@ -139,7 +139,7 @@ jar.dependsOn generateSchema wrapper { distributionType = Wrapper.DistributionType.ALL - gradleVersion = "5.6" + gradleVersion = "6.7.1" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ca9d628..1f3fdbc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8a857310e94f65af026f45371994288e2daecd2b Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 10:52:59 +0200 Subject: [PATCH 40/46] Migrate deprecated declarations. --- README.md | 2 +- build.gradle | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 057dfd9..a0b9e2d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Scenarioo Writer API for Java to generate Scenarioo Documentations - http://www. ## Usage Scenarioo-Java is available on maven central: Include the latest version as a dependency in your favorite dependency management system: -`compile 'org.scenarioo:scenarioo-java:3.0.0'` +`implementation 'org.scenarioo:scenarioo-java:3.0.0'` Notice that at least Java 8 is required for version 3.0.0 of the writer library diff --git a/build.gradle b/build.gradle index 2521f54..e705761 100644 --- a/build.gradle +++ b/build.gradle @@ -37,17 +37,17 @@ repositories { } dependencies { - compile 'org.apache.commons:commons-lang3:3.0.1' - compile 'commons-io:commons-io:1.3.2' - compile 'commons-codec:commons-codec:1.2' - compile 'log4j:log4j:1.2.17' - testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' - testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.3.2' + implementation 'org.apache.commons:commons-lang3:3.0.1' + implementation 'commons-io:commons-io:1.3.2' + implementation 'commons-codec:commons-codec:1.2' + implementation 'log4j:log4j:1.2.17' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.2' //These libraries are no longer provided in Java 9+, thus we need to add them manually - compile 'javax.xml.bind:jaxb-api:2.3.1' - compile 'com.sun.xml.bind:jaxb-core:2.3.0.1' - compile 'com.sun.xml.bind:jaxb-impl:2.3.2' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + implementation 'com.sun.xml.bind:jaxb-core:2.3.0.1' + implementation 'com.sun.xml.bind:jaxb-impl:2.3.2' } test { From 3bd2e2bc0e87b2d3a2bee8d653bd452ec330d71b Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 13:27:10 +0200 Subject: [PATCH 41/46] Migrate to maven publish. --- build.gradle | 78 +++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 37 deletions(-) diff --git a/build.gradle b/build.gradle index e705761..53b08fc 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ version = '3.0.0-SNAPSHOT' apply plugin: 'eclipse' apply plugin: 'java' -apply plugin: 'maven' +apply plugin: 'maven-publish' apply plugin: 'signing' sourceCompatibility = 1.8 @@ -64,7 +64,7 @@ task javadocJar(type: Jar) { } task sourcesJar(type: Jar) { - archiveClassifier.set('javadoc') + archiveClassifier.set('sources') from sourceSets.main.allSource } @@ -72,62 +72,66 @@ artifacts { archives javadocJar, sourcesJar } -if (project.hasProperty('sign')) { - signing { - sign configurations.archives - } -} - tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') } -uploadArchives { - repositories { - mavenDeployer { - if (project.hasProperty('sign')) { - beforeDeployment { - MavenDeployment deployment -> signing.signPom(deployment) - } - } - - repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - - snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") { - authentication(userName: ossrhUsername, password: ossrhPassword) - } +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact sourcesJar + artifact javadocJar - pom.project { - name 'Scenarioo java' - packaging 'jar' - description 'Scenarioo Writer library for Java to generate Scenarioo Documentation http://www.scenarioo.org' - url 'http://www.scenarioo.org' + pom { + name = 'Scenarioo Java' + packaging = 'jar' + description = 'Scenarioo Writer library for Java to generate Scenarioo Documentation http://www.scenarioo.org' + url = 'http://www.scenarioo.org' scm { - connection 'https://github.com/scenarioo/scenarioo-java.git' - developerConnection 'https://github.com/scenarioo/scenarioo-java.git' - url 'https://github.com/scenarioo/scenarioo-java.git' + connection = 'https://github.com/scenarioo/scenarioo-java.git' + developerConnection = 'https://github.com/scenarioo/scenarioo-java.git' + url = 'https://github.com/scenarioo/scenarioo-java.git' } licenses { license { - name 'GNU GENERAL PUBLIC LICENCE with linking exception' - url 'https://github.com/scenarioo/scenarioo-java/blob/develop/LICENSE.txt' + name = 'GNU GENERAL PUBLIC LICENCE with linking exception' + url = 'https://github.com/scenarioo/scenarioo-java/blob/develop/LICENSE.txt' } } developers { developer { - id 'scenarioo' - name 'Scenarioo' - email 'contact@scenarioo.org' + id = 'scenarioo' + name = 'Scenarioo' + email = 'contact@scenarioo.org' } } } } } + + repositories { + maven { + if (version.contains("SNAPSHOT")) { + url "https://oss.sonatype.org/content/repositories/snapshots/" + } else { + url "https://oss.sonatype.org/service/local/staging/deploy/maven2" + } + credentials { + username ossrhUsername + password ossrhPassword + } + } + } +} + +if (ossrhPassword) { + signing { + sign publishing.publications.mavenJava + } } task generateSchema(type: JavaExec) { From 47548e7f783a4df8aaea6ef79e5535640f09fccb Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 16:36:09 +0200 Subject: [PATCH 42/46] Migrate to slf4j. Use try-with-resources for cleaner code. Fixes #17. --- build.gradle | 2 +- .../api/util/xml/ScenarioDocuXMLFileUtil.java | 40 +++------- .../api/util/xml/ScenarioDocuXMLUtil.java | 77 +++++++++---------- 3 files changed, 47 insertions(+), 72 deletions(-) diff --git a/build.gradle b/build.gradle index 53b08fc..18ae435 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation 'org.apache.commons:commons-lang3:3.0.1' implementation 'commons-io:commons-io:1.3.2' implementation 'commons-codec:commons-codec:1.2' - implementation 'log4j:log4j:1.2.17' + implementation 'org.slf4j:slf4j-api:1.7.31' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.2' diff --git a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java index 23198cb..ecbf1ce 100644 --- a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java +++ b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLFileUtil.java @@ -23,40 +23,30 @@ package org.scenarioo.api.util.xml; +import org.scenarioo.api.exception.ResourceNotFoundException; +import org.scenarioo.api.files.ObjectFromDirectory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; -import java.io.IOException; import java.util.ArrayList; import java.util.List; -import org.apache.log4j.Logger; -import org.scenarioo.api.exception.ResourceNotFoundException; -import org.scenarioo.api.files.ObjectFromDirectory; - /** * Writing or reading of all ScenarioDocu entities to XML files and back */ public class ScenarioDocuXMLFileUtil { - private static final Logger LOGGER = Logger.getLogger(ScenarioDocuXMLFileUtil.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ScenarioDocuXMLFileUtil.class); public static void marshal(final T object, final File destFile) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(destFile); + try (FileOutputStream fos = new FileOutputStream(destFile)) { ScenarioDocuXMLUtil.marshal(object, fos); } catch (Exception e) { throw new RuntimeException("Could not marshall Object of type " + object.getClass().getName() + " into file: " + destFile.getAbsolutePath(), e); - } finally { - try { - if (fos != null) { - fos.close(); - } - } catch (IOException e) { - throw new RuntimeException("Could not close file output stream for " + destFile.getAbsolutePath(), e); - } } } @@ -64,20 +54,10 @@ public static T unmarshal(final Class targetClass, final File srcFile) { if (!srcFile.exists()) { throw new ResourceNotFoundException(srcFile.getAbsolutePath()); } - FileInputStream fis = null; - try { - fis = new FileInputStream(srcFile); + try (FileInputStream fis = new FileInputStream(srcFile)) { return ScenarioDocuXMLUtil.unmarshal(targetClass, fis); } catch (Exception e) { throw new RuntimeException("Could not unmarshall " + srcFile.getAbsolutePath(), e); - } finally { - try { - if (fis != null) { - fis.close(); - } - } catch (IOException e) { - throw new RuntimeException("Could not close file input stream for " + srcFile.getAbsolutePath(), e); - } } } @@ -120,12 +100,12 @@ public static List> unmarshalListOfFilesWithDirNames( * object was loaded from. */ public static List> unmarshalListOfFilesWithDirNamesIgnoreInvalid( - final List files, final Class targetClass, final Class... classesToBind) { + final List files, final Class targetClass, final Class... classesToBind) { List> result = new ArrayList>(); for (File file : files) { try { result.add(new ObjectFromDirectory(unmarshal(targetClass, file), file - .getParentFile().getName())); + .getParentFile().getName())); } catch (Throwable e) { LOGGER.error("Could not parse invalid File: " + file.getAbsolutePath() + " - will ignore this object."); } diff --git a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLUtil.java b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLUtil.java index d9ed0c6..34b3b7f 100644 --- a/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLUtil.java +++ b/src/main/java/org/scenarioo/api/util/xml/ScenarioDocuXMLUtil.java @@ -1,21 +1,21 @@ /* scenarioo-api * Copyright (C) 2014, scenarioo.org Development Team - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * As a special exception, the copyright holders of this library give you - * permission to link this library with independent modules, according + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules, according * to the GNU General Public License with "Classpath" exception as provided * in the LICENSE file that accompanied this code. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ @@ -23,36 +23,31 @@ package org.scenarioo.api.util.xml; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.*; +import org.apache.commons.lang3.StringUtils; +import org.scenarioo.model.docu.entities.generic.*; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; - -import org.apache.commons.lang3.StringUtils; -import org.scenarioo.model.docu.entities.generic.Details; -import org.scenarioo.model.docu.entities.generic.ObjectDescription; -import org.scenarioo.model.docu.entities.generic.ObjectList; -import org.scenarioo.model.docu.entities.generic.ObjectReference; -import org.scenarioo.model.docu.entities.generic.ObjectTreeNode; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.*; /** * Streaming of all ScenarioDocu entities to XML and back from input streams or to output streams. */ public class ScenarioDocuXMLUtil { - private static Map jaxbContextCache = new HashMap(); + private static final Map jaxbContextCache = new HashMap<>(); + + private static final Class[] SUPPORTED_COLLECTION_CLASSES = new Class[]{HashMap.class, ArrayList.class}; + + private static final Class[] SUPPORTED_GENERIC_CLASSES = new Class[]{ObjectDescription.class, + ObjectReference.class, ObjectList.class, ObjectTreeNode.class, Details.class}; - private static final Class[] SUPPORTED_COLLECTION_CLASSES = new Class[] { HashMap.class, ArrayList.class }; - - private static final Class[] SUPPORTED_GENERIC_CLASSES = new Class[] { ObjectDescription.class, - ObjectReference.class, ObjectList.class, ObjectTreeNode.class, Details.class }; - public static void marshal(final T object, final OutputStream outStream) { - + try { JAXBContext contextObj = createJAXBContext(object.getClass()); Marshaller marshallerObj = contextObj.createMarshaller(); @@ -62,7 +57,7 @@ public static void marshal(final T object, final OutputStream outStream) { throw new RuntimeException("Could not marshall Object of type " + object.getClass().getName(), e); } } - + @SuppressWarnings("unchecked") public static T unmarshal(final Class targetClass, final InputStream inStream) { try { @@ -73,29 +68,29 @@ public static T unmarshal(final Class targetClass, final InputStream inSt throw new RuntimeException("Could not unmarshall object of type " + targetClass.getName(), e); } } - + public static JAXBContext createJAXBContext(Class... classesToBind) throws JAXBException { - String key = getKeyFromClassesArray(classesToBind); - JAXBContext cachedJaxbContext = jaxbContextCache.get(key); - if(cachedJaxbContext != null) { - return cachedJaxbContext; - } + String key = getKeyFromClassesArray(classesToBind); + JAXBContext cachedJaxbContext = jaxbContextCache.get(key); + if (cachedJaxbContext != null) { + return cachedJaxbContext; + } classesToBind = appendClasses(classesToBind, SUPPORTED_COLLECTION_CLASSES); classesToBind = appendClasses(classesToBind, SUPPORTED_GENERIC_CLASSES); - JAXBContext jaxbContext = JAXBContext.newInstance(classesToBind); - jaxbContextCache.put(key, jaxbContext); - return jaxbContext; + JAXBContext jaxbContext = JAXBContext.newInstance(classesToBind); + jaxbContextCache.put(key, jaxbContext); + return jaxbContext; } - private static String getKeyFromClassesArray(Class[] classesToBind) { - List keys = new ArrayList(); - for (Class aClass : classesToBind) { - keys.add(aClass.getCanonicalName()); - } - return StringUtils.join(keys, ","); - } + private static String getKeyFromClassesArray(Class[] classesToBind) { + List keys = new ArrayList(); + for (Class aClass : classesToBind) { + keys.add(aClass.getCanonicalName()); + } + return StringUtils.join(keys, ","); + } - private static Class[] appendClasses(Class[] classesToBind, final Class... additionalClasses) { + private static Class[] appendClasses(Class[] classesToBind, final Class... additionalClasses) { int index = classesToBind.length; classesToBind = Arrays.copyOf(classesToBind, classesToBind.length + additionalClasses.length); for (Class additionalClass : additionalClasses) { @@ -104,5 +99,5 @@ private static Class[] appendClasses(Class[] classesToBind, final Class } return classesToBind; } - + } From 1a95a38ae605b50ca233d33f37c40648f20c124e Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 16:39:53 +0200 Subject: [PATCH 43/46] Improve documentation. --- docs/upload-to-maven-central.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docs/upload-to-maven-central.md b/docs/upload-to-maven-central.md index 3fbadb1..333efcb 100644 --- a/docs/upload-to-maven-central.md +++ b/docs/upload-to-maven-central.md @@ -2,18 +2,22 @@ ## Snapshot -1. You will need to specify the following properties in your `gradle.properties` located in your gradle home directory: +1. You will need to specify the following properties in your `gradle.properties` located in your gradle home directory: + + ``` + signing.keyId=BDCAAE60 + signing.password=#private key goes here# + signing.secretKeyRingFile=#secret key file goes here# + ossrhUsername=scenarioo + ossrhPassword=#sonatype password goes here# + ``` +The credentials can be found in the internal MS Teams Channel. - ``` - signing.keyId=BDCAAE60 - signing.password=#private key goes here# - signing.secretKeyRingFile=#secret key file goes here# - ossrhUsername=scenarioo - ossrhPassword=#sonatype password goes here# - ``` 2. Change the version appropriately in the `build.gradle` -3. `gradlew clean uploadArchives -Psign` +3. `gradlew clean publish` +4. Promote build to maven central: http://central.sonatype.org/pages/releasing-the-deployment.html + Please note, we're using the old server https://oss.sonatype.org. ## Releases From b5b1ea0f388b3cb7546975ac24115751ab07ad96 Mon Sep 17 00:00:00 2001 From: danielsuter Date: Fri, 25 Jun 2021 17:11:14 +0200 Subject: [PATCH 44/46] Overload addDetail method and provide some javadoc. Code clean up (IntelliJ suggestions). Closes #1 --- .../model/docu/entities/generic/Details.java | 116 +++++++++++------- .../org/scenarioo/api/SaveScreenshotTest.java | 18 +-- 2 files changed, 84 insertions(+), 50 deletions(-) diff --git a/src/main/java/org/scenarioo/model/docu/entities/generic/Details.java b/src/main/java/org/scenarioo/model/docu/entities/generic/Details.java index 07d7b1a..9e2d4ee 100755 --- a/src/main/java/org/scenarioo/model/docu/entities/generic/Details.java +++ b/src/main/java/org/scenarioo/model/docu/entities/generic/Details.java @@ -1,42 +1,41 @@ /* scenarioo-api * Copyright (C) 2014, scenarioo.org Development Team - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * As a special exception, the copyright holders of this library give you - * permission to link this library with independent modules, according + * As a special exception, the copyright holders of this library give you + * permission to link this library with independent modules, according * to the GNU General Public License with "Classpath" exception as provided * in the LICENSE file that accompanied this code. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ package org.scenarioo.model.docu.entities.generic; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; - /** * Collection of application specific additional information to store and display in the scenarioo documentation. - * + *

    * A client of the scenarioo-API can add any key-value-data to this detail informations. - * + *

    * Following type of objects are possible values inside the details: *

      *
    • {@link String}: for usual text information
    • @@ -52,17 +51,17 @@ @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Details implements Map, Serializable { - - private final Map properties = new LinkedHashMap(); - + + private final Map properties = new LinkedHashMap<>(); + public Map getProperties() { return properties; } - + /** * Add a key value pair as a information item to this details. The details will be presented in same order as added * to the details object in the documentation. - * + *

      * See class description of {@link Details} about possible types to use as values. */ public Details addDetail(final String key, final Object value) { @@ -73,79 +72,121 @@ public Details addDetail(final String key, final Object value) { } return this; } - + + /** + * Use to describe an object (described through a type and a name and additional + * key-value-details again). + * + *

      + * See class description of {@link Details} about other possible types to use. + */ + public Details addDetail(final String key, final ObjectDescription objectDescription) { + return this.addDetail(key, (Object) objectDescription); + } + + /** + * Use to reference an {@link ObjectDescription} that was already stored elsewhere, only + * through its type and name without storing all the details information again. + * + *

      + * See class description of {@link Details} about other possible types to use. + */ + public Details addDetail(final String key, final ObjectReference objectReference) { + return this.addDetail(key, (Object) objectReference); + } + + /** + * Use for complex tree structures containing same content types as possible node objects. + * + *

      + * See class description of {@link Details} about other possible types to use. + */ + public Details addDetail(final String key, final ObjectTreeNode objectTreeNode) { + return this.addDetail(key, (Object) objectTreeNode); + } + + /** + * Use for a list of value items (same types allowed as content types again). + * + *

      + * See class description of {@link Details} about other possible types to use. + */ + public Details addDetail(final String key, final ObjectList objectList) { + return this.addDetail(key, (Object) objectList); + } + public Object getDetail(final String key) { return properties.get(key); } - + @Override public int size() { return properties.size(); } - + @Override public boolean isEmpty() { return properties.isEmpty(); } - + @Override public boolean containsKey(final Object key) { return properties.containsKey(key); } - + @Override public boolean containsValue(final Object value) { return properties.containsValue(value); } - + @Override public Object get(final Object key) { return properties.get(key); } - + @Override public Object put(final String key, final Object value) { return properties.put(key, value); } - + @Override public Object remove(final Object key) { return properties.remove(key); } - + @Override public void putAll(final Map m) { properties.putAll(m); } - + @Override public void clear() { properties.clear(); } - + @Override public Set keySet() { return properties.keySet(); } - + @Override public Collection values() { return properties.values(); } - + @Override public Set> entrySet() { return properties.entrySet(); } - + @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + result = prime * result + properties.hashCode(); return result; } - + @Override public boolean equals(final Object obj) { if (this == obj) { @@ -158,14 +199,7 @@ public boolean equals(final Object obj) { return false; } Details other = (Details) obj; - if (properties == null) { - if (other.properties != null) { - return false; - } - } else if (!properties.equals(other.properties)) { - return false; - } - return true; + return properties.equals(other.properties); } - + } diff --git a/src/test/java/org/scenarioo/api/SaveScreenshotTest.java b/src/test/java/org/scenarioo/api/SaveScreenshotTest.java index 5bb628a..8208001 100644 --- a/src/test/java/org/scenarioo/api/SaveScreenshotTest.java +++ b/src/test/java/org/scenarioo/api/SaveScreenshotTest.java @@ -1,16 +1,17 @@ package org.scenarioo.api; -import static org.scenarioo.api.TestConstants.*; - -import java.io.File; -import java.io.IOException; - import org.apache.commons.io.FileUtils; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.io.File; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.fail; +import static org.scenarioo.api.TestConstants.*; + class SaveScreenshotTest { private static final String pngFileName = "/scenarioo-icon-unittest.png"; @@ -49,12 +50,11 @@ private void assertStoredFileContentEqualsOriginalImage() { try { fileAsByteArray = FileUtils.readFileToByteArray(file); } catch (IOException e) { - Assertions.fail("Could not read file " + file); - e.printStackTrace(); + fail("Could not read file " + file, e); return; } - Assertions.assertArrayEquals(imageAsByteArray, fileAsByteArray); + assertArrayEquals(imageAsByteArray, fileAsByteArray); } } From f3c0b4c8f0c81157eb4f07d61a04a2e8bd14ee27 Mon Sep 17 00:00:00 2001 From: Michael Werner Date: Wed, 16 Nov 2022 10:04:44 +0100 Subject: [PATCH 45/46] docs: updated changelog for release 3.0.0 preparation --- docs/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 411f51f..37d538c 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -15,3 +15,10 @@ With version 3, the Java Writer Library needs at least Java 8 to run. Java 11 does not include Java EE libraries anymore. Since scenarioo-java relies on JAXB for writing the XML files, we need to provide the dependencies out of the box. Users of Java 11+ should switch to this version, if they don't want to supply the missing dependencies themselves. + + +### Improvements to the details interface + +* [#1 - Improve details interface & API documentation](https://github.com/scenarioo/scenarioo-java/issues/1) + +The possibility to add details via the API has been improved by a few more method overloads. For more details see the [Details class](https://github.com/scenarioo/scenarioo-java/blob/develop/src/main/java/org/scenarioo/model/docu/entities/generic/Details.java) From e81f96307e274ac12f2415e3f8181895db66ce21 Mon Sep 17 00:00:00 2001 From: Michael Werner Date: Wed, 16 Nov 2022 11:07:18 +0100 Subject: [PATCH 46/46] build: updated version to RC1 for testing --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 18ae435..7ad652f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ group = 'org.scenarioo' -version = '3.0.0-SNAPSHOT' +version = '3.0.0-RC1' apply plugin: 'eclipse' apply plugin: 'java'