From e0a6ea5e4333c2cef5ef759767787180292f6335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Kr=C3=A1l?= <53821852+im-konge@users.noreply.github.com> Date: Tue, 6 Feb 2024 18:14:10 +0100 Subject: [PATCH] Enable Javadoc check + add javadoc for all classes (#13) Signed-off-by: Lukas Kral --- pom.xml | 36 +++++----- .../java/io/skodjob/CommandLineOptions.java | 32 --------- .../main/java/io/skodjob/DocGenerator.java | 67 ++++++++++++++++++- .../java/io/skodjob/DocGeneratorMojo.java | 33 +++++++++ .../java/io/skodjob/annotations/TestDoc.java | 64 +++++++++++++++++- .../main/java/io/skodjob/markdown/Header.java | 17 +++-- .../main/java/io/skodjob/markdown/Table.java | 18 ++++- .../java/io/skodjob/markdown/TextList.java | 17 +++-- .../java/io/skodjob/markdown/TextStyle.java | 12 ++-- 9 files changed, 223 insertions(+), 73 deletions(-) delete mode 100644 test-docs-generator-maven-plugin/src/main/java/io/skodjob/CommandLineOptions.java diff --git a/pom.xml b/pom.xml index c1a2feb..5119db2 100644 --- a/pom.xml +++ b/pom.xml @@ -156,24 +156,24 @@ - - - - - - - - - - - - - - - - - - + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.javadoc.version} + + + attach-javadocs + + jar + + + public + true + true + + + + org.apache.maven.plugins maven-plugin-plugin diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/CommandLineOptions.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/CommandLineOptions.java deleted file mode 100644 index 97c9f1e..0000000 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/CommandLineOptions.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright Skodjob authors. - * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html). - */ -package io.skodjob; - -public class CommandLineOptions { - private String filePath; - private String generatePath; - - public CommandLineOptions(String[] args) { - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - - if (arg.equals("--filePath")) { - filePath = args[++i]; - } else if (arg.equals("--generatePath")) { - generatePath = args[++i]; - } else if (arg.contains("--")) { - throw new RuntimeException("Unsupported command line option " + arg); - } - } - } - - public String getFilePath() { - return filePath; - } - - public String getGeneratePath() { - return generatePath; - } -} diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGenerator.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGenerator.java index 02917d8..94cda13 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGenerator.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGenerator.java @@ -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 methods = Arrays.stream(testClass.getDeclaredMethods()) .filter(method -> method.getAnnotation(TestDoc.class) != null) @@ -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)); @@ -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 tableRows = new ArrayList<>(); List headers = List.of("Step", "Action", "Result"); @@ -85,6 +119,11 @@ 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} + */ private static List createUseCases(TestDoc.Usecase[] usecases) { List usesText = new ArrayList<>(); Arrays.stream(usecases).forEach(usecase -> usesText.add("`" + usecase.id() + "`")); @@ -92,15 +131,22 @@ private static List createUseCases(TestDoc.Usecase[] usecases) { 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 getTestClassesWithTheirPath(String filePath, String generatePath) { Map 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); } @@ -108,6 +154,21 @@ static Map getTestClassesWithTheirPath(String filePath, String g 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 getClassesForPackage(Map classes, Path packagePath, String generatePath) { try { Files.list(packagePath) diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGeneratorMojo.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGeneratorMojo.java index fa6ecf5..ef43f3a 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGeneratorMojo.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/DocGeneratorMojo.java @@ -23,6 +23,9 @@ 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, @@ -30,18 +33,40 @@ ) 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"); @@ -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()) { diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/annotations/TestDoc.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/annotations/TestDoc.java index e6190d1..c7354d0 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/annotations/TestDoc.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/annotations/TestDoc.java @@ -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 ""; } } \ No newline at end of file diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Header.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Header.java index c28db09..a827bfa 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Header.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Header.java @@ -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; - } } diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Table.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Table.java index 0a7f06a..9b4b016 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Table.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/Table.java @@ -6,8 +6,17 @@ import java.util.List; +/** + * Class responsible for creating representation of Markdown table in text format, returned as String + */ public class Table { + /** + * Creates the Markdown table in text format, containing specified headers and rows + * @param headers list of headers that should be inside the table + * @param rows list of rows added to the table + * @return Markdown table in text format, returned as String + */ public static String createTable(List headers, List rows) { StringBuilder table = new StringBuilder(); @@ -23,11 +32,16 @@ public static String createTable(List headers, List rows) { return table.toString(); } + /** + * Creates a single row for {@param content} + * @param content of the row + * @return table row in text format, returned as String + */ public static String createRow(String... content) { StringBuilder row = new StringBuilder(); - for (int i = 0; i < content.length; i++) { - row.append("| ").append(content[i]); + for (String s : content) { + row.append("| ").append(s); } row.append(" |"); diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextList.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextList.java index 888e3f6..ace1bfb 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextList.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextList.java @@ -6,17 +6,16 @@ import java.util.List; +/** + * Class responsible for creating representation of Markdown lists in text format, returned as String + */ public class TextList { - public static String createOrderedList(List objects) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < objects.size(); i++) { - builder.append(i + 1 + ". " + objects.get(i) + "\n"); - } - - return builder.toString(); - } - + /** + * Creates the Markdown unordered list in text format, containing all from the {@param objects} + * @param objects list of objects that should be inside the unordered list + * @return Markdown unordered list in text format, returned as String + */ public static String createUnorderedList(List objects) { StringBuilder builder = new StringBuilder(); objects.forEach(object -> diff --git a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextStyle.java b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextStyle.java index 50022ed..3470533 100644 --- a/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextStyle.java +++ b/test-docs-generator-maven-plugin/src/main/java/io/skodjob/markdown/TextStyle.java @@ -4,13 +4,17 @@ */ package io.skodjob.markdown; +/** + * Class responsible for applying Markdown text styles to specified text, returned as String + */ public class TextStyle { + /** + * Method for adding bold style to specified {@param text} + * @param text that should be in bold style + * @return bold stylization for {@param text} + */ public static String boldText(String text) { return "**" + text + "**"; } - - public static String italicText(String text) { - return "_" + text + "_"; - } }