Skip to content

Commit

Permalink
Minor UI enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
wakaleo committed Sep 1, 2023
1 parent 94af905 commit ba46897
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 85 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<commons.net.version>3.9.0</commons.net.version>
<commons.codec.version>1.16.0</commons.codec.version>
<freemarker.version>2.3.32</freemarker.version>
<selenium.version>4.11.0</selenium.version>
<selenium.version>4.12.0</selenium.version>
<htmlunit.driver.version>4.10.0</htmlunit.driver.version>
<jsonassert.version>1.5.1</jsonassert.version>
<jsoup.version>1.15.4</jsoup.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class JUnit5DataDrivenAnnotations {

private final Class testClass;

private final Map<String,DataTable> parameterTables;
private final Map<String, DataTable> parameterTables;

public static JUnit5DataDrivenAnnotations forClass(final Class testClass) {
return new JUnit5DataDrivenAnnotations(testClass);
Expand All @@ -49,29 +49,26 @@ public static JUnit5DataDrivenAnnotations forClass(final Class testClass) {
this.parameterTables = generateParameterTables();
}

public Map<String,DataTable> getParameterTables() {
public Map<String, DataTable> getParameterTables() {
return parameterTables;
}

private Map<String,DataTable> generateParameterTables() {
private Map<String, DataTable> generateParameterTables() {
List<Method> allMethods = findTestDataMethods();
Map<String,DataTable> dataTables = new HashMap<>();
for(Method testDataMethod : allMethods) {
if(isAValueSourceAnnotatedMethod(testDataMethod)) {
Map<String, DataTable> dataTables = new HashMap<>();
for (Method testDataMethod : allMethods) {
if (isAValueSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromValueSource(dataTables, testDataMethod);
}
else if(isACsvFileSourceAnnotatedMethod(testDataMethod))
{
fillDataTablesFromCsvFileSource(dataTables,testDataMethod);
}
else if (isAEnumSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromEnumSource(dataTables,testDataMethod);
}
else if (isACsvSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromCsvSource(dataTables,testDataMethod);
}
else if (isAMethodSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromMethodSource(dataTables,testDataMethod);
} else if (isACsvFileSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromCsvFileSource(dataTables, testDataMethod);
} else if (isAEnumSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromEnumSource(dataTables, testDataMethod);
} else if (isACsvSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromCsvSource(dataTables, testDataMethod);
} else if (isAMethodSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromMethodSource(dataTables, testDataMethod);
} else if (isAnArgumentsSourceAnnotatedMethod(testDataMethod)) {
fillDataTablesFromArgumentsSource(dataTables, testDataMethod);
}

}
Expand Down Expand Up @@ -99,7 +96,7 @@ private void fillDataTablesFromCsvSource(Map<String, DataTable> dataTables, Meth
if (csvSource.textBlock() != null && !csvSource.textBlock().isEmpty()) {
fillDataTablesFromCsvSourceTextBlock(dataTables, testDataMethod);
} else {
fillDataTablesFromCsvSourceValues(dataTables,testDataMethod);
fillDataTablesFromCsvSourceValues(dataTables, testDataMethod);
}
}

Expand All @@ -115,7 +112,7 @@ private void fillDataTablesFromCsvSourceTextBlock(Map<String, DataTable> dataTab
String dataTableName = testDataMethod.getDeclaringClass().getCanonicalName() + "." + testDataMethod.getName();

String testData = csvSource.textBlock();
List<List<Object>> rows = listOfCsvObjectsFrom(testData.split("\\R"),deliminator);
List<List<Object>> rows = listOfCsvObjectsFrom(testData.split("\\R"), deliminator);
logger.debug("GetParameterTables: Put parameter dataTableName " + dataTableName + " -- " + rows);
dataTables.put(dataTableName, createParametersTableFrom(columnNamesString, rows));
}
Expand All @@ -136,23 +133,30 @@ private void fillDataTablesFromCsvFileSource(Map<String, DataTable> dataTables,
try {
JUnit5CSVTestDataSource csvTestDataSource = new JUnit5CSVTestDataSource(Arrays.asList(paths), CSVReader.DEFAULT_SEPARATOR);
List<Map<String, String>> data = csvTestDataSource.getData();
List<List<Object>> rows = new ArrayList<>();
for(Map<String,String> dataRowMap : data)
{
List<List<Object>> rows = new ArrayList<>();
for (Map<String, String> dataRowMap : data) {
ArrayList<Object> dataRow = new ArrayList<>();
for(String header : csvTestDataSource.getHeaders()) {
for (String header : csvTestDataSource.getHeaders()) {
dataRow.add(dataRowMap.get(header));
}
rows.add(dataRow);
}
logger.debug("GetParameterTablesCSV: Put parameter dataTableName " + dataTableName);
dataTables.put(dataTableName, createParametersTableFrom(columnNamesString,rows));
dataTables.put(dataTableName, createParametersTableFrom(columnNamesString, rows));
} catch (IOException e) {
logger.error("Cannot load csv resource ",e);
logger.error("Cannot load csv resource ", e);
}
}

private void fillDataTablesFromMethodSource(Map<String, DataTable> dataTables, Method testDataMethod) {
private void fillDataTablesFromMethodSource(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));
}

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);
Expand Down Expand Up @@ -185,14 +189,14 @@ String createColumnNamesFromParameterNames(Method method) {
}

List<List<Object>> listOfObjectsFromMethodSource(Method testDataMethod) {
MethodSource methodSourceAnnotation = testDataMethod.getAnnotation(MethodSource.class);
MethodSource methodSourceAnnotation = testDataMethod.getAnnotation(MethodSource.class);
String[] value = methodSourceAnnotation.value();
String methodName;
boolean staticMethodUsed = isStaticMethodUsed(testDataMethod);
if(value != null && (value.length > 0) && (!value[0].isEmpty())) {
if (value != null && (value.length > 0) && (!value[0].isEmpty())) {
List<String> methodNames = Arrays.asList(value);
methodName = methodNames.get(0);
if(methodName.indexOf("#") > 0) { //external class source
if (methodName.indexOf("#") > 0) { //external class source
List<List<Object>> result = getListOfObjectsFromExternalClassSource(methodName);
if (result != null) return result;
}
Expand All @@ -212,18 +216,18 @@ List<List<Object>> listOfObjectsFromMethodSource(Method testDataMethod) {
// }
// return result.map(argument->Arrays.asList(argument.get())).collect(Collectors.toList());
Stream<?> result = null;
if(staticMethodUsed) {
result = (Stream<?>)factoryMethod.invoke(null);
if (staticMethodUsed) {
result = (Stream<?>) factoryMethod.invoke(null);
} else {
result = (Stream<?>)factoryMethod.invoke(testDataMethod.getDeclaringClass().getConstructor().newInstance());
result = (Stream<?>) factoryMethod.invoke(testDataMethod.getDeclaringClass().getConstructor().newInstance());
}
return result.map(argument -> convertToListOfParameters(argument)).collect(Collectors.toList());
//return result.map(argument->Arrays.asList(argument.get())).collect(Collectors.toList());
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
logger.error("Cannot get list of objects from method source ", e);
}
} catch(NoSuchMethodException ex) {
logger.error("No static method with the name " + methodName + " found ",ex);
} catch (NoSuchMethodException ex) {
logger.error("No static method with the name " + methodName + " found ", ex);
}
return null;
}
Expand All @@ -246,64 +250,65 @@ private boolean isStaticMethodUsed(Method testDataMethod) {
private List<List<Object>> getListOfObjectsFromExternalClassSource(String methodName) {
Method factoryMethod;
String externalParameterFactoryClassName = methodName.substring(0, methodName.indexOf("#"));
String externalParameterFactoryMethodName = methodName.substring(methodName.indexOf("#") +1);
String externalParameterFactoryMethodName = methodName.substring(methodName.indexOf("#") + 1);
try {
Class externalClassFactory = Class.forName(externalParameterFactoryClassName);
factoryMethod = externalClassFactory.getDeclaredMethod(externalParameterFactoryMethodName);
factoryMethod.setAccessible(true);
Stream<Arguments> result = (Stream<Arguments>)factoryMethod.invoke(null);
return result.map(argument->Arrays.asList(argument.get())).collect(Collectors.toList());
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Stream<Arguments> result = (Stream<Arguments>) factoryMethod.invoke(null);
return result.map(argument -> Arrays.asList(argument.get())).collect(Collectors.toList());
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |
InvocationTargetException e) {
logger.error("Cannot found external parameter factory class method", e);
}
return null;
}

List<List<Object>> listOfObjectsFromValueSource(Method testDataMethod) {
ValueSource annotation = testDataMethod.getAnnotation(ValueSource.class);
if(ArrayUtils.isNotEmpty(annotation.strings()))
if (ArrayUtils.isNotEmpty(annotation.strings()))
return listOfObjectsFrom(annotation.strings());
else if(ArrayUtils.isNotEmpty(annotation.bytes()))
else if (ArrayUtils.isNotEmpty(annotation.bytes()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.bytes()));
else if(ArrayUtils.isNotEmpty(annotation.chars()))
else if (ArrayUtils.isNotEmpty(annotation.chars()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.chars()));
else if(ArrayUtils.isNotEmpty(annotation.doubles()))
else if (ArrayUtils.isNotEmpty(annotation.doubles()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.doubles()));
else if(ArrayUtils.isNotEmpty(annotation.floats()))
else if (ArrayUtils.isNotEmpty(annotation.floats()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.floats()));
else if(ArrayUtils.isNotEmpty(annotation.ints()))
else if (ArrayUtils.isNotEmpty(annotation.ints()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.ints()));
else if(ArrayUtils.isNotEmpty(annotation.shorts()))
else if (ArrayUtils.isNotEmpty(annotation.shorts()))
return listOfObjectsFrom(ArrayUtils.toObject(annotation.shorts()));
else if(ArrayUtils.isNotEmpty(annotation.classes()))
else if (ArrayUtils.isNotEmpty(annotation.classes()))
return listOfObjectsFrom(annotation.classes());
return null;
}

List<List<Object>> listOfCsvObjectsFrom(Method testDataMethod){
List<List<Object>> listOfCsvObjectsFrom(Method testDataMethod) {
CsvSource annotation = testDataMethod.getAnnotation(CsvSource.class);
String annotationDelimiter = annotation.delimiterString();
String delimiter = (annotationDelimiter != null && !annotationDelimiter.isEmpty()) ? annotationDelimiter : ",";
return listOfCsvObjectsFrom(annotation.value(), delimiter);
}

private List<List<Object>> listOfCsvObjectsFrom(Object[] parameters,String delimiter) {
private List<List<Object>> listOfCsvObjectsFrom(Object[] parameters, String delimiter) {
List<List<Object>> ret = new ArrayList<>();
for(Object parameter : parameters) {
for (Object parameter : parameters) {
String[] split = ((String) parameter).split(Pattern.quote(delimiter));
ret.add(Arrays.asList(split));
}
return ret;
}

List<List<Object>> listOfEnumSourceObjectsFrom(Method testDataMethod){
List<List<Object>> listOfEnumSourceObjectsFrom(Method testDataMethod) {
EnumSource annotation = testDataMethod.getAnnotation(EnumSource.class);
Class<? extends Enum<?>> enumValue = annotation.value();
if(annotation.value() != null) {
if (annotation.value() != null) {
Enum<?>[] enumConstants = enumValue.getEnumConstants();
EnumSource.Mode mode = annotation.mode();
String[] names = annotation.names();
if(ArrayUtils.isNotEmpty(names)) {
if (ArrayUtils.isNotEmpty(names)) {
Set<String> namesSet = new HashSet(Arrays.asList(names));
Set<String> selectedNamesSet = new HashSet(Arrays.asList(enumConstants).stream().map(Enum::toString).collect(Collectors.toList()));
switch (mode) {
Expand Down Expand Up @@ -360,23 +365,27 @@ private boolean findParameterizedTests(Method method) {
|| isAMethodSourceAnnotatedMethod(method));
}

private boolean isAValueSourceAnnotatedMethod(Method method){
private boolean isAValueSourceAnnotatedMethod(Method method) {
return method.getAnnotation(ValueSource.class) != null;
}

private boolean isAEnumSourceAnnotatedMethod(Method method){
private boolean isAEnumSourceAnnotatedMethod(Method method) {
return method.getAnnotation(EnumSource.class) != null;
}

private boolean isACsvSourceAnnotatedMethod(Method method){
private boolean isACsvSourceAnnotatedMethod(Method method) {
return method.getAnnotation(CsvSource.class) != null;
}

private boolean isACsvFileSourceAnnotatedMethod(Method method){
private boolean isACsvFileSourceAnnotatedMethod(Method method) {
return method.getAnnotation(CsvFileSource.class) != null;
}

private boolean isAMethodSourceAnnotatedMethod(Method method){
private boolean isAMethodSourceAnnotatedMethod(Method method) {
return method.getAnnotation(MethodSource.class) != null;
}

private boolean isAnArgumentsSourceAnnotatedMethod(Method method) {
return method.getAnnotation(ArgumentsSource.class) != null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,35 +94,41 @@ private Stream<TestOutcome> supportedOutcomesFrom(List<TestOutcome> outcomes) {
private List<Requirement> loadRequirements() {
TestOutcomeLoader loader = new TestOutcomeLoader();
File outputDirectory = ConfiguredEnvironment.getConfiguration().getOutputDirectory();
List<TestOutcome> outcomes = loader.loadFrom(outputDirectory);

int maxRequirementsDepth = getMaxRequirementsDepthFrom(outcomes);
// If no output directory exists (yet), the test run is still in progress, so don't bother reading the requirements yet.
if (outputDirectory.exists()) {
List<TestOutcome> outcomes = loader.loadFrom(outputDirectory);

// Bottom-level requirements
Map<PathElements, Requirement> leafLevelRequirements = getLeafLevelRequirementsFrom(outcomes);
int maxRequirementsDepth = getMaxRequirementsDepthFrom(outcomes);

Set<PathElements> leafPathElements = leafLevelRequirements.keySet();
// Bottom-level requirements
Map<PathElements, Requirement> leafLevelRequirements = getLeafLevelRequirementsFrom(outcomes);

Map<PathElements, Requirement> requirementsByPath = new HashMap<>();
Set<PathElements> leafPathElements = leafLevelRequirements.keySet();

// Non-leaf requirements indexed by path
findPathElementsIn(outcomes).forEach(pathElements -> processPathElements(pathElements, maxRequirementsDepth, leafPathElements, leafLevelRequirements, requirementsByPath));
Map<PathElements, Requirement> requirementsByPath = new HashMap<>();

Collection<Requirement> allRequirements = requirementsByPath.values();
// Non-leaf requirements indexed by path
findPathElementsIn(outcomes).forEach(pathElements -> processPathElements(pathElements, maxRequirementsDepth, leafPathElements, leafLevelRequirements, requirementsByPath));

// Use the map to update the leaf requirements
updateParentFieldsIn(requirementsByPath, allRequirements);
Collection<Requirement> allRequirements = requirementsByPath.values();

// Make an alias for any leaf requirements that also appear in the non-leaf requirements.
// Use the map to update the leaf requirements
updateParentFieldsIn(requirementsByPath, allRequirements);

populateChildren(requirementsByPath, allRequirements);
// Make an alias for any leaf requirements that also appear in the non-leaf requirements.

RequirementCache.getInstance().indexRequirements(requirementsByPath);
populateChildren(requirementsByPath, allRequirements);

// Return a list of the top-level or leaf requirements with no parent elements
return allRequirements.stream()
.filter(requirement -> StringUtils.isEmpty(requirement.getParent()))
.collect(Collectors.toList());
RequirementCache.getInstance().indexRequirements(requirementsByPath);

// Return a list of the top-level or leaf requirements with no parent elements
return allRequirements.stream()
.filter(requirement -> StringUtils.isEmpty(requirement.getParent()))
.collect(Collectors.toList());
} else {
return new ArrayList<>();
}
}

private void processPathElements(PathElements pathElements, int maxRequirementsDepth, Set<PathElements> leafPathElements,
Expand Down
Loading

0 comments on commit ba46897

Please sign in to comment.