diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 0dec83312..8178c9b61 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -3,7 +3,7 @@ Thank you so much for sending us a pull request!
Make sure you have a clear name for your pull request.
The name should start with a capital letter and no dot is required in the end of the sentence.
-To link the request with isses use the following notation: (fixes #123, fixes #321\)
+To link the request with issues use the following notation: (fixes #123, fixes #321\)
An example of good pull request names:
* Add Cucumber integration (fixes #123\)
diff --git a/allure-java-commons/src/main/java/io/qameta/allure/Allure.java b/allure-java-commons/src/main/java/io/qameta/allure/Allure.java
index 9e494de21..90f069556 100644
--- a/allure-java-commons/src/main/java/io/qameta/allure/Allure.java
+++ b/allure-java-commons/src/main/java/io/qameta/allure/Allure.java
@@ -247,12 +247,60 @@ public static void label(final String name, final String value) {
/**
* Adds parameter to current test or step (or fixture) if any. Takes no effect
* if no test run at the moment.
+ *
+ * Shortcut for {@link #parameter(String, Object, Boolean, Parameter.Mode)}.
*
* @param name the name of parameter.
* @param value the value of parameter.
*/
public static T parameter(final String name, final T value) {
- final Parameter parameter = createParameter(name, value);
+ return parameter(name, value, null, null);
+ }
+
+ /**
+ * Adds parameter to current test or step (or fixture) if any. Takes no effect
+ * if no test run at the moment.
+ *
+ * Shortcut for {@link #parameter(String, Object, Boolean, Parameter.Mode)}.
+ *
+ * @param name the name of parameter.
+ * @param value the value of parameter.
+ * @param excluded true if parameter should be excluded from history key calculation, false otherwise.
+ * @return the specified value.
+ */
+ public static T parameter(final String name, final T value, final Boolean excluded) {
+ return parameter(name, value, excluded, null);
+ }
+
+ /**
+ * Adds parameter to current test or step (or fixture) if any. Takes no effect
+ * if no test run at the moment.
+ *
+ * Shortcut for {@link #parameter(String, Object, Boolean, Parameter.Mode)}.
+ *
+ * @param name the name of parameter.
+ * @param value the value of parameter.
+ * @param mode the parameter mode.
+ * @return the specified value.
+ */
+ public static T parameter(final String name, final T value,
+ final Parameter.Mode mode) {
+ return parameter(name, value, null, mode);
+ }
+
+ /**
+ * Adds parameter to current test or step (or fixture) if any. Takes no effect
+ * if no test run at the moment.
+ *
+ * @param name the name of parameter.
+ * @param value the value of parameter.
+ * @param excluded true if parameter should be excluded from history key calculation, false otherwise.
+ * @param mode the parameter mode.
+ * @return the specified value.
+ */
+ public static T parameter(final String name, final T value,
+ final Boolean excluded, final Parameter.Mode mode) {
+ final Parameter parameter = createParameter(name, value, excluded, mode);
getLifecycle().updateTestCase(testResult -> testResult.getParameters().add(parameter));
return value;
}
@@ -485,12 +533,66 @@ public interface ThrowableContextRunnableVoid {
/**
* Step context.
*/
+ @SuppressWarnings("MultipleStringLiterals")
public interface StepContext {
+ /**
+ * Sets step's name.
+ *
+ * @param name the deserted name of step.
+ */
void name(String name);
+ /**
+ * Adds parameter to a step.
+ *
+ * @param name the name of parameter.
+ * @param value the value.
+ * @param the type of value.
+ * @return the value.
+ */
T parameter(String name, T value);
+ /**
+ * Adds parameter to a step.
+ *
+ * @param name the name of parameter.
+ * @param value the value.
+ * @param excluded true if parameter should be excluded from history key generation, false otherwise.
+ * @param the type of value.
+ * @return the value.
+ */
+ default T parameter(String name, T value, Boolean excluded) {
+ throw new UnsupportedOperationException("method is not implemented");
+ }
+
+ /**
+ * Adds parameter to a step.
+ *
+ * @param name the name of parameter.
+ * @param value the value.
+ * @param mode the parameter's mode.
+ * @param the type of value.
+ * @return the value.
+ */
+ default T parameter(String name, T value, Parameter.Mode mode) {
+ throw new UnsupportedOperationException("method is not implemented");
+ }
+
+ /**
+ * Adds parameter to a step.
+ *
+ * @param name the name of parameter.
+ * @param value the value.
+ * @param excluded true if parameter should be excluded from history key generation, false otherwise.
+ * @param mode the parameter's mode.
+ * @param the type of value.
+ * @return the value.
+ */
+ default T parameter(String name, T value, Boolean excluded, Parameter.Mode mode) {
+ throw new UnsupportedOperationException("method is not implemented");
+ }
+
}
/**
@@ -511,7 +613,22 @@ public void name(final String name) {
@Override
public T parameter(final String name, final T value) {
- final Parameter param = createParameter(name, value);
+ return parameter(name, value, null, null);
+ }
+
+ @Override
+ public T parameter(final String name, final T value, final Boolean excluded) {
+ return parameter(name, value, excluded, null);
+ }
+
+ @Override
+ public T parameter(final String name, final T value, final Parameter.Mode mode) {
+ return parameter(name, value, null, mode);
+ }
+
+ @Override
+ public T parameter(final String name, final T value, final Boolean excluded, final Parameter.Mode mode) {
+ final Parameter param = createParameter(name, value, excluded, mode);
getLifecycle().updateStep(uuid, stepResult -> stepResult.getParameters().add(param));
return value;
}
diff --git a/allure-java-commons/src/main/java/io/qameta/allure/Param.java b/allure-java-commons/src/main/java/io/qameta/allure/Param.java
new file mode 100644
index 000000000..33e34f5bc
--- /dev/null
+++ b/allure-java-commons/src/main/java/io/qameta/allure/Param.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019 Qameta Software OÜ
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.qameta.allure;
+
+import io.qameta.allure.model.Parameter;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation used to add parameters to results
+ * from method parameters.
+ *
+ * @see Parameter
+ * @see Parameter.Mode
+ * @see Allure#parameter(String, Object)
+ */
+@Documented
+@Inherited
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.PARAMETER})
+public @interface Param {
+
+ /**
+ * Alias for {@link #name()}. Overrides value, specified in {@link #name()}.
+ */
+ String value() default "";
+
+ /**
+ * The name of parameter. Be careful, changing parameter's name
+ * may affect method signature and, as result, may get different
+ * test case generated.
+ *
+ * If not specified, the parameter name from reflection will be used.
+ *
+ * @return the name of parameter.
+ */
+ String name() default "";
+
+ /**
+ * The parameter mode.
+ *
+ * @return the parameter mode.
+ */
+ Parameter.Mode mode() default Parameter.Mode.DEFAULT;
+
+ /**
+ * Set it to true to exclude the parameter from historyKey generation.
+ *
+ * @return true if parameter is excluded, false otherwise.
+ */
+ boolean excluded() default false;
+
+}
diff --git a/allure-java-commons/src/main/java/io/qameta/allure/util/AspectUtils.java b/allure-java-commons/src/main/java/io/qameta/allure/util/AspectUtils.java
index 98c83e7b6..640298f9d 100644
--- a/allure-java-commons/src/main/java/io/qameta/allure/util/AspectUtils.java
+++ b/allure-java-commons/src/main/java/io/qameta/allure/util/AspectUtils.java
@@ -15,6 +15,7 @@
*/
package io.qameta.allure.util;
+import io.qameta.allure.Param;
import io.qameta.allure.model.Parameter;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
@@ -25,6 +26,7 @@
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
import static io.qameta.allure.util.NamingUtils.processNameTemplate;
import static io.qameta.allure.util.ResultsUtils.createParameter;
@@ -38,19 +40,6 @@ private AspectUtils() {
throw new IllegalStateException("Do not instance");
}
- /**
- * @deprecated use {@link AspectUtils#getName(String,JoinPoint)} instead.
- */
- @Deprecated
- public static String getName(final String nameTemplate,
- final MethodSignature methodSignature,
- final Object... args) {
- return Optional.of(nameTemplate)
- .filter(v -> !v.isEmpty())
- .map(value -> processNameTemplate(value, getParametersMap(methodSignature, args)))
- .orElseGet(methodSignature::getName);
- }
-
public static String getName(final String nameTemplate, final JoinPoint joinPoint) {
return Optional.of(nameTemplate)
.filter(v -> !v.isEmpty())
@@ -81,9 +70,26 @@ public static Map getParametersMap(final JoinPoint joinPoint) {
}
public static List getParameters(final MethodSignature signature, final Object... args) {
+ final java.lang.reflect.Parameter[] params = signature.getMethod().getParameters();
return IntStream
.range(0, args.length)
- .mapToObj(index -> createParameter(signature.getParameterNames()[index], args[index]))
+ .mapToObj(index -> {
+ final Parameter parameter = createParameter(signature.getParameterNames()[index], args[index]);
+ final java.lang.reflect.Parameter ref = params[index];
+ Stream.of(ref.getAnnotationsByType(Param.class))
+ .findFirst()
+ .ifPresent(param -> {
+ Stream.of(param.value(), param.name())
+ .map(String::trim)
+ .filter(name -> name.length() > 0)
+ .findFirst()
+ .ifPresent(parameter::setName);
+
+ parameter.setMode(param.mode());
+ parameter.setExcluded(param.excluded());
+ });
+ return parameter;
+ })
.collect(Collectors.toList());
}
diff --git a/allure-java-commons/src/main/java/io/qameta/allure/util/ParameterUtils.java b/allure-java-commons/src/main/java/io/qameta/allure/util/ParameterUtils.java
new file mode 100644
index 000000000..f0e68f7ec
--- /dev/null
+++ b/allure-java-commons/src/main/java/io/qameta/allure/util/ParameterUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 Qameta Software OÜ
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.qameta.allure.util;
+
+import io.qameta.allure.Param;
+import io.qameta.allure.model.Parameter;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+/**
+ * @author charlie (Dmitry Baev).
+ */
+public final class ParameterUtils {
+
+ private ParameterUtils() {
+ throw new IllegalStateException("do not instance");
+ }
+
+ public static List createParameters(final Method method,
+ final Object... args) {
+ final java.lang.reflect.Parameter[] parameters = method.getParameters();
+ return IntStream.range(0, parameters.length)
+ .mapToObj(i -> {
+ final java.lang.reflect.Parameter parameter = parameters[i];
+ final Object value = args[i];
+ final Param annotation = parameter.getAnnotation(Param.class);
+ if (Objects.isNull(annotation)) {
+ return ResultsUtils.createParameter(parameter.getName(), value);
+ }
+ final String name = Stream.of(annotation.value(), annotation.name(), parameter.getName())
+ .map(String::trim)
+ .filter(s -> s.length() > 0)
+ .findFirst()
+ .orElseGet(() -> "arg" + i);
+
+ return ResultsUtils.createParameter(
+ name,
+ value,
+ annotation.excluded(),
+ annotation.mode()
+ );
+ })
+ .collect(Collectors.toList());
+ }
+
+}
diff --git a/allure-java-commons/src/main/java/io/qameta/allure/util/ResultsUtils.java b/allure-java-commons/src/main/java/io/qameta/allure/util/ResultsUtils.java
index c49cba794..6b5194826 100644
--- a/allure-java-commons/src/main/java/io/qameta/allure/util/ResultsUtils.java
+++ b/allure-java-commons/src/main/java/io/qameta/allure/util/ResultsUtils.java
@@ -64,8 +64,7 @@
"ClassDataAbstractionCoupling",
"PMD.ExcessiveImports",
"PMD.TooManyMethods",
- "PMD.GodClass",
- "deprecation"
+ "PMD.GodClass"
})
public final class ResultsUtils {
@@ -109,7 +108,16 @@ private ResultsUtils() {
}
public static Parameter createParameter(final String name, final Object value) {
- return new Parameter().setName(name).setValue(ObjectUtils.toString(value));
+ return createParameter(name, value, null, null);
+ }
+
+ public static Parameter createParameter(final String name, final Object value,
+ final Boolean excluded, final Parameter.Mode mode) {
+ return new Parameter()
+ .setName(name)
+ .setValue(ObjectUtils.toString(value))
+ .setExcluded(excluded)
+ .setMode(mode);
}
public static Label createSuiteLabel(final String suite) {
@@ -353,7 +361,7 @@ private static String getRealHostName() {
try {
cachedHost = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
- LOGGER.debug("Could not get host name {}", e);
+ LOGGER.debug("Could not get host name", e);
cachedHost = "default";
}
}
diff --git a/allure-java-commons/src/test/java/io/qameta/allure/AllureTest.java b/allure-java-commons/src/test/java/io/qameta/allure/AllureTest.java
index ac7dbccc9..9e874187c 100644
--- a/allure-java-commons/src/test/java/io/qameta/allure/AllureTest.java
+++ b/allure-java-commons/src/test/java/io/qameta/allure/AllureTest.java
@@ -180,6 +180,31 @@ void shouldAddParameter() {
);
}
+ @Test
+ void shouldAddParameterWithModeAndExcluded() {
+ final Parameter first = current().nextObject(Parameter.class);
+ final Parameter second = current().nextObject(Parameter.class);
+ final Parameter third = current().nextObject(Parameter.class);
+
+ final AllureResults results = runWithinTestContext(
+ () -> {
+ parameter(first.getName(), first.getValue(), first.getMode());
+ parameter(second.getName(), second.getValue(), second.getExcluded());
+ parameter(third.getName(), third.getValue(), third.getExcluded(), third.getMode());
+ },
+ Allure::setLifecycle
+ );
+
+ assertThat(results.getTestResults())
+ .flatExtracting(TestResult::getParameters)
+ .extracting(Parameter::getName, Parameter::getValue, Parameter::getExcluded, Parameter::getMode)
+ .contains(
+ tuple(first.getName(), first.getValue(), null, first.getMode()),
+ tuple(second.getName(), second.getValue(), second.getExcluded(), null),
+ tuple(third.getName(), third.getValue(), third.getExcluded(), third.getMode())
+ );
+ }
+
@Test
void shouldAddLinks() {
final io.qameta.allure.model.Link first = current().nextObject(Link.class);
diff --git a/allure-java-commons/src/test/java/io/qameta/allure/aspects/StepsAspectsTest.java b/allure-java-commons/src/test/java/io/qameta/allure/aspects/StepsAspectsTest.java
index 72e3d2f5e..eb2cfb8c5 100644
--- a/allure-java-commons/src/test/java/io/qameta/allure/aspects/StepsAspectsTest.java
+++ b/allure-java-commons/src/test/java/io/qameta/allure/aspects/StepsAspectsTest.java
@@ -16,6 +16,7 @@
package io.qameta.allure.aspects;
import io.qameta.allure.Issue;
+import io.qameta.allure.Param;
import io.qameta.allure.Step;
import io.qameta.allure.model.Parameter;
import io.qameta.allure.model.Status;
@@ -30,6 +31,7 @@
import java.util.stream.Collectors;
import static io.qameta.allure.test.RunUtils.runWithinTestContext;
+import static io.qameta.allure.test.TestData.randomString;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.tuple;
@@ -285,6 +287,35 @@ void shouldSupportParallelStepsRun() {
);
}
+ @Test
+ void shouldProcessParamAnnotation() {
+ final String p1 = randomString(10);
+ final String p2 = randomString(10);
+ final String p3 = randomString(10);
+ final String p4 = randomString(10);
+ final AllureResults results = runWithinTestContext(() -> stepWithParamAnnotation(p1, p2, p3, p4));
+
+ assertThat(results.getTestResults())
+ .flatExtracting(TestResult::getSteps)
+ .flatExtracting(StepResult::getParameters)
+ .extracting(Parameter::getName, Parameter::getValue, Parameter::getExcluded, Parameter::getMode)
+ .containsExactlyInAnyOrder(
+ tuple("Named", p1, false, Parameter.Mode.DEFAULT),
+ tuple("Excluded", p2, true, Parameter.Mode.DEFAULT),
+ tuple("Masked", p3, false, Parameter.Mode.MASKED),
+ tuple("Masked", p4, false, Parameter.Mode.HIDDEN)
+ );
+
+ }
+
+ @Step
+ void stepWithParamAnnotation(
+ @Param("Named") final String named,
+ @Param(name = "Excluded", excluded = true) final String excluded,
+ @Param(name = "Masked", mode = Parameter.Mode.MASKED) final String masked,
+ @Param(name = "Masked", mode = Parameter.Mode.HIDDEN) final String hidden) {
+ }
+
@Step
void stepWithDefaultName() {
}
diff --git a/allure-java-commons/src/test/java/io/qameta/allure/util/AspectUtilsTest.java b/allure-java-commons/src/test/java/io/qameta/allure/util/ObjectUtilsTest.java
similarity index 98%
rename from allure-java-commons/src/test/java/io/qameta/allure/util/AspectUtilsTest.java
rename to allure-java-commons/src/test/java/io/qameta/allure/util/ObjectUtilsTest.java
index ea5af2cde..64045ea81 100644
--- a/allure-java-commons/src/test/java/io/qameta/allure/util/AspectUtilsTest.java
+++ b/allure-java-commons/src/test/java/io/qameta/allure/util/ObjectUtilsTest.java
@@ -23,7 +23,7 @@
/**
* @author charlie (Dmitry Baev).
*/
-class AspectUtilsTest {
+class ObjectUtilsTest {
@Issue("191")
@Test