Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
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;
Expand All @@ -26,10 +25,8 @@
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;

/**
* Utility methods used by AspectJ-based Allure integrations.
Expand Down Expand Up @@ -85,24 +82,14 @@ public static Map<String, Object> getParametersMap(final JoinPoint joinPoint) {
*/
public static List<Parameter> getParameters(final MethodSignature signature, final Object... args) {
final java.lang.reflect.Parameter[] params = signature.getMethod().getParameters();
final String[] parameterNames = signature.getParameterNames();
return IntStream
.range(0, args.length)
.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;
final String name = Optional.ofNullable(parameterNames[index])
.orElseGet(ref::getName);
return ParameterUtils.createParameter(ref, args[index], name);
})
.collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,51 @@ public static List<Parameter> createParameters(final Method method,
.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()
);
return createParameter(parameter, value);
})
.collect(Collectors.toList());
}

/**
* Creates and returns the parameter using the Java reflection parameter name as a fallback.
*
* @param parameter the Java parameter to inspect
* @param value the value
* @return the parameter
*/
public static Parameter createParameter(final java.lang.reflect.Parameter parameter,
final Object value) {
return createParameter(parameter, value, parameter.getName());
}

/**
* Creates and returns the parameter.
*
* @param parameter the framework or Java parameter to inspect
* @param value the value
* @param defaultName the name to use when {@link Param} does not override it
* @return the parameter
*/
public static Parameter createParameter(final java.lang.reflect.Parameter parameter,
final Object value,
final String defaultName) {
Objects.requireNonNull(defaultName, "defaultName");
final Param annotation = parameter.getAnnotation(Param.class);
if (Objects.isNull(annotation)) {
return ResultsUtils.createParameter(defaultName, value);
}
final String name = Stream.of(annotation.value(), annotation.name(), defaultName)
.map(String::trim)
.filter(s -> s.length() > 0)
.findFirst()
.orElse(defaultName);

return ResultsUtils.createParameter(
name,
value,
annotation.excluded(),
annotation.mode()
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.qameta.allure.aspects;

import io.qameta.allure.Allure;
import io.qameta.allure.Issue;
import io.qameta.allure.Param;
import io.qameta.allure.Step;
Expand Down Expand Up @@ -102,15 +103,17 @@ void shouldUseMethodPlaceholder() {
void shouldAddParams() {
final AllureResults results = runWithinTestContext(() -> stepWithParams("first", "second"));

assertThat(results.getTestResults())
.hasSize(1)
.flatExtracting(TestResult::getSteps)
.flatExtracting(StepResult::getParameters)
.extracting(Parameter::getName, Parameter::getValue)
.containsExactlyInAnyOrder(
tuple("a", "first"),
tuple("b", "second")
);
Allure.step(
"Assert step parameters keep AspectJ names", () -> assertThat(results.getTestResults())
.hasSize(1)
.flatExtracting(TestResult::getSteps)
.flatExtracting(StepResult::getParameters)
.extracting(Parameter::getName, Parameter::getValue)
.containsExactlyInAnyOrder(
tuple("a", "first"),
tuple("b", "second")
)
);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright 2016-2026 Qameta Software Inc
*
* 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 org.junit.jupiter.api.Test;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import static io.qameta.allure.Allure.addAttachment;
import static io.qameta.allure.Allure.step;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
import static org.assertj.core.api.Assertions.tuple;

class ParameterUtilsTest {

@Test
void shouldApplyParamAnnotationToFrameworkParameter() throws NoSuchMethodException {
step("Create framework parameters and verify @Param metadata", () -> {
final Method method = getClass().getDeclaredMethod(
"methodWithParameters",
String.class,
String.class,
String.class
);
final List<Parameter> parameters = Arrays.asList(
ParameterUtils.createParameter(method.getParameters()[0], "1", "first"),
ParameterUtils.createParameter(method.getParameters()[1], "2", "second"),
ParameterUtils.createParameter(method.getParameters()[2], "3", "third")
);

addAttachment(
"created parameters", "text/plain", parameters.stream()
.map(
parameter -> String.format(
"%s=%s excluded=%s mode=%s",
parameter.getName(),
parameter.getValue(),
parameter.getExcluded(),
parameter.getMode()
)
)
.collect(Collectors.joining("\n"))
);

assertThat(parameters)
.extracting(Parameter::getName, Parameter::getValue, Parameter::getExcluded, Parameter::getMode)
.containsExactly(
tuple("Named", "1", false, Parameter.Mode.DEFAULT),
tuple("Hidden", "2", true, Parameter.Mode.HIDDEN),
tuple("third", "3", null, null)
);
});
}

@Test
void shouldUseReflectionNameWhenFrameworkNameIsNotProvided() throws NoSuchMethodException {
step("Create parameters with reflection names and verify @Param metadata", () -> {
final Method method = getClass().getDeclaredMethod(
"methodWithParameters",
String.class,
String.class,
String.class
);
final List<Parameter> parameters = Arrays.asList(
ParameterUtils.createParameter(method.getParameters()[0], "1"),
ParameterUtils.createParameter(method.getParameters()[1], "2"),
ParameterUtils.createParameter(method.getParameters()[2], "3")
);

assertThat(parameters)
.extracting(Parameter::getName, Parameter::getValue, Parameter::getExcluded, Parameter::getMode)
.containsExactly(
tuple("Named", "1", false, Parameter.Mode.DEFAULT),
tuple("Hidden", "2", true, Parameter.Mode.HIDDEN),
tuple("plain", "3", null, null)
);
});
}

@Test
void shouldRejectNullFrameworkDefaultName() throws NoSuchMethodException {
step("Verify framework default name is required", () -> {
final Method method = getClass().getDeclaredMethod(
"methodWithParameters",
String.class,
String.class,
String.class
);

assertThatNullPointerException()
.isThrownBy(() -> ParameterUtils.createParameter(method.getParameters()[0], "1", null))
.withMessage("defaultName");
});
}

void methodWithParameters(@Param("Named") final String named,
@Param(
name = "Hidden",
excluded = true,
mode = Parameter.Mode.HIDDEN
) final String hidden,
final String plain) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import io.qameta.allure.testng.config.AllureTestNgConfig;
import io.qameta.allure.util.AnnotationUtils;
import io.qameta.allure.util.ObjectUtils;
import io.qameta.allure.util.ParameterUtils;
import io.qameta.allure.util.ResultsUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -836,9 +837,9 @@ private String getUniqueUuid(final IAttributes suite) {
private List<Parameter> getParameters(final ITestContext context,
final ITestNGMethod method,
final Object... parameters) {
final Map<String, String> result = new HashMap<>(
context.getCurrentXmlTest().getAllParameters()
);
final Map<String, Parameter> result = new HashMap<>();
context.getCurrentXmlTest().getAllParameters()
.forEach((name, value) -> result.put(name, createParameter(name, value)));
final Object instance = method.getInstance();
if (nonNull(instance)) {
Stream.of(instance.getClass().getDeclaredFields())
Expand All @@ -851,7 +852,7 @@ private List<Parameter> getParameters(final ITestContext context,
try {
field.setAccessible(true);
final String value = ObjectUtils.toString(field.get(instance));
result.put(name, value);
result.put(name, createParameter(name, value));
} catch (IllegalAccessException e) {
LOGGER.debug("Could not access field value");
}
Expand All @@ -869,9 +870,7 @@ private List<Parameter> getParameters(final ITestContext context,
.map(Parameters::value)
.orElse(new String[]{});

final String[] reflectionNames = Stream.of(m.getParameters())
.map(java.lang.reflect.Parameter::getName)
.toArray(String[]::new);
final java.lang.reflect.Parameter[] reflectionParameters = m.getParameters();

int skippedCount = 0;
for (int i = 0; i < parameterTypes.length; i++) {
Expand All @@ -882,20 +881,23 @@ private List<Parameter> getParameters(final ITestContext context,
}

final int indexFromAnnotation = i - skippedCount;
if (indexFromAnnotation < providedNames.length) {
result.put(providedNames[indexFromAnnotation], ObjectUtils.toString(parameters[i]));
continue;
}

if (i < reflectionNames.length) {
result.put(reflectionNames[i], ObjectUtils.toString(parameters[i]));
final String defaultName = indexFromAnnotation < providedNames.length
? providedNames[indexFromAnnotation]
: reflectionParameters[i].getName();
final Parameter parameter = ParameterUtils.createParameter(
reflectionParameters[i],
parameters[i],
defaultName
);
if (nonNull(parameter.getName())) {
result.remove(defaultName);
result.put(parameter.getName(), parameter);
}
}

});

return result.entrySet().stream()
.map(entry -> createParameter(entry.getKey(), entry.getValue()))
return result.values().stream()
.collect(Collectors.toList());
}

Expand Down
Loading
Loading