Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/**
* Orignal work: Copyright 2015 www.seleniumtests.com
* Modified work: Copyright 2016 www.infotel.com
* Copyright 2017-2019 B.Hecquet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.seleniumtests.util.helper;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.testng.annotations.Test;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseResult;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Modifier;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.Node.TreeTraversal;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.comments.Comment;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.ast.expr.MemberValuePair;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NormalAnnotationExpr;
import com.github.javaparser.ast.expr.ObjectCreationExpr;
import com.github.javaparser.ast.stmt.BlockStmt;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.seleniumtests.customexception.ConfigurationException;
import com.seleniumtests.util.StringUtility;
/**
* Class for creating test documentation, which can be imported into confluence through API
* It generates a template.confluence file which contains the formatted javadoc for each Test method and step
* https://support.atlassian.com/confluence-cloud/docs/insert-confluence-wiki-markup/
*
*/
public class AppTestDocumentation {
private static StringBuilder javadoc;
private static Map> stepsUsedInTests;
private static List steps;
private static List tests;
private static Integer searchedElements;
public static void main(String[] args) throws IOException {
System.setProperty("mavenExecution", "true");
stepsUsedInTests = new HashMap<>();
steps = new ArrayList<>();
tests = new ArrayList<>();
searchedElements = 0;
File srcDir = Paths.get(args[0].replace(File.separator, "/"), "src", "test", "java").toFile();
// find the root source path (folder where "tests" and "webpage" can be found
List rootFolders;
try (Stream files = Files.walk(Paths.get(srcDir.getAbsolutePath()))) {
rootFolders = files
.filter(Files::isDirectory)
.filter(p -> p.toAbsolutePath().resolve("tests").toFile().exists() && p.toAbsolutePath().resolve("webpage").toFile().exists())
.collect(Collectors.toList());
}
javadoc = new StringBuilder("Cette page référence l'ensemble des tests et des opération disponible pour l'application\n");
Path rootFolder = null;
if (rootFolders.isEmpty()) {
System.out.println("Cannot find a folder which contains 'tests' and 'webpage' subfolder. The project does not follow conventions");
javadoc.append("Cannot find a folder which contains 'tests' and 'webpage' subfolder. The project does not follow conventions");
System.exit(0);
} else {
rootFolder = rootFolders.get(0);
}
javadoc.append("
\n"
+ ""
+ "
");
StringBuilder pagesDoc = new StringBuilder();
pagesDoc.append("
\n", path.getFileName().toString()));
FileInputStream in = new FileInputStream(path.toAbsolutePath().toString());
// parse the file
ParseResult cu = new JavaParser().parse(in);
// prints the resulting compilation unit to default system output
cu.getResult().get().accept(new ClassVisitor(), "Pages");
WebPageMethodVisitor methodVisitor = new WebPageMethodVisitor();
cu.getResult().get().accept(methodVisitor, null);
for (Entry pageEntry: methodVisitor.getMethodInfo().entrySet()) {
pagesDoc.append(String.format("\n
Operation: %s
\n", pageEntry.getKey()));
pagesDoc.append(pageEntry.getValue());
}
}
private static class TestAttributeVisitor extends VoidVisitorAdapter {
Map attributes = new HashMap<>();
@Override
public void visit(NormalAnnotationExpr n, Void arg) {
for (MemberValuePair pair: n.getPairs()) {
if ("attributes".equals(pair.getNameAsString())) {
TestCustomAttributeVisitor taVisitor = new TestCustomAttributeVisitor();
pair.accept(taVisitor, null);
attributes = taVisitor.getAttribute();
}
}
}
public Map getAttributes() {
return attributes;
}
}
/**
* Class for reading CustomAttributes
* Returning all the attributes as a map
*
*/
private static class TestCustomAttributeVisitor extends VoidVisitorAdapter {
Map attribute = new HashMap<>();
@Override
public void visit(NormalAnnotationExpr n, Void arg) {
String name = null;
String value = null;
for (MemberValuePair pair: n.getPairs()) {
if ("name".equals(pair.getNameAsString())) {
name = pair.getValue().toString();
} else if ("values".equals(pair.getNameAsString())) {
value = pair.getValue().toString();
}
}
if (name != null && value != null) {
attribute.put(name, value);
}
}
public Map getAttribute() {
return attribute;
}
}
private static class TestMethodVisitor extends VoidVisitorAdapter {
private Map methodInfos = new HashMap<>();
private Map> testAttributes = new HashMap<>();
private Map> stepsInScenario = new HashMap<>();
private List findAllMethodCalls(Node instruction) {
final List found = new ArrayList<>();
instruction.walk(TreeTraversal.BREADTHFIRST, node -> {
if (MethodCallExpr.class.isAssignableFrom(node.getClass())) {
found.add(MethodCallExpr.class.cast(node));
}
});
Collections.reverse(found);
return found;
}
@Override
public void visit(MethodDeclaration n, Void arg) {
// read all method calls so that we can correlate with webpages
String methodId;
try {
Optional optBody = n.getBody();
Optional optParentNode = n.getParentNode();
if (optBody.isPresent() && optParentNode.isPresent()) {
BlockStmt body = optBody.get();
methodId = ((ClassOrInterfaceDeclaration)(optParentNode.get())).getNameAsString() + "." + n.getNameAsString();
stepsInScenario.put(methodId, new ArrayList<>());
for (Node instruction: body.getChildNodes()) {
for (MethodCallExpr methodCall: findAllMethodCalls(instruction)) {
String methodName = methodCall.getNameAsString();
if (steps.contains(methodName)) {
stepsInScenario.get(methodId).add(methodName);
}
}
}
} else {
return;
}
} catch (NoSuchElementException | ClassCastException e) {
// we expect that 'n' is a method, and its parent is the class itself. We do not support, for example enumeration
return;
}
// ignore non test methods
Optional optAnnotation = n.getAnnotationByClass(Test.class);
if (!optAnnotation.isPresent()) {
return;
}
// search for attributes
TestAttributeVisitor taVisitor = new TestAttributeVisitor();
n.accept(taVisitor, null);
testAttributes.put(methodId, taVisitor.getAttributes());
tests.add(methodId);
String methodDoc = "";
Optional optComment = n.getComment();
if (optComment.isPresent()) {
Comment comment = optComment.get();
methodDoc = formatJavadoc(comment.getContent());
}
methodInfos.put(methodId, methodDoc);
}
public Map getMethodInfos() {
return methodInfos;
}
public Map> getStepsInScenario() {
return stepsInScenario;
}
public Map> getTestAttributes() {
return testAttributes;
}
}
private static class WebPageMethodVisitor extends VoidVisitorAdapter {
private Map methodInfo = new HashMap<>();
@Override
public void visit(MethodDeclaration n, Void arg) {
// only display public methods
if (!n.getModifiers().contains(Modifier.publicModifier())) {
return;
}
steps.add(n.getNameAsString());
String methodJavaDoc = "";
Optional optComment = n.getComment();
if (optComment.isPresent()) {
Comment comment = optComment.get();
methodJavaDoc = formatJavadoc(comment.getContent());
}
methodInfo.put(n.getNameAsString(), methodJavaDoc);
}
public Map getMethodInfo() {
return methodInfo;
}
}
private static class ClassVisitor extends VoidVisitorAdapter {
private String classDoc;
private String className;
@Override
public void visit(ClassOrInterfaceDeclaration n, String objectType) {
Optional optComment = n.getComment();
className = n.getNameAsString();
if (optComment.isPresent()) {
Comment comment = optComment.get();
classDoc = String.format("%s", formatJavadoc(comment.getContent()));
} else {
classDoc = String.format("%s de la classe %s", objectType, n.getNameAsString());
}
if ("Pages".equals(objectType)) {
for (ObjectCreationExpr field: n.findAll(ObjectCreationExpr.class)) {
if (field.getType().getNameAsString().contains("Element")) {
searchedElements++;
}
}
searchedElements += n.findAll(MethodCallExpr.class).stream().filter(m -> m.getNameAsString().startsWith("findElement")).collect(Collectors.toList()).size();
}
}
public String getClassDoc() {
return classDoc;
}
public String getClassName() {
return className;
}
}
/**
* Remove the star in front of each line
* @return
*/
private static String formatJavadoc(String javadoc) {
StringBuilder out = new StringBuilder();
for (String line: javadoc.split("\n")) {
line = line.trim();
if (line.startsWith("*")) {
line = line.substring(1).trim();
}
if (line.startsWith("@")) {
line = String.format("