Skip to content

Commit

Permalink
Supportmorecases (#119)
Browse files Browse the repository at this point in the history
* extract test classes and improve test coverage

* enhance test coverage, fix duplication of some changes

* refactor slightly to improve readability

* detect classrule
  • Loading branch information
carstenartur authored Nov 23, 2024
1 parent 8ac2996 commit 8115c70
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodDeclaration;
Expand Down Expand Up @@ -71,6 +72,10 @@
*/
public abstract class AbstractTool<T> {

private static final String ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_ALL_CALLBACK= "org.junit.jupiter.api.extension.AfterAllCallback";
private static final String ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_ALL_CALLBACK= "org.junit.jupiter.api.extension.BeforeAllCallback";
private static final String AFTER_ALL_CALLBACK= "AfterAllCallback";
private static final String BEFORE_ALL_CALLBACK= "BeforeAllCallback";
private static final String TEST_NAME= "testName";
private static final String METHOD_AFTER_EACH= "afterEach";
private static final String METHOD_BEFORE_EACH= "beforeEach";
Expand Down Expand Up @@ -332,15 +337,70 @@ private void adaptTypeDeclaration(TypeDeclaration typeDecl, ASTRewrite rewrite,
importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK);
}

private boolean isUsedAsClassRule(TypeDeclaration node, String annotationclass) {
ITypeBinding typeBinding = node.resolveBinding();
if (typeBinding == null) {
return false;
}

CompilationUnit cu = (CompilationUnit) node.getRoot();
if (cu == null) {
return false;
}
final boolean[] isClassRule = {false};

cu.accept(new ASTVisitor() {
@Override
public boolean visit(FieldDeclaration fieldDeclaration) {
// Prüfe, ob das Feld mit @ClassRule annotiert ist
boolean hasClassRuleAnnotation = fieldDeclaration.modifiers().stream()
.filter(modifier -> modifier instanceof Annotation) // Sicherstellen, dass es sich um eine Annotation handelt
.map(modifier -> (Annotation) modifier) // Cast zu Annotation
.anyMatch(annotation -> {
String annotationBinding = ((Annotation) annotation).getTypeName().getFullyQualifiedName();

return annotationBinding != null && annotationclass.equals(annotationBinding);
});

// Prüfe, ob das Feld vom Typ der aktuellen Klasse ist
if (hasClassRuleAnnotation) {
Type fieldType = fieldDeclaration.getType();
if (fieldType.resolveBinding() != null && fieldType.resolveBinding().isEqualTo(typeBinding)) {
isClassRule[0] = true;
}
}
return super.visit(fieldDeclaration);
}
});

return isClassRule[0];
}

private void refactorToImplementCallbacks(TypeDeclaration node, ASTRewrite rewriter, AST ast, TextEditGroup group,
ImportRewrite importRewriter) {
rewriter.remove(node.getSuperclassType(), group);
importRewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE);
ListRewrite listRewrite= rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY);
addInterfaceCallback(listRewrite, ast, BEFORE_EACH_CALLBACK, group);
addInterfaceCallback(listRewrite, ast, AFTER_EACH_CALLBACK, group);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK);
ImportRewrite importRewriter) {
// Entferne die Superklasse ExternalResource
rewriter.remove(node.getSuperclassType(), group);
importRewriter.removeImport(ORG_JUNIT_RULES_EXTERNAL_RESOURCE);

// Prüfe, ob die Klasse statisch verwendet wird
boolean isStaticUsage = isUsedAsClassRule(node, "org.junit.ClassRule");

ListRewrite listRewrite = rewriter.getListRewrite(node, TypeDeclaration.SUPER_INTERFACE_TYPES_PROPERTY);

// Füge die entsprechenden Callback-Interfaces hinzu
if (isStaticUsage) {
// Verwende BeforeAllCallback und AfterAllCallback für statische Ressourcen
addInterfaceCallback(listRewrite, ast, BEFORE_ALL_CALLBACK, group);
addInterfaceCallback(listRewrite, ast, AFTER_ALL_CALLBACK, group);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_ALL_CALLBACK);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_ALL_CALLBACK);
} else {
// Verwende BeforeEachCallback und AfterEachCallback für nicht-statische Ressourcen
addInterfaceCallback(listRewrite, ast, BEFORE_EACH_CALLBACK, group);
addInterfaceCallback(listRewrite, ast, AFTER_EACH_CALLBACK, group);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_BEFORE_EACH_CALLBACK);
importRewriter.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_AFTER_EACH_CALLBACK);
}
}

private void addBeforeAndAfterEachCallbacks(TypeDeclaration typeDecl, ASTRewrite rewrite, AST ast,
Expand Down Expand Up @@ -538,12 +598,12 @@ protected boolean hasDefaultConstructorOrNoConstructor(TypeDeclaration classNode
return !hasConstructor;
}

private boolean isAnnotatedWithRule(BodyDeclaration declaration) {
private boolean isAnnotatedWithRule(BodyDeclaration declaration, String annotationclass) {
for (Object modifier : declaration.modifiers()) {
if (modifier instanceof Annotation) {
Annotation annotation= (Annotation) modifier;
ITypeBinding binding= annotation.resolveTypeBinding();
if (binding != null && ORG_JUNIT_RULE.equals(binding.getQualifiedName())) {
if (binding != null && annotationclass.equals(binding.getQualifiedName())) {
return true;
}
}
Expand Down Expand Up @@ -605,8 +665,15 @@ public void migrateRuleToRegisterExtensionAndAdaptHierarchy(Optional<ASTNode> in
group);
}
for (FieldDeclaration field : testClass.getFields()) {
if (isAnnotatedWithRule(field) && isExternalResource(field)) {
removeRuleAnnotation(field, rewrite, group, importRewrite);
if (isAnnotatedWithRule(field, ORG_JUNIT_RULE) && isExternalResource(field)) {
removeRuleAnnotation(field, rewrite, group, importRewrite, ORG_JUNIT_RULE);
addRegisterExtensionAnnotation(field, rewrite, ast, importRewrite, group);
importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_REGISTER_EXTENSION);
ITypeBinding fieldType= ((VariableDeclarationFragment) field.fragments().get(0)).resolveBinding()
.getType();
adaptExternalResourceHierarchy(fieldType, rewrite, ast, importRewrite, group);
} else if (isAnnotatedWithRule(field, ORG_JUNIT_CLASS_RULE) && isExternalResource(field)) {
removeRuleAnnotation(field, rewrite, group, importRewrite, ORG_JUNIT_CLASS_RULE);
addRegisterExtensionAnnotation(field, rewrite, ast, importRewrite, group);
importRewrite.addImport(ORG_JUNIT_JUPITER_API_EXTENSION_REGISTER_EXTENSION);
ITypeBinding fieldType= ((VariableDeclarationFragment) field.fragments().get(0)).resolveBinding()
Expand Down Expand Up @@ -644,15 +711,15 @@ public void process(Annotation node, IJavaProject jproject, ASTRewrite rewrite,
}

private void removeRuleAnnotation(BodyDeclaration declaration, ASTRewrite rewriter, TextEditGroup group,
ImportRewrite importRewriter) {
ImportRewrite importRewriter, String annotationclass) {
List<?> modifiers= declaration.modifiers();
for (Object modifier : modifiers) {
if (modifier instanceof Annotation) {
Annotation annotation= (Annotation) modifier;
ITypeBinding binding= annotation.resolveTypeBinding();
if (binding != null && binding.getQualifiedName().equals(ORG_JUNIT_RULE)) {
if (binding != null && binding.getQualifiedName().equals(annotationclass)) {
rewriter.remove(annotation, group);
importRewriter.removeImport(ORG_JUNIT_RULE);
importRewriter.removeImport(annotationclass);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ public void find(JUnitCleanUpFixCore fixcore, CompilationUnit compilationUnit,
HelperVisitor.callFieldDeclarationVisitor(ORG_JUNIT_RULE, ORG_JUNIT_RULES_EXTERNAL_RESOURCE, compilationUnit,
dataholder, nodesprocessed,
(visited, aholder) -> processFoundNode(fixcore, operations, visited, aholder));
HelperVisitor.callFieldDeclarationVisitor(ORG_JUNIT_CLASS_RULE, ORG_JUNIT_RULES_EXTERNAL_RESOURCE, compilationUnit,
dataholder, nodesprocessed,
(visited, aholder) -> processFoundNode(fixcore, operations, visited, aholder));
}

private boolean processFoundNode(JUnitCleanUpFixCore fixcore,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ protected void after() {
}
@ClassRule
public static ExternalResource staticResource = new StaticExternalResource();
public static ExternalResource staticResource = new StaticExternalResource();
// Klasse mit Konstruktor
final class ConstructedExternalResource extends ExternalResource {
Expand Down Expand Up @@ -792,7 +792,6 @@ public void testWithMultipleResources() {
"""
package test;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
Expand Down Expand Up @@ -845,8 +844,8 @@ public void afterEach(ExtensionContext context) {
}
}
@ClassRule
public static ExternalResource staticResource = new StaticExternalResource();
@RegisterExtension
public static ExternalResource staticResource = new StaticExternalResource();
// Klasse mit Konstruktor
final class ConstructedExternalResource implements BeforeEachCallback, AfterEachCallback {
Expand Down

0 comments on commit 8115c70

Please sign in to comment.