Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Javadoc check + add javadoc for all classes #13

Merged
merged 1 commit into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,24 +154,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
Loading