-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add fmf generator to allow users to generate fmf files from test docs (…
…#21) Signed-off-by: Jakub Stejskal <[email protected]>
- Loading branch information
Showing
8 changed files
with
360 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
158 changes: 158 additions & 0 deletions
158
test-docs-generator-maven-plugin/src/main/java/io/skodjob/FmfGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
/* | ||
* Copyright Skodjob authors. | ||
* License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). | ||
*/ | ||
package io.skodjob; | ||
|
||
import io.skodjob.annotations.Step; | ||
import io.skodjob.annotations.TestDoc; | ||
import io.skodjob.annotations.TestTag; | ||
import io.skodjob.annotations.UseCase; | ||
import io.skodjob.common.Utils; | ||
import org.yaml.snakeyaml.DumperOptions; | ||
import org.yaml.snakeyaml.Yaml; | ||
|
||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
import java.lang.reflect.Method; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
|
||
/** | ||
* The FmfGenerator generates FMF files for each documented test-case inside the test-class | ||
* For each test-class is created separate FMF file - with the same name as the test-class | ||
* All needed information is parsed from the particular @TestDoc annotation. | ||
*/ | ||
public class FmfGenerator { | ||
|
||
/** | ||
* Generates test documentation in fmf format. | ||
* Lists all methods (test-cases) annotated by {@link TestDoc} inside the {@param testClass}, creates | ||
* parent folders (if needed), new FMF file for the class, and after that generates test-suite documentation using | ||
* {@link #generateDocumentationForTestCases(PrintWriter, List)}, all written inside the newly created Markdown file. | ||
* | ||
* @param testClass for which the FMF file is created and test-cases are documented | ||
* @param classFilePath path of the FMF file | ||
* @throws IOException during file creation | ||
*/ | ||
public static void generate(Class<?> testClass, String classFilePath) throws IOException { | ||
List<Method> methods = Arrays.stream(testClass.getDeclaredMethods()) | ||
.filter(method -> method.getAnnotation(TestDoc.class) != null) | ||
.toList(); | ||
|
||
if (!methods.isEmpty()) { | ||
PrintWriter printWriter = Utils.createFilesForTestClass(classFilePath); | ||
|
||
generateDocumentationForTestCases(printWriter, methods); | ||
|
||
printWriter.close(); | ||
} | ||
} | ||
|
||
/** | ||
* Generates documentation records for each test-cases (test-methods) from {@param methods} | ||
* @param writer file writer | ||
* @param methods containing {@link TestDoc} annotation | ||
*/ | ||
private static void generateDocumentationForTestCases(PrintWriter writer, List<Method> methods) { | ||
if (!methods.isEmpty()) { | ||
methods.forEach(method -> { | ||
TestDoc testDoc = method.getAnnotation(TestDoc.class); | ||
if (testDoc != null) { | ||
createTestRecord(writer, testDoc, method.getName()); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Creates a single record of a test-case (test-method) inside the test-class | ||
* The record contains: name of the test, description, steps, tags, and use-cases obtained from the | ||
* {@param testDoc}. | ||
* | ||
* @param write file writer | ||
* @param testDoc annotation containing all @TestDoc objects, from which is the record generated | ||
* @param methodName name of the test-case containing {@param testDoc} | ||
*/ | ||
public static void createTestRecord(PrintWriter write, TestDoc testDoc, String methodName) { | ||
|
||
Map<String, Object> testCaseData = new HashMap<>(); | ||
testCaseData.put("summary", methodName); | ||
// Make description multiline out of the box | ||
String description = String.format("%s\n", testDoc.description().value()); | ||
testCaseData.put("description", description); | ||
if (!Objects.equals(testDoc.contact().name(), "")) { | ||
testCaseData.put("contact", String.format("%s <%s>", testDoc.contact().name(), testDoc.contact().email())); | ||
} | ||
if (testDoc.tags().length > 0) { | ||
testCaseData.put("tags", createTags(testDoc.tags())); | ||
} | ||
if (testDoc.useCases().length > 0) { | ||
testCaseData.put("usecases", createUseCases(testDoc.useCases())); | ||
} | ||
if (testDoc.steps().length > 0) { | ||
testCaseData.put("steps", createListOfSteps(testDoc.steps())); | ||
} | ||
|
||
Map<String, Object> yamlData = new HashMap<>(); | ||
String testCaseKey = String.format("/%s", methodName); | ||
yamlData.put(testCaseKey, testCaseData); | ||
|
||
// Serialize the data to YAML | ||
DumperOptions options = new DumperOptions(); | ||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); | ||
Yaml yaml = new Yaml(options); | ||
|
||
yaml.dump(yamlData, write); | ||
write.println(); | ||
} | ||
|
||
/** | ||
* For the provided list of steps creates table with following columns: | ||
* | ||
* @param steps list of steps of the test-case | ||
* @return List of maps that represents all steps of teh test-case | ||
*/ | ||
private static List<Map<String, String>> createListOfSteps(Step[] steps) { | ||
|
||
List<Map<String, String>> listOfSteps = new ArrayList<>(); | ||
|
||
for (Step step : steps) { | ||
Map<String, String> stepMap = new HashMap<>(); | ||
stepMap.put("step", step.value()); | ||
stepMap.put("result", step.expected()); | ||
listOfSteps.add(stepMap); | ||
} | ||
|
||
return listOfSteps; | ||
} | ||
|
||
/** | ||
* Creates list of use-cases for the particular test-case | ||
* @param usecases list of usecases from the {@link TestDoc} annotation | ||
* @return list of usecases in {@link List<String>} | ||
*/ | ||
private static List<String> createUseCases(UseCase[] usecases) { | ||
List<String> fmfUsecases = new ArrayList<>(); | ||
Arrays.stream(usecases).forEach(usecase -> fmfUsecases.add(usecase.id())); | ||
|
||
return fmfUsecases; | ||
} | ||
|
||
/** | ||
* Creates list of tags for the particular test-case | ||
* @param testTags list of tags from the {@link TestDoc} annotation | ||
* @return list of tags in {@link List<String>} | ||
*/ | ||
private static List<String> createTags(TestTag[] testTags) { | ||
List<String> fmfTags = new ArrayList<>(); | ||
Arrays.stream(testTags).forEach(testTag -> fmfTags.add(testTag.value())); | ||
|
||
return fmfTags; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.