Skip to content

Commit

Permalink
Added support for JUnit 5 @ArgumentsSource annotation
Browse files Browse the repository at this point in the history
  • Loading branch information
wakaleo committed Sep 1, 2023
1 parent e69a4e8 commit 526606e
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@

import au.com.bytecode.opencsv.CSVReader;
import com.google.common.base.Splitter;
import net.bytebuddy.implementation.MethodCall;
import net.serenitybdd.junit5.datadriven.JUnit5CSVTestDataSource;
import net.thucydides.model.environment.SystemEnvironmentVariables;
import net.thucydides.model.domain.DataTable;
import net.thucydides.model.util.EnvironmentVariables;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.*;
import org.slf4j.Logger;
Expand Down Expand Up @@ -157,11 +159,43 @@ private void fillDataTablesFromMethodSource(Map<String, DataTable> dataTables, M
}

private void fillDataTablesFromArgumentsSource(Map<String, DataTable> dataTables, Method testDataMethod) {
String columnNamesString = createColumnNamesFromParameterNames(testDataMethod);
String dataTableName = testDataMethod.getDeclaringClass().getCanonicalName() + "." + testDataMethod.getName();
List<List<Object>> parametersAsListsOfObjects = listOfObjectsFromMethodSource(testDataMethod);
logger.info("GetParameterTablesFromMethodSource: Put parameter dataTableName " + dataTableName + " " + parametersAsListsOfObjects);
dataTables.put(dataTableName, createParametersTableFrom(columnNamesString, parametersAsListsOfObjects));
try {

ArgumentsSource argumentsSource = testDataMethod.getAnnotation(ArgumentsSource.class);
ArgumentsProvider argumentProvider = argumentsSource.value().getConstructor().newInstance();

// We don't have the extensionContext here, so we can't use the extensionContext to get the arguments
// If the extensionContext is needed, this will fail, and we will fall back to the old way of getting the arguments
List<?> arguments = argumentProvider.provideArguments(null).map(Arguments::get).collect(Collectors.toList());

// If there are no arguments...actually not sure if this can happen
if (arguments.isEmpty()) {
return;
}

// The arguments can be either a list of objects or a list of arrays.
// If it is a list of arrays, we need to convert it to a list of objects
List<List<Object>> argumentRows = new ArrayList<>();
if (arguments.get(0) instanceof Object[]) {
for (Object[] argument : (List<Object[]>) arguments) {
argumentRows.add(Arrays.asList(argument));
}
} else {
for (Object argument : arguments) {
argumentRows.add(Collections.singletonList(argument));
}
}

// We don't have explicit column names, so we will use the default column names
List<String> columns = numberedColumnHeadings(argumentRows.get(0).size());

String dataTableName = testDataMethod.getDeclaringClass().getCanonicalName() + "." + testDataMethod.getName();
dataTables.put(dataTableName, createParametersTableFrom(columns, argumentRows));

} catch (NullPointerException ignored) {
} catch (Exception e) {
throw new RuntimeException(e);
}
}

List<Method> findTestDataMethods() {
Expand Down Expand Up @@ -341,6 +375,12 @@ private DataTable createParametersTableFrom(String columnNamesString, List<List<
.build();
}

private DataTable createParametersTableFrom(List<String> columnNames, List<List<Object>> parametersList) {
return DataTable.withHeaders(columnNames)
.andRows(parametersList)
.build();
}

private List<String> split(String columnNamesString, int numberOfColumns) {
if (StringUtils.isEmpty(columnNamesString)) {
return numberedColumnHeadings(numberOfColumns);
Expand All @@ -362,7 +402,8 @@ private boolean findParameterizedTests(Method method) {
|| isACsvFileSourceAnnotatedMethod(method)
|| isACsvSourceAnnotatedMethod(method)
|| isAEnumSourceAnnotatedMethod(method)
|| isAMethodSourceAnnotatedMethod(method));
|| isAMethodSourceAnnotatedMethod(method)
|| isAnArgumentsSourceAnnotatedMethod(method));
}

private boolean isAValueSourceAnnotatedMethod(Method method) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package net.serenitybdd.junit5.samples.integration;

import net.serenitybdd.junit5.SerenityJUnit5Extension;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;

import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@ExtendWith(SerenityJUnit5Extension.class)
public class Junit5ParameterizedArgumentsTest {

@ParameterizedTest
@ArgumentsSource(Junit5ParameterizedArgumentsTest.StringArgumentsProvider.class)
void shouldCalculateResultsWithArgSource(String calculation) {
System.out.println(calculation);
}

public static class StringArgumentsProvider implements ArgumentsProvider {

@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
"1,+,2,3",
"7,-,3,4",
"3,*,2,6",
"10,/,2,5")
.map(Arguments::of);
}
}

@ParameterizedTest
@ArgumentsSource(Junit5ParameterizedArgumentsTest.MultiArgumentsProvider.class)
void shouldCalculateResultsWithMultipleArgSource(String a, String op, String b, String res) {
System.out.println(a + " " + op + " " + b + " = " + res);
}
public static class MultiArgumentsProvider implements ArgumentsProvider {

@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
new Object[]{"1","+","2","3"},
new Object[]{"7","-","3","4"}
)
.map(Arguments::of);
}
}

@ParameterizedTest
@ArgumentsSource(Junit5ParameterizedArgumentsTest.ExtensionContextArgumentsProvider.class)
void shouldCalculateResultsForArgumentSourceThatNeedsTheExtensionContext(String a, String op, String b, String res) {
System.out.println(a + " " + op + " " + b + " = " + res);
}
public static class ExtensionContextArgumentsProvider implements ArgumentsProvider {

@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
context.getDisplayName();
return Stream.of(
new Object[]{"1","+","2","3"},
new Object[]{"7","-","3","4"}
)
.map(Arguments::of);
}
}

}

0 comments on commit 526606e

Please sign in to comment.