All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.theoryinpractice.testng.inspection.JUnitConvertTool Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition testng library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2012 JetBrains s.r.o.
 *
 * 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.theoryinpractice.testng.inspection;

import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInspection.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiElementFilter;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.theoryinpractice.testng.util.TestNGUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author Hani Suleiman Date: Aug 3, 2005 Time: 3:34:56 AM
 */
public class JUnitConvertTool extends BaseJavaLocalInspectionTool {

  private static final Logger LOG = Logger.getInstance("TestNG QuickFix");
  private static final String DISPLAY_NAME = "Convert JUnit Tests to TestNG";
  public static final String QUICKFIX_NAME = "Convert TestCase to TestNG";

  @NotNull
  @Override
  public String getGroupDisplayName() {
    return "TestNG";
  }

  @NotNull
  @Override
  public String getDisplayName() {
    return DISPLAY_NAME;
  }

  @NotNull
  @Override
  public String getShortName() {
    return "JUnitTestNG";
  }

  @Override
  @Nullable
  public ProblemDescriptor[] checkClass(@NotNull PsiClass psiClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
    if (TestNGUtil.inheritsJUnitTestCase(psiClass) || TestNGUtil.containsJunitAnnotions(psiClass)) {
      final PsiIdentifier nameIdentifier = psiClass.getNameIdentifier();
      ProblemDescriptor descriptor = manager.createProblemDescriptor(nameIdentifier != null ? nameIdentifier : psiClass, "TestCase can be converted to TestNG",
                                                                     new JUnitConverterQuickFix(),
                                                                     ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
      return new ProblemDescriptor[]{descriptor};
    }
    return null;
  }

  public static class JUnitConverterQuickFix implements LocalQuickFix {

    @NotNull
    public String getName() {
      return QUICKFIX_NAME;
    }

     @NotNull
    public String getFamilyName() {
      return getName();
    }

    public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
      if (!FileModificationService.getInstance().preparePsiElementForWrite(descriptor.getPsiElement())) return;
      final PsiClass psiClass = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PsiClass.class);
      if (!TestNGUtil.checkTestNGInClasspath(psiClass)) return;
      try {
        final PsiManager manager = PsiManager.getInstance(project);
        final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
        final PsiJavaFile javaFile = (PsiJavaFile)psiClass.getContainingFile();

        for (PsiMethod method : psiClass.getMethods()) {
          if (method.isConstructor()) {
            convertJUnitConstructor(method);
          }
          else {
            if (!javaFile.getLanguageLevel().isAtLeast(LanguageLevel.JDK_1_5)) {
              addMethodJavadoc(factory, method);
            }
            else {
              if (TestNGUtil.containsJunitAnnotions(method)) {
                convertJunitAnnotions(factory, method);
              } else {
                addMethodAnnotations(factory, method);
              }
            }
          }

          final PsiMethodCallExpression[] methodCalls = getTestCaseCalls(method);
          for (PsiMethodCallExpression methodCall : methodCalls) {
            PsiMethod assertMethod = methodCall.resolveMethod();
            if (assertMethod == null) {
              continue;
            }
            PsiAssertStatement assertStatement = null;
            @NonNls String methodName = assertMethod.getName();
            PsiExpression[] expressions = methodCall.getArgumentList().getExpressions();
            final PsiStatement methodCallStatement = PsiTreeUtil.getParentOfType(methodCall, PsiStatement.class);
            LOG.assertTrue(methodCallStatement != null);
            if ("assertTrue".equals(methodName) || "assertFalse".equals(methodName)) {
              if (expressions.length == 1) {
                assertStatement = createAssert(factory, null, methodCall);
                final PsiExpression assertCondition = assertStatement.getAssertCondition();
                LOG.assertTrue(assertCondition != null);
                assertCondition.replace(expressions[0]);
              }
              else if (expressions.length == 2) {
                assertStatement = createAssert(factory, expressions[0], methodCall);
                final PsiExpression assertCondition = assertStatement.getAssertCondition();
                LOG.assertTrue(assertCondition != null);
                assertCondition.replace(expressions[1]);
              }

              if ("assertFalse".equals(methodName) && assertStatement != null) {
                PsiExpression assertCondition = assertStatement.getAssertCondition();
                LOG.assertTrue(assertCondition != null);
                assertCondition.replace(factory.createExpressionFromText("!(" + assertCondition.getText() + ')',
                                                                         PsiTreeUtil.getParentOfType(assertCondition,
                                                                                                     PsiMethodCallExpression.class)));
              }
            }
            else if ("assertNull".equals(methodName) || "assertNotNull".equals(methodName)) {
              String operator = "assertNull".equals(methodName) ? "==" : "!=";
              if (expressions.length == 1) {
                assertStatement = createAssert(factory, null, methodCall);
                PsiExpression expression =
                  factory.createExpressionFromText(expressions[0].getText() + ' ' + operator + " null", assertStatement);
                final PsiExpression assertCondition = assertStatement.getAssertCondition();
                LOG.assertTrue(assertCondition != null);
                assertCondition.replace(expression);
              }
              else if (expressions.length == 2) {
                assertStatement = createAssert(factory, expressions[0], methodCall.getParent());
                PsiExpression expression =
                  factory.createExpressionFromText(expressions[1].getText() + ' ' + operator + " null", assertStatement);
                final PsiExpression assertCondition = assertStatement.getAssertCondition();
                LOG.assertTrue(assertCondition != null);
                assertCondition.replace(expression);
              }
            }
            else if ("fail".equals(methodName)) {
              if (expressions.length == 0) {
                assertStatement = createAssert(factory, null, methodCall);
              }
              else if (expressions.length == 1) {
                assertStatement = createAssert(factory, expressions[0], methodCall);
              }
            }
            else {
              //if it's a 3 arg, the error message goes at the end
              PsiElement inserted = null;
              if (expressions.length == 2) {
                final PsiExpression qualifierExpression = methodCall.getMethodExpression().getQualifierExpression();
                final String text = "org.testng." + (qualifierExpression == null ? "Assert." : "") + methodCall.getText() + ";";
                inserted = methodCallStatement
                  .replace(factory.createStatementFromText(text, methodCall.getParent()));
              }
              else if (expressions.length == 3) {
                @NonNls String call = "org.testng.Assert." + methodName + '(' + expressions[2].getText() + ", " + expressions[1].getText() +
                                      ", " + expressions[0].getText() + ");";
                inserted = methodCallStatement.replace(factory.createStatementFromText(call, methodCall.getParent()));
              }
              if (inserted != null) {
                JavaCodeStyleManager.getInstance(project).shortenClassReferences(inserted);
              }
            }
            if (assertStatement != null) {
              methodCallStatement.replace(assertStatement);
            }
          }
        }
        final PsiClass superClass = psiClass.getSuperClass();
        if (superClass != null && "junit.framework.TestCase".equals(superClass.getQualifiedName())) {
          final PsiReferenceList extendsList = psiClass.getExtendsList();
          LOG.assertTrue(extendsList != null);
          for (PsiJavaCodeReferenceElement element : extendsList.getReferenceElements()) {
            element.delete();
          }
        }
        JavaCodeStyleManager.getInstance(project).optimizeImports(javaFile);//delete unused imports
      }
      catch (IncorrectOperationException e) {
        LOG.error("Error converting testcase", e);
      }
    }



    private static void convertJunitAnnotions(PsiElementFactory factory, PsiMethod method) throws IncorrectOperationException {
      PsiAnnotation[] annotations = method.getModifierList().getAnnotations();
      for (PsiAnnotation annotation : annotations) {
        PsiAnnotation newAnnotation = null;
        if ("org.junit.Test".equals(annotation.getQualifiedName())) {
          newAnnotation = factory.createAnnotationFromText("@org.testng.annotations.Test", method);
        }
        else if ("org.junit.BeforeClass".equals(annotation.getQualifiedName())) {
          newAnnotation = factory.createAnnotationFromText("@org.testng.annotations.BeforeClass", method);
        }
        else if ("org.junit.Before".equals(annotation.getQualifiedName())) {
          newAnnotation = factory.createAnnotationFromText("@org.testng.annotations.BeforeMethod", method);
        }
        else if ("org.junit.AfterClass".equals(annotation.getQualifiedName())) {
          newAnnotation = factory.createAnnotationFromText("@org.testng.annotations.AfterClass", method);
        }
        else if ("org.junit.After".equals(annotation.getQualifiedName())) {
          newAnnotation = factory.createAnnotationFromText("@org.testng.annotations.AfterMethod", method);
        }
        if (newAnnotation != null) {
          JavaCodeStyleManager.getInstance(annotation.getProject()).shortenClassReferences(annotation.replace(newAnnotation));
        }
      }
    }

    private static void convertJUnitConstructor(PsiMethod method) {
      method.accept(new JavaRecursiveElementWalkingVisitor() {

        @Override
        public void visitExpressionStatement(PsiExpressionStatement statement) {
          PsiExpression expression = statement.getExpression();
          if (expression instanceof PsiMethodCallExpression) {
            PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression;
            if (methodCall.getArgumentList().getExpressions().length == 1) {
              PsiMethod resolved = methodCall.resolveMethod();
              if (resolved != null && "junit.framework.TestCase".equals(resolved.getContainingClass().getQualifiedName()) &&
                  "TestCase".equals(resolved.getName())) {
                try {
                  statement.delete();
                }
                catch (IncorrectOperationException e) {
                  LOG.error(e);
                }
              }
            }
          }
        }
      });
    }

    private static PsiMethodCallExpression[] getTestCaseCalls(PsiMethod method) {
      PsiElement[] methodCalls = PsiTreeUtil.collectElements(method, new PsiElementFilter() {
        public boolean isAccepted(PsiElement element) {
          if (!(element instanceof PsiMethodCallExpression)) return false;
          final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
          final PsiMethod method = methodCall.resolveMethod();
          if (method != null) {
            final PsiClass containingClass = method.getContainingClass();
            if (containingClass != null) {
              final String qualifiedName = containingClass.getQualifiedName();
              if ("junit.framework.Assert".equals(qualifiedName) || 
                  "org.junit.Assert".equals(qualifiedName) || 
                  "junit.framework.TestCase".equals(qualifiedName)) {
                return true;
              }
            }
          }
          return false;
        }
      });
      PsiMethodCallExpression[] expressions = new PsiMethodCallExpression[methodCalls.length];
      System.arraycopy(methodCalls, 0, expressions, 0, methodCalls.length);
      return expressions;
    }

    private static void addMethodJavadoc(PsiElementFactory factory, PsiMethod method) throws IncorrectOperationException {
      if (method.getName().startsWith("test")) {
        addMethodJavadocLine(factory, method, " * @testng.test");
      }
      else if ("setUp".equals(method.getName()) && method.getParameterList().getParameters().length == 0) {
        addMethodJavadocLine(factory, method, " * @testng.before-test");
      }
      else if ("tearDown".equals(method.getName()) && method.getParameterList().getParameters().length == 0) {
        addMethodJavadocLine(factory, method, " * @testng.after-test");
      }
    }

    private static void addMethodJavadocLine(PsiElementFactory factory, PsiMethod method, @NonNls String javaDocLine)
      throws IncorrectOperationException {
      PsiComment newComment;
      PsiElement comment = method.getFirstChild();
      if (comment != null && comment instanceof PsiComment) {
        String[] commentLines = comment.getText().split("\n");
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < commentLines.length; i++) {
          String commentLine = commentLines[i];
          // last line, append our new comment entry
          if (i == commentLines.length - 1) {
            buf.append(javaDocLine);
            buf.append(commentLine);
          }
          else {
            buf.append(commentLine);
            buf.append('\n');
          }
        }
        String commentString = buf.toString();

        newComment = factory.createCommentFromText(commentString, null);
        comment.replace(newComment);

      }
      else {
        String commentString;

        StringBuffer commentBuffer = new StringBuffer();
        commentBuffer.append("/**\n");
        commentBuffer.append(javaDocLine);
        commentBuffer.append('\n');
        commentBuffer.append(" */");

        commentString = commentBuffer.toString();
        newComment = factory.createCommentFromText(commentString, null);

        method.addBefore(newComment, comment);
      }
    }

    private static void addMethodAnnotations(PsiElementFactory factory, PsiMethod method) throws IncorrectOperationException {
      PsiAnnotation annotation = null;
      if (method.getName().startsWith("test")) {
        annotation = factory.createAnnotationFromText("@org.testng.annotations.Test", method);
      }
      else if ("setUp".equals(method.getName()) && method.getParameterList().getParameters().length == 0) {
        annotation = factory.createAnnotationFromText("@org.testng.annotations.BeforeMethod", method);
      }
      else if ("tearDown".equals(method.getName()) && method.getParameterList().getParameters().length == 0) {
        annotation = factory.createAnnotationFromText("@org.testng.annotations.AfterMethod", method);
      }
      if (annotation != null) {
        JavaCodeStyleManager.getInstance(annotation.getProject()).shortenClassReferences(method.getModifierList().addAfter(annotation, null));
      }
    }

    private static PsiAssertStatement createAssert(PsiElementFactory factory, PsiExpression description, PsiElement context)
      throws IncorrectOperationException {
      PsiAssertStatement assertStatement;
      if (description == null) {
        assertStatement = (PsiAssertStatement)factory.createStatementFromText("assert false;", context.getParent());
        return assertStatement;
      }
      else {
        assertStatement = (PsiAssertStatement)factory.createStatementFromText("assert false : \"x\";", context.getParent());
        final PsiExpression assertDescription = assertStatement.getAssertDescription();
        assert assertDescription != null;
        assertDescription.replace(description);
      }
      return assertStatement;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy