Skip to content

Commit

Permalink
Enable Javadoc check + add javadoc for all classes (#13)
Browse files Browse the repository at this point in the history
Signed-off-by: Lukas Kral <[email protected]>
  • Loading branch information
im-konge authored Feb 6, 2024
1 parent 1450fb4 commit e0a6ea5
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 73 deletions.
36 changes: 18 additions & 18 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,24 @@
</execution>
</executions>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-javadoc-plugin</artifactId>-->
<!-- <version>${maven.javadoc.version}</version>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>attach-javadocs</id>-->
<!-- <goals>-->
<!-- <goal>jar</goal>-->
<!-- </goals>-->
<!-- <configuration>-->
<!-- <show>public</show>-->
<!-- <failOnError>true</failOnError>-->
<!-- <failOnWarnings>true</failOnWarnings>-->
<!-- </configuration>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.javadoc.version}</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<show>public</show>
<failOnError>true</failOnError>
<failOnWarnings>true</failOnWarnings>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,25 @@
import java.util.Map;
import java.util.regex.Pattern;

/**
* Main Test Docs Generator class of the module
* The DocGenerator generates Markdown files for each documented test-case inside the test-class
* For each test-class is created separate Markdown file - with the same name as the test-class
* All needed information is parsed from the particular @TestDoc annotation.
*/
public class DocGenerator {
private static final Pattern REMOVE_BEFORE_PACKAGE = Pattern.compile(".*java\\/");

/**
* Method that generates test documentation of the specified test-class.
* Lists all methods (test-cases) annotated by {@link TestDoc} inside the {@param testClass}, creates
* parent folders (if needed), new Markdown file for the class, and finally using {@link #createRecord(PrintWriter, TestDoc, String)} generates
* documentation for each test-case, written inside the newly created Markdown file.
*
* @param testClass for which the Markdown file is created and test-cases are documented
* @param classFilePath path of the Markdown 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)
Expand Down Expand Up @@ -60,6 +76,15 @@ public static void generate(Class<?> testClass, String classFilePath) throws IOE
}
}

/**
* Creates a single record of a test-case (test-method) inside the test-class
* The record contains: name of the test as header level 2, description, steps, 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 createRecord(PrintWriter write, TestDoc testDoc, String methodName) {
write.println();
write.println(Header.secondLevelHeader(methodName));
Expand All @@ -74,6 +99,15 @@ public static void createRecord(PrintWriter write, TestDoc testDoc, String metho
write.println(TextList.createUnorderedList(createUseCases(testDoc.usecases())));
}

/**
* For the provided list of steps creates table with following columns:
* - Step - number of the current step
* - Action - action done during the step
* - Result - expected result of the step
*
* @param steps list of steps of the test-case
* @return String representation of table in Markdown
*/
private static String createTableOfSteps(TestDoc.Step[] steps) {
List<String> tableRows = new ArrayList<>();
List<String> headers = List.of("Step", "Action", "Result");
Expand All @@ -85,29 +119,56 @@ private static String createTableOfSteps(TestDoc.Step[] steps) {
return Table.createTable(headers, tableRows);
}

/**
* Creates list of use-cases for the particular test-case in format - `use-case`
* @param usecases list of usecases from the {@link TestDoc} annotation
* @return list of usecases in {@link List<String>}
*/
private static List<String> createUseCases(TestDoc.Usecase[] usecases) {
List<String> usesText = new ArrayList<>();
Arrays.stream(usecases).forEach(usecase -> usesText.add("`" + usecase.id() + "`"));

return usesText;
}

/**
* On specified {@param filePath} lists all classes and returns them in Map, where key is target
* path, where the Markdown file will be created, and value is package with class name available
* on classpath
* Also excludes files that should not be considered for documentation (currently just "AbstractST")
* @param filePath path where are all test-classes present
* @param generatePath "prefix" path where the documentation should be generated into
* @return Map with test-classes info from the {@param filePath}
*/
static Map<String, String> getTestClassesWithTheirPath(String filePath, String generatePath) {
Map<String, String> classes = new HashMap<>();

try {
Files.list(Paths.get(filePath))
.filter(file -> !file.getFileName().toString().contains("AbstractST"))
.forEach(path -> {
classes.putAll(getClassesForPackage(classes, path, generatePath));
});
.forEach(path -> classes.putAll(getClassesForPackage(classes, path, generatePath)));
} catch (IOException exception) {
throw new RuntimeException(exception);
}

return classes;
}

/**
* Updates Map ({@param classes}) with info about classes inside {@param packagePath}.
* It goes through all files inside the {@param packagePath} and does two things:
* - in case that file is directory (another package), it recursively calls itself and adds all info needed for all files
* inside the directory
* - otherwise adds key/value record in the map
* - key -> path in which the particular `.md` file will be generated, typically {@param generatePath}/{@code classPackagePath}
* - f.e. -> ./test-docs/path/to/my/package/TestClassST
* - value -> path for the particular test class -> in package format, available on classpath
* - f.e. -> path.to.my.package.TestClassST
* @param classes Map that should be updated with test-classes info
* @param packagePath path on which the files and classes should be listed
* @param generatePath "prefix" path where the documentation should be generated into
* @return updated Map with test-classes info from the {@param packagePath}
*/
private static Map<String, String> getClassesForPackage(Map<String, String> classes, Path packagePath, String generatePath) {
try {
Files.list(packagePath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,50 @@
import static io.skodjob.DocGenerator.generate;
import static io.skodjob.DocGenerator.getTestClassesWithTheirPath;

/**
* DocGeneratorMojo class for Maven plugin handling
*/
@Mojo(
name = "test-docs-generator",
defaultPhase = LifecyclePhase.COMPILE,
requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME
)
public class DocGeneratorMojo extends AbstractMojo {

/**
* Path where are all test-classes stored
*/
@Parameter(property = "filePath", defaultValue = "./test", required = true, readonly = true)
String filePath;

/**
* Path where the test documentation should be generated to
*/
@Parameter(property = "generatePath", defaultValue = "./test-docs", required = true, readonly = true)
String generatePath;

/**
* Pointer to Maven project
* Defaults to current project
*/
@Parameter(defaultValue = "${project}", readonly = true)
MavenProject project;

/**
* Descriptor of the plugin
* Defaults to current plugin
*/
@Parameter(defaultValue = "${plugin}", readonly = true)
PluginDescriptor descriptor;

/**
* Method for the execution of the test-docs-generator Maven plugin
* Generates documentation of test-cases based on specified parameters:
* - {@link #filePath}
* - {@link #generatePath}
* - {@link #project}
* - {@link #descriptor}
*/
public void execute() {

getLog().info("Starting generator");
Expand Down Expand Up @@ -81,6 +106,14 @@ public void execute() {
getLog().info("Done");
}

/**
* It goes through all files inside the {@param directory} and does two things:
* - in case that file is directory (another package), it recursively calls itself and adds all .jar files to the classPath
* - otherwise adds the .jar files to classPath
* @param directory where the files are listed
* @param classRealm realm containing all libs set on classPath, from where the test-classes will be loaded
* @throws MalformedURLException during URL construction
*/
public void addJarFilesToClassPath(File directory, ClassRealm classRealm) throws MalformedURLException {
// Check if the provided file is a directory
if (!directory.isDirectory()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,86 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Annotation collecting all information about the test-case.
* Currently, we can specify following:
* - description
* - steps
* - usecases
*
* Example usage:
* ```
* \@TestDoc(
* description = @Desc("Test checking that the application works as expected"),
* steps = {
* \@Step(value = "Create object instance", expected = "Instance of an object is created"),
* \@Step(value = "Do a magic trick", expected = "Magic trick is done with success"),
* \@Step(value = "Clean up the test case", expected = "Everything is cleared")
* },
* usecases = {
* \@Usecase(id = "core")
* }
* )
* void testMyCode(ExtensionContext extensionContext) {
* }
* ```
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface TestDoc {

/**
* Description of particular test-case
* @return description in {@link Desc}
*/
Desc description();
/**
* Array of steps done in the test-case
* @return array of steps in {@link Step}
*/
Step[] steps();

/**
* Array of use-cases covered by test-case
* @return array of use-cases in {@link Usecase}
*/
Usecase[] usecases();

/**
* Interface for setting description inside the {@link TestDoc} annotation
*/
@interface Desc {
/**
* Description of the test-case stored inside `value` field
* @return description in String
*/
String value();
}

/**
* Interface for setting step inside the {@link TestDoc} annotation
*/
@interface Step {
/**
* Step of the test-case stored inside `value` field
* @return step in String
*/
String value();

/**
* Expected outcome of the particular step in test-case
* @return expected outcome in String
*/
String expected();
}

/**
* Interface for setting use-case inside the {@link TestDoc} annotation
*/
@interface Usecase {
/**
* ID of the use-case, which is covered by the test-case
* @return ID of the use-case in String
*/
String id();
String note() default "";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,26 @@
*/
package io.skodjob.markdown;

/**
* Class responsible for creating representation of Markdown headers in text format, returned as String
*/
public class Header {

/**
* Method for creating first level header containing {@param text}
* @param text that should be in first level header
* @return first level header with {@param text}
*/
public static String firstLevelHeader(String text) {
return "# " + text;
}

/**
* Method for creating second level header containing {@param text}
* @param text that should be in second level header
* @return second level header with {@param text}
*/
public static String secondLevelHeader(String text) {
return "## " + text;
}

public static String thirdLevelHeader(String text) {
return "### " + text;
}
}
Loading

0 comments on commit e0a6ea5

Please sign in to comment.