Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls. Removed oraclejdk8 from travis-ci. Added custom Jupiter DisplayNameGenerator for user friendly test names in report. Extended documentation. Removed Playground.
This commit is contained in:
parent
66f1467b23
commit
eab50f590b
@ -1,6 +1,5 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- openjdk8
|
||||
|
||||
before_script:
|
||||
|
96
README.md
96
README.md
@ -73,6 +73,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
## Implemented inspections and quickfixes
|
||||
|
||||
- JoinAssertThatStatements
|
||||
|
||||
Joins multiple ```assertThat()``` statements with same actual expression together.
|
||||
|
||||
```
|
||||
from: assertThat(expected).someCondition();
|
||||
assertThat(expected).anotherCondition();
|
||||
@ -82,8 +85,11 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
except for method calls with known side-effect methods such as ```Iterator.next()``` -- please notify me about others.
|
||||
|
||||
The comments of the statements will be preserved. When using ```.extracting()``` or similar, the statements will not be merged.
|
||||
|
||||
|
||||
- AssertThatObjectIsNullOrNotNull
|
||||
|
||||
Uses ```isNull()``` and ```isNotNull()``` instead.
|
||||
|
||||
```
|
||||
from: assertThat(object).isEqualTo(null);
|
||||
to: assertThat(object).isNull();
|
||||
@ -93,12 +99,18 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
```
|
||||
|
||||
- AssertThatBooleanCondition
|
||||
|
||||
Uses ```isTrue()``` and ```isFalse()``` instead.
|
||||
|
||||
```
|
||||
from: assertThat(booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
|
||||
to: assertThat(booleanValue).isTrue()/isFalse();
|
||||
```
|
||||
|
||||
- AssertThatInvertedBooleanCondition
|
||||
|
||||
Inverts the boolean condition to make it more readable.
|
||||
|
||||
```
|
||||
from: assertThat(!booleanValue).isEqualTo(true/false/Boolean.TRUE/Boolean.FALSE);
|
||||
from: assertThat(!booleanValue).isTrue()/isFalse();
|
||||
@ -106,6 +118,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
```
|
||||
|
||||
- AssertThatInstanceOf
|
||||
|
||||
Moves ```instanceof``` expressions out of ```assertThat()```.
|
||||
|
||||
```
|
||||
from: assertThat(object instanceof classname).isEqualTo(true);
|
||||
from: assertThat(object instanceof classname).isTrue();
|
||||
@ -117,13 +132,21 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
```
|
||||
|
||||
- AssertThatStringIsEmpty
|
||||
|
||||
Uses ```isEmpty()``` for empty string assertions.
|
||||
|
||||
```
|
||||
from: assertThat(charSequence/string).isEqualTo("");
|
||||
from: assertThat(charSequence/string).hasSize(0);
|
||||
to: assertThat(charSequence/string).isEmpty();
|
||||
```
|
||||
|
||||
The ```assertThat(string.length()).isEqualTo(0);``` case is handled in the AssertThatSize inspection.
|
||||
|
||||
- AssertThatStringExpression
|
||||
|
||||
Moves string operations inside assertThat() out.
|
||||
|
||||
```
|
||||
from: assertThat(stringActual.isEmpty()).isTrue();
|
||||
to: assertThat(stringActual).isEmpty();
|
||||
@ -147,12 +170,19 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
Analogously with ```isFalse()```.
|
||||
|
||||
- AssertThatEnumerableIsEmpty
|
||||
|
||||
Uses ```isEmpty()``` for ```hasSize(0)``` iterable assertions instead.
|
||||
|
||||
```
|
||||
from: assertThat(enumerable).hasSize(0);
|
||||
to: assertThat(enumerable).isEmpty();
|
||||
```
|
||||
|
||||
- AssertThatSize
|
||||
|
||||
Makes assertions on sizes of arrays, collections, strings,
|
||||
or ```CharSequence```s more concise.
|
||||
|
||||
```
|
||||
from: assertThat(array.length).isEqualTo(0);
|
||||
from: assertThat(array.length).isLessThanOrEqualTo(0);
|
||||
@ -201,6 +231,9 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
```
|
||||
|
||||
- AssertThatBinaryExpression
|
||||
|
||||
Splits a boolean condition represented by binary expression out of ```assertThat()```.
|
||||
|
||||
```
|
||||
from: assertThat(primActual == primExpected).isTrue();
|
||||
to: assertThat(primActual).isEqualTo(primExpected);
|
||||
@ -220,6 +253,11 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
...and many, many more combinations (more than 150).
|
||||
|
||||
- AssertThatJava8Optional
|
||||
|
||||
Examines the statement for Java 8 Optional type and whether the statement
|
||||
effectively tries to assert the presence, absence or content and then
|
||||
replaces the statement by better assertions.
|
||||
|
||||
```
|
||||
from: assertThat(opt.isPresent()).isEqualTo(true);
|
||||
from: assertThat(opt.isPresent()).isNotEqualTo(false);
|
||||
@ -249,6 +287,11 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
```
|
||||
|
||||
- AssertThatGuavaOptional
|
||||
|
||||
Examines the statement for Google Guava Optional type and whether the statement
|
||||
effectively tries to assert the presence, absence or content and then
|
||||
replaces the statement by better assertions.
|
||||
|
||||
```
|
||||
from: assertThat(opt.isPresent()).isEqualTo(true);
|
||||
from: assertThat(opt.isPresent()).isNotEqualTo(false);
|
||||
@ -276,7 +319,54 @@ You can toggle the various inspections in the Settings/Editor/Inspections in the
|
||||
|
||||
AssertJ for Guava needs to be available in the classpath.
|
||||
|
||||
- AssumeThatInsteadOfReturn
|
||||
|
||||
Tries to detect bogus uses of return statements in test methods and replaces them by ```assumeThat()``` calls.
|
||||
|
||||
Novices will use these to skip test execution by bailing out early on some preconditions not met.
|
||||
However, this suggests that the test has actually been run and passed instead of showing the test
|
||||
as being skipped.
|
||||
|
||||
Return statements in ```if``` statements in main test methods (must be annotated with JUnit 4 or
|
||||
Jupiter @Test annotations) will be verified to have at least one ```assertThat()``` statement in the code flow.
|
||||
Method calls within the same class will be examined for ```assertThat()``` statements, too.
|
||||
However, at most 50 statements and down to five recursions will be tolerated before giving up.
|
||||
|
||||
Currently, the quickfix may lose some comments during operation. The other branch of the ```if``` statement
|
||||
will be inlined (blocks with declarations will remain a code block due to variable scope).
|
||||
|
||||
The generated ```assumeThat()``` statement could be optimized further (similar to ```assertThat()```).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
@Test
|
||||
public void check_fuel_emission() {
|
||||
if (System.getProperty("manufacturer").equals("Volkswagen")) {
|
||||
return;
|
||||
}
|
||||
double nitroxppm = doWltpDrivingCycle();
|
||||
assertThat(nitroxppm).isLessThan(500.0);
|
||||
}
|
||||
```
|
||||
will be transformed to
|
||||
```
|
||||
@Test
|
||||
public void check_fuel_emission() {
|
||||
assumeThat(System.getProperty("manufacturer").equals("Volkswagen")).isFalse();
|
||||
double nitroxppm = doWltpDrivingCycle();
|
||||
assertThat(nitroxppm).isLessThan(500.0);
|
||||
}
|
||||
```
|
||||
|
||||
- JUnitAssertToAssertJ
|
||||
|
||||
Tries to convert most of the JUnit 4 assertions to AssertJ format.
|
||||
|
||||
Does not support Hamcrest-Matchers.
|
||||
If you need that kind of conversion, you might want to check out the
|
||||
[Assertions2AssertJ plugin](https://plugins.jetbrains.com/plugin/10345-assertions2assertj) by Ric Emery.
|
||||
|
||||
```
|
||||
assertTrue(condition);
|
||||
assertTrue(message, condition);
|
||||
@ -332,7 +422,6 @@ The IntelliJ framework actually uses the JUnit 3 TestCase for plugin testing and
|
||||
Feel free to use the code (in package de.platon42.intellij.jupiter) for your projects (with attribution).
|
||||
|
||||
## Planned features
|
||||
- AssumeThatInsteadOfReturn
|
||||
- Extraction with property names to lambda with Java 8
|
||||
```
|
||||
from: assertThat(object).extracting("propOne", "propNoGetter", "propTwo.innerProp")...
|
||||
@ -343,7 +432,7 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
|
||||
|
||||
## Changelog
|
||||
|
||||
#### V0.8 (unreleased)
|
||||
#### V0.8 (05-May-19)
|
||||
- Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
||||
- Fixed ```isEmpty()``` for enumerables and strings and ```isNull()``` for object conversions to be applied only if it is the terminal method call as ```isEmpty()``` and ```isNull()``` return void.
|
||||
- Heavily reworked inspections for edge cases, such as multiple ```isEqualTo()``` calls inside a single statement.
|
||||
@ -351,6 +440,7 @@ Feel free to use the code (in package de.platon42.intellij.jupiter) for your pro
|
||||
- Corrected highlighting for many inspections.
|
||||
- Fixed family names for inspections in batch mode.
|
||||
- Reworded many inspection messages for better understanding.
|
||||
- Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by ```assumeThat()``` calls.
|
||||
|
||||
#### V0.7 (28-Apr-19)
|
||||
- Another fix for AssertThatGuavaOptional inspection regarding using the same family name for slightly different quick fix executions
|
||||
|
@ -42,7 +42,7 @@ intellij {
|
||||
|
||||
patchPluginXml {
|
||||
changeNotes """
|
||||
<h4>V0.8 (unreleased)</h4>
|
||||
<h4>V0.8 (05-May-19)</h4>
|
||||
<ul>
|
||||
<li>Fixed missing description for JoinAssertThatStatements and detection of equivalent expressions (sorry, released it too hastily).
|
||||
<li>Fixed isEmpty() for enumerables and strings and isNull() for object conversions to be applied only if it is the terminal method call as isEmpty() and isNull() return void.
|
||||
@ -51,6 +51,7 @@ patchPluginXml {
|
||||
<li>Corrected highlighting for many inspections.
|
||||
<li>Fixed family names for inspections in batch mode.
|
||||
<li>Reworded many inspection messages for better understanding.
|
||||
<li>Added a first version of a new inspection that tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
|
||||
</ul>
|
||||
<h4>V0.7 (28-Apr-19)</h4>
|
||||
<ul>
|
||||
|
@ -7,6 +7,9 @@ class AssertJClassNames {
|
||||
@NonNls
|
||||
const val ASSERTIONS_CLASSNAME = "org.assertj.core.api.Assertions"
|
||||
|
||||
@NonNls
|
||||
const val ASSUMPTIONS_CLASSNAME = "org.assertj.core.api.Assumptions"
|
||||
|
||||
@NonNls
|
||||
const val DESCRIPTABLE_INTERFACE = "org.assertj.core.api.Descriptable"
|
||||
@NonNls
|
||||
|
@ -12,7 +12,10 @@ import de.platon42.intellij.plugins.cajon.inspections.AbstractAssertJInspection
|
||||
val PsiMethodCallExpression.qualifierExpression: PsiExpression get() = methodExpression.qualifierExpression!!
|
||||
val PsiMethodCallExpression.firstArg: PsiExpression get() = getArg(0)
|
||||
|
||||
fun PsiElement.hasAssertThat() = text.contains("assertThat")
|
||||
fun PsiElement.hasAssertThat(): Boolean {
|
||||
val elementText = text
|
||||
return elementText.startsWith("${MethodNames.ASSERT_THAT}(") || elementText.contains(".${MethodNames.ASSERT_THAT}(")
|
||||
}
|
||||
|
||||
fun PsiMethodCallExpression.replaceQualifier(qualifier: PsiElement) {
|
||||
qualifierExpression.replace(qualifier)
|
||||
|
@ -12,6 +12,9 @@ class MethodNames {
|
||||
@NonNls
|
||||
const val ASSERT_THAT = "assertThat"
|
||||
|
||||
@NonNls
|
||||
const val ASSUME_THAT = "assumeThat"
|
||||
|
||||
@NonNls
|
||||
const val AS = "as"
|
||||
@NonNls
|
||||
|
@ -0,0 +1,146 @@
|
||||
package de.platon42.intellij.plugins.cajon.inspections
|
||||
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.psi.*
|
||||
import de.platon42.intellij.plugins.cajon.hasAssertThat
|
||||
import de.platon42.intellij.plugins.cajon.quickfixes.ReplaceIfByAssumeThatQuickFix
|
||||
|
||||
class AssumeThatInsteadOfReturnInspection : AbstractAssertJInspection() {
|
||||
|
||||
companion object {
|
||||
private const val DISPLAY_NAME = "Replace conditional test exits by assumeThat() statements with same actual expression"
|
||||
private const val REPLACE_RETURN_BY_ASSUME_THAT_DESCRIPTION = "Conditional return should probably be an assumeThat() statement instead"
|
||||
|
||||
private const val MAX_RECURSION_DEPTH = 5
|
||||
private const val MAX_STATEMENTS_COUNT = 50
|
||||
|
||||
private val TEST_ANNOTATIONS = listOf(
|
||||
"org.junit.Test",
|
||||
"org.junit.jupiter.api.Test",
|
||||
"org.junit.jupiter.api.TestTemplate",
|
||||
"org.junit.jupiter.api.params.ParameterizedTest"
|
||||
)
|
||||
|
||||
private fun hasEmptyReturn(statement: PsiStatement): Boolean {
|
||||
return when (statement) {
|
||||
is PsiBlockStatement -> {
|
||||
val psiReturnStatement = (statement.firstChild as? PsiCodeBlock)?.statements?.singleOrNull() as? PsiReturnStatement
|
||||
(psiReturnStatement != null) && (psiReturnStatement.returnValue == null)
|
||||
}
|
||||
is PsiReturnStatement -> statement.returnValue == null
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerProblem(holder: ProblemsHolder, isOnTheFly: Boolean, statement: PsiStatement, removeElse: Boolean) {
|
||||
val problemDescriptor = holder.manager.createProblemDescriptor(
|
||||
statement,
|
||||
statement,
|
||||
REPLACE_RETURN_BY_ASSUME_THAT_DESCRIPTION,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
isOnTheFly,
|
||||
ReplaceIfByAssumeThatQuickFix(removeElse)
|
||||
)
|
||||
holder.registerProblem(problemDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getDisplayName() = DISPLAY_NAME
|
||||
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean): PsiElementVisitor {
|
||||
return object : JavaElementVisitor() {
|
||||
override fun visitMethod(method: PsiMethod) {
|
||||
super.visitMethod(method)
|
||||
if (TEST_ANNOTATIONS.none(method::hasAnnotation)) {
|
||||
return
|
||||
}
|
||||
val containingClass = method.containingClass ?: return
|
||||
val visitor: PsiElementVisitor = TestMethodVisitor(holder, isOnTheFly, containingClass)
|
||||
method.accept(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestMethodVisitor(
|
||||
private val holder: ProblemsHolder,
|
||||
private val isOnTheFly: Boolean,
|
||||
private val containingClass: PsiClass
|
||||
) : JavaRecursiveElementWalkingVisitor() {
|
||||
|
||||
private var contSearch = true
|
||||
|
||||
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
|
||||
if (contSearch) {
|
||||
val methodCallExpression = statement.expression as? PsiMethodCallExpression
|
||||
if (methodCallExpression != null) {
|
||||
if (methodCallExpression.hasAssertThat()) {
|
||||
contSearch = false
|
||||
} else {
|
||||
val method = methodCallExpression.resolveMethod()
|
||||
if (method?.containingClass == containingClass) {
|
||||
val recursionVisitor = CheckForAssertThatCallsVisitor(containingClass, 1)
|
||||
method.accept(recursionVisitor)
|
||||
if (recursionVisitor.aborted || recursionVisitor.foundAssertThat) {
|
||||
contSearch = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (contSearch) {
|
||||
super.visitExpressionStatement(statement)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitIfStatement(statement: PsiIfStatement) {
|
||||
if (contSearch) {
|
||||
checkBranch(statement, statement.thenBranch, false)
|
||||
checkBranch(statement, statement.elseBranch, true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkBranch(statement: PsiIfStatement, branch: PsiStatement?, removeElse: Boolean) {
|
||||
if (branch != null) {
|
||||
if (hasEmptyReturn(branch)) {
|
||||
registerProblem(holder, isOnTheFly, statement, removeElse)
|
||||
} else {
|
||||
branch.accept(TestMethodVisitor(holder, isOnTheFly, containingClass))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CheckForAssertThatCallsVisitor(private val containingClass: PsiClass, private var depth: Int) : JavaRecursiveElementWalkingVisitor() {
|
||||
var foundAssertThat = false
|
||||
private var statementCount = 0
|
||||
var aborted = false
|
||||
|
||||
override fun visitExpressionStatement(statement: PsiExpressionStatement) {
|
||||
if (foundAssertThat || aborted) {
|
||||
return
|
||||
}
|
||||
if (++statementCount > MAX_STATEMENTS_COUNT) {
|
||||
aborted = true
|
||||
return
|
||||
}
|
||||
super.visitExpressionStatement(statement)
|
||||
val methodCallExpression = statement.expression as? PsiMethodCallExpression
|
||||
if (methodCallExpression != null) {
|
||||
foundAssertThat = methodCallExpression.hasAssertThat()
|
||||
val method = methodCallExpression.resolveMethod()
|
||||
if (method?.containingClass == containingClass) {
|
||||
if (depth < MAX_RECURSION_DEPTH) {
|
||||
val recursionVisitor = CheckForAssertThatCallsVisitor(containingClass, depth + 1)
|
||||
method.accept(recursionVisitor)
|
||||
foundAssertThat = recursionVisitor.foundAssertThat
|
||||
statementCount += recursionVisitor.statementCount
|
||||
aborted = recursionVisitor.aborted
|
||||
} else {
|
||||
aborted = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import de.platon42.intellij.plugins.cajon.quickfixes.JoinStatementsQuickFix
|
||||
class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
||||
|
||||
companion object {
|
||||
private const val DISPLAY_NAME = "Joining multiple assertThat() statements with same actual expression"
|
||||
private const val DISPLAY_NAME = "Join multiple assertThat() statements with same actual expression"
|
||||
private const val CAN_BE_JOINED_DESCRIPTION = "Multiple assertThat() statements can be joined together"
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
||||
}
|
||||
if (reset) {
|
||||
if (sameCount > 1) {
|
||||
registerProblem(firstStatement, lastStatement)
|
||||
registerProblem(holder, isOnTheFly, firstStatement!!, lastStatement!!)
|
||||
}
|
||||
firstStatement = statement
|
||||
lastStatement = null
|
||||
@ -62,22 +62,10 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
||||
}
|
||||
}
|
||||
if (sameCount > 1) {
|
||||
registerProblem(firstStatement, lastStatement)
|
||||
registerProblem(holder, isOnTheFly, firstStatement!!, lastStatement!!)
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerProblem(firstStatement: PsiStatement?, lastStatement: PsiStatement?) {
|
||||
val problemDescriptor = holder.manager.createProblemDescriptor(
|
||||
firstStatement!!,
|
||||
lastStatement!!,
|
||||
CAN_BE_JOINED_DESCRIPTION,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
isOnTheFly,
|
||||
JoinStatementsQuickFix()
|
||||
)
|
||||
holder.registerProblem(problemDescriptor)
|
||||
}
|
||||
|
||||
private fun isLegitAssertThatCall(statement: PsiStatement?): PsiMethodCallExpression? {
|
||||
if ((statement is PsiExpressionStatement) && (statement.expression is PsiMethodCallExpression)) {
|
||||
if (!statement.hasAssertThat()) {
|
||||
@ -90,4 +78,16 @@ class JoinAssertThatStatementsInspection : AbstractAssertJInspection() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun registerProblem(holder: ProblemsHolder, isOnTheFly: Boolean, firstStatement: PsiStatement, lastStatement: PsiStatement) {
|
||||
val problemDescriptor = holder.manager.createProblemDescriptor(
|
||||
firstStatement,
|
||||
lastStatement,
|
||||
CAN_BE_JOINED_DESCRIPTION,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
|
||||
isOnTheFly,
|
||||
JoinStatementsQuickFix()
|
||||
)
|
||||
holder.registerProblem(problemDescriptor)
|
||||
}
|
||||
}
|
@ -3,9 +3,9 @@ package de.platon42.intellij.plugins.cajon.quickfixes
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import de.platon42.intellij.plugins.cajon.findStaticMethodCall
|
||||
import de.platon42.intellij.plugins.cajon.shortenAndReformat
|
||||
|
||||
class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
|
||||
|
||||
@ -48,6 +48,6 @@ class JoinStatementsQuickFix : AbstractCommonQuickFix(JOIN_STATEMENTS_MESSAGE) {
|
||||
previousStatement.delete()
|
||||
} while (previousStatement !== firstStatement)
|
||||
val codeBlock = PsiTreeUtil.getParentOfType(lastStatement, PsiCodeBlock::class.java) ?: return
|
||||
CodeStyleManager.getInstance(project).reformat(codeBlock)
|
||||
codeBlock.shortenAndReformat()
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package de.platon42.intellij.plugins.cajon.quickfixes
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiBlockStatement
|
||||
import com.intellij.psi.PsiDeclarationStatement
|
||||
import com.intellij.psi.PsiIfStatement
|
||||
import de.platon42.intellij.plugins.cajon.*
|
||||
|
||||
class ReplaceIfByAssumeThatQuickFix(private val removeElse: Boolean) : AbstractCommonQuickFix(REPLACE_IF_MESSAGE) {
|
||||
|
||||
companion object {
|
||||
private const val REPLACE_IF_MESSAGE = "Replace if statement by assumeTrue()"
|
||||
}
|
||||
|
||||
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
|
||||
val ifStatement = descriptor.startElement as PsiIfStatement
|
||||
|
||||
val condition = ifStatement.condition ?: return
|
||||
val factory = JavaPsiFacade.getElementFactory(ifStatement.project)
|
||||
val assumptionExpression = if (removeElse) MethodNames.IS_TRUE else MethodNames.IS_FALSE
|
||||
val assumeThatStatement = factory.createStatementFromText(
|
||||
"${AssertJClassNames.ASSUMPTIONS_CLASSNAME}.${MethodNames.ASSUME_THAT}(true).$assumptionExpression();",
|
||||
ifStatement
|
||||
)
|
||||
val assumeThatMethodCall = assumeThatStatement.findStaticMethodCall() ?: return
|
||||
assumeThatMethodCall.firstArg.replace(condition)
|
||||
assumeThatMethodCall.resolveMethod()?.addAsStaticImport(ifStatement)
|
||||
|
||||
val branchToKeep = (if (removeElse) ifStatement.thenBranch else ifStatement.elseBranch)?.copy()
|
||||
val parentBlock = ifStatement.parent
|
||||
if (branchToKeep != null) {
|
||||
val anchorElement = ifStatement.nextSibling
|
||||
if (branchToKeep is PsiBlockStatement) {
|
||||
val codeBlock = branchToKeep.codeBlock
|
||||
val hasDeclarations = codeBlock.statements.any { it is PsiDeclarationStatement }
|
||||
if (hasDeclarations) {
|
||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||
} else {
|
||||
parentBlock.addRangeAfter(codeBlock.firstBodyElement, codeBlock.lastBodyElement, anchorElement)
|
||||
}
|
||||
} else {
|
||||
parentBlock.addAfter(branchToKeep, anchorElement)
|
||||
}
|
||||
}
|
||||
ifStatement.replace(assumeThatStatement).shortenAndReformat()
|
||||
}
|
||||
}
|
@ -45,6 +45,8 @@
|
||||
|
||||
<localInspection groupPath="Java" shortName="JoinAssertThatStatements" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.JoinAssertThatStatementsInspection"/>
|
||||
<localInspection groupPath="Java" shortName="AssumeThatInsteadOfReturnInspection" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssumeThatInsteadOfReturnInspection"/>
|
||||
|
||||
<localInspection groupPath="Java" shortName="AssertThatJava8Optional" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="de.platon42.intellij.plugins.cajon.inspections.AssertThatJava8OptionalInspection"/>
|
||||
|
@ -0,0 +1,18 @@
|
||||
<html>
|
||||
<body>
|
||||
Tries to detect bogus uses of return statements in test methods and replaces them by assumeThat() calls.
|
||||
<!-- tooltip end -->
|
||||
<br>
|
||||
Novices will use these to skip test execution by bailing out early on some preconditions not met.
|
||||
However, this suggests that the test has actually been run and passed instead of showing the test
|
||||
as being skipped.
|
||||
<p>Return statements in if statements in main test methods
|
||||
(must be annotated with JUnit 4 or Jupiter @Test annotations)
|
||||
will be verified to have at least one assertThat() statement in the code flow.
|
||||
Method calls within the same class will be examined for assertThat() statements, too.
|
||||
However, at most 50 statements and down to five recursions will be tolerated before giving up.
|
||||
</p>
|
||||
<p>Currently, the quickfix may lose some comments during operation. The other branch of the if statement
|
||||
will be inlined (blocks with declarations will remain a code block due to variable scope).</p>
|
||||
</body>
|
||||
</html>
|
@ -1,11 +1,11 @@
|
||||
<html>
|
||||
<body>
|
||||
Tries to convert most of the JUnit 4 assertions to AssertJ-Format.
|
||||
Tries to convert most of the JUnit 4 assertions to AssertJ format.
|
||||
<!-- tooltip end -->
|
||||
<br>Works for assertTrue(), assertFalse(), assertNull(), assertNotNull(), assertEquals(), assertNotEquals(), assertSame() assertNotSame(), assertArrayEquals().
|
||||
Copes with variants with message and without, handles special versions for double and float types (including arrays).
|
||||
<p>
|
||||
Does not support Hamcrest-Matchers. If you need that kind of conversion, you might want to check out the Assertions2AssertJ plugin by Ric Emery.
|
||||
Does not support Hamcrest-Matchers. If you need that kind of conversion, you might want to check out the Assertions2AssertJ plugin by Ric Emery.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@ -1,449 +0,0 @@
|
||||
package de.platon42.intellij.playground;
|
||||
|
||||
import org.assertj.core.api.ListAssert;
|
||||
import org.assertj.core.data.Offset;
|
||||
import org.assertj.core.extractor.Extractors;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.data.Offset.offset;
|
||||
import static org.assertj.guava.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class Playground {
|
||||
|
||||
private void sizeOfList() {
|
||||
assertThat("string").as("foo").hasSize(0);
|
||||
assertThat(new StringBuilder()).as("bar").hasSize(0);
|
||||
ListAssert<String> etc = assertThat(new ArrayList<String>()).as("etc");
|
||||
etc.hasSize(0);
|
||||
assertThat(new Long[1]).as("etc").hasSize(0);
|
||||
|
||||
assertThat("string").as("foo").isEmpty();
|
||||
assertThat(new StringBuilder()).as("bar").isEmpty();
|
||||
assertThat(new ArrayList<Long>()).as("etc").isEmpty();
|
||||
assertThat(new Long[1]).as("etc").isEmpty();
|
||||
|
||||
assertThat(new ArrayList<>().size()).isEqualTo(1);
|
||||
assertThat(new ArrayList<String>().size()).isEqualTo(1);
|
||||
assertThat(new ArrayList<String>().size()).isGreaterThanOrEqualTo(1);
|
||||
assertThat(new ArrayList<String>().size()).isZero();
|
||||
assertThat(new ArrayList<String>()).hasSizeGreaterThan(1);
|
||||
assertThat(new ArrayList<String>()).hasSameSizeAs(new ArrayList<>());
|
||||
assertThat(new Long[1]).as("etc").hasSameSizeAs(new Long[2]);
|
||||
assertThat(new Long[1]).as("etc").hasSameSizeAs(new Long[2]);
|
||||
}
|
||||
|
||||
private void joinStatements() {
|
||||
List<String> list = new ArrayList<>();
|
||||
assertThat(list).as("foo").hasSize(2);
|
||||
assertThat(list).as("bar").contains("barbar"); // comment to keep
|
||||
assertThat(list).as("etc").contains("etcetc");
|
||||
|
||||
// moar!
|
||||
assertThat(list).doesNotContain("foobar");
|
||||
|
||||
assertThat("narf").isNotEqualTo("puit");
|
||||
assertThat(list).as("bar").contains("barbar");
|
||||
assertThat(list).as("foo").hasSize(2);
|
||||
assertThat(list).as("evil").extracting(String::length).contains(2);
|
||||
|
||||
assertThat(list).as("bar").contains("barbar");
|
||||
assertThat("narf").isNotEqualTo("puit");
|
||||
assertThat(list).as("foo").hasSize(2);
|
||||
if (true) {
|
||||
assertThat(list).doesNotContain("narf");
|
||||
assertThat(list).as("bar").contains("barbar");
|
||||
}
|
||||
assertThat(list.get(0)).isNotEmpty();
|
||||
assertThat(list.get(0)).hasSize(3);
|
||||
assertThat(list.get(0)).isEqualTo("bar");
|
||||
|
||||
assertThat(list.get(0) + "foo").isEqualTo("bar");
|
||||
assertThat(list.get(0) + "foo").doesNotStartWith("foo");
|
||||
|
||||
Iterator<String> iterator = list.iterator();
|
||||
assertThat(iterator.next()).isEqualTo("foo");
|
||||
assertThat(iterator.next()).isEqualTo("bar");
|
||||
}
|
||||
|
||||
private void sizeOfArray() {
|
||||
assertThat(new String[1].length).isLessThanOrEqualTo(1);
|
||||
assertThat(new String[1]).hasSameSizeAs(new Object());
|
||||
assertThat("").isEqualTo(null);
|
||||
assertThat(true).isTrue();
|
||||
assertThat(true).isEqualTo(true);
|
||||
assertThat(Boolean.TRUE).isEqualTo(Boolean.FALSE);
|
||||
assertThat(Boolean.TRUE).isEqualTo(true);
|
||||
}
|
||||
|
||||
private void booleanIsTrueOrFalse() {
|
||||
boolean primitive = false;
|
||||
Boolean object = java.lang.Boolean.TRUE;
|
||||
|
||||
assertThat(primitive).isEqualTo(Boolean.TRUE);
|
||||
assertThat(primitive).isEqualTo(Boolean.FALSE);
|
||||
assertThat(object).isEqualTo(Boolean.TRUE);
|
||||
assertThat(object).isEqualTo(Boolean.FALSE);
|
||||
assertThat(primitive).isEqualTo(true);
|
||||
assertThat(primitive).isEqualTo(false);
|
||||
assertThat(object).isEqualTo(true);
|
||||
assertThat(object).isEqualTo(false);
|
||||
|
||||
assertThat(primitive).isNotEqualTo(Boolean.TRUE);
|
||||
assertThat(primitive).isNotEqualTo(Boolean.FALSE);
|
||||
assertThat(object).isNotEqualTo(Boolean.TRUE);
|
||||
assertThat(object).isNotEqualTo(Boolean.FALSE);
|
||||
assertThat(primitive).isNotEqualTo(true);
|
||||
assertThat(primitive).isNotEqualTo(false);
|
||||
assertThat(object).isNotEqualTo(true);
|
||||
assertThat(object).isNotEqualTo(false);
|
||||
|
||||
assertThat(primitive).as("nah").isEqualTo(true && !true);
|
||||
assertThat(object).isEqualTo(Boolean.TRUE && !Boolean.TRUE);
|
||||
|
||||
assertThat("").isEqualTo(Boolean.TRUE);
|
||||
}
|
||||
|
||||
private void binaryExpression() {
|
||||
int primExp = 42;
|
||||
int primAct = 1337;
|
||||
Double numberObjExp = 42.0;
|
||||
Double numberObjAct = 1337.0;
|
||||
String stringExp = "foo";
|
||||
String stringAct = "bar";
|
||||
|
||||
assertThat(primAct == primExp).isTrue();
|
||||
assertThat(primAct == 1).isTrue();
|
||||
assertThat(primAct == primExp).isEqualTo(false);
|
||||
assertThat(primAct != primExp).isEqualTo(true);
|
||||
assertThat(1 != primAct).isTrue();
|
||||
assertThat(primAct != primExp).isNotEqualTo(true);
|
||||
assertThat(primAct > primExp).isNotEqualTo(false);
|
||||
assertThat(primAct > primExp).isFalse();
|
||||
assertThat(primAct > 1).isFalse();
|
||||
assertThat(primAct >= 1).isTrue();
|
||||
assertThat(primAct >= primExp).isEqualTo(false);
|
||||
assertThat(1 <= primAct).isFalse();
|
||||
assertThat(1 > primAct).isTrue();
|
||||
assertThat(primAct < primExp).isNotEqualTo(true);
|
||||
assertThat(primAct <= primExp).isNotEqualTo(false);
|
||||
assertThat(primAct <= primExp).isFalse();
|
||||
assertThat(primAct <= 1).isFalse();
|
||||
assertThat(numberObjAct == 1).isTrue();
|
||||
assertThat(numberObjAct == numberObjExp).isEqualTo(false);
|
||||
assertThat(numberObjAct != numberObjExp).isEqualTo(true);
|
||||
assertThat(1 != numberObjAct).isTrue();
|
||||
assertThat(numberObjAct != numberObjExp).isNotEqualTo(true);
|
||||
assertThat(numberObjAct > numberObjExp).isNotEqualTo(false);
|
||||
assertThat(numberObjAct > 1).isFalse();
|
||||
assertThat(numberObjAct >= numberObjExp).isTrue();
|
||||
assertThat(numberObjAct >= numberObjExp).isEqualTo(false);
|
||||
assertThat(1 <= numberObjAct).isFalse();
|
||||
assertThat(numberObjAct < numberObjExp).isEqualTo(true);
|
||||
assertThat(numberObjAct < numberObjExp).isNotEqualTo(true);
|
||||
assertThat(numberObjAct <= numberObjExp).isNotEqualTo(false);
|
||||
assertThat(numberObjAct <= 1).isFalse();
|
||||
assertThat(numberObjAct.equals(numberObjExp)).isFalse();
|
||||
assertThat(stringAct == stringExp).isNotEqualTo(false);
|
||||
assertThat(stringAct.equals(stringExp)).isEqualTo(true);
|
||||
assertThat(stringAct != stringExp).isFalse();
|
||||
assertThat(stringAct == null).isNotEqualTo(true);
|
||||
assertThat(null == stringAct).isEqualTo(false);
|
||||
|
||||
assertThat(null == null).isTrue();
|
||||
assertThat(!false).isTrue();
|
||||
}
|
||||
|
||||
private void stringStuff() {
|
||||
String foo = "bar";
|
||||
assertThat(foo).isEqualTo("");
|
||||
assertThat(foo).hasSize(0);
|
||||
assertThat(foo.contains("foobar")).isTrue();
|
||||
assertThat(foo).contains("foobar");
|
||||
assertThat(foo.startsWith("foobar")).isTrue();
|
||||
assertThat(foo).startsWith("foobar");
|
||||
assertThat(foo.endsWith("foobar")).isTrue();
|
||||
assertThat(foo).endsWith("foobar");
|
||||
assertThat(foo.equalsIgnoreCase("foo")).isTrue();
|
||||
assertThat(foo).isEqualToIgnoringCase("foo");
|
||||
|
||||
assertThat(foo.contains("foobar")).isFalse();
|
||||
assertThat(foo).doesNotContain("foobar");
|
||||
assertThat(foo.startsWith("foobar")).isFalse();
|
||||
assertThat(foo).doesNotStartWith("foobar");
|
||||
assertThat(foo.endsWith("foobar")).isFalse();
|
||||
assertThat(foo).doesNotEndWith("foobar");
|
||||
assertThat(foo.equalsIgnoreCase("foo")).isFalse();
|
||||
assertThat(foo).isNotEqualToIgnoringCase("foo");
|
||||
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
long[] otherArray = new long[4];
|
||||
|
||||
String string = "string";
|
||||
assertThat(string.length()).isEqualTo(0);
|
||||
assertThat(string.length()).isZero();
|
||||
assertThat(string.length()).isNotZero();
|
||||
assertThat(string.length()).as("hi").isGreaterThan(0);
|
||||
assertThat(string.length()).isGreaterThanOrEqualTo(1);
|
||||
assertThat(string.length()).isLessThan(1);
|
||||
assertThat(string.length()).isLessThanOrEqualTo(0);
|
||||
assertThat(string.length()).isEqualTo(list.size());
|
||||
assertThat(string.length()).isEqualTo(otherArray.length);
|
||||
assertThat(string.length()).isEqualTo(1);
|
||||
assertThat(string.length()).isGreaterThan(otherArray.length - 1);
|
||||
assertThat(string.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
|
||||
assertThat(string.length()).isLessThan(otherArray.length - 3);
|
||||
assertThat(string.length()).isLessThanOrEqualTo(1 - otherArray.length);
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
assertThat(stringBuilder.length()).isEqualTo(0);
|
||||
assertThat(stringBuilder.length()).isZero();
|
||||
assertThat(stringBuilder.length()).isNotZero();
|
||||
assertThat(stringBuilder.length()).as("hi").isGreaterThan(0);
|
||||
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(1);
|
||||
assertThat(stringBuilder.length()).isLessThan(1);
|
||||
assertThat(stringBuilder.length()).isLessThanOrEqualTo(0);
|
||||
assertThat(stringBuilder.length()).isEqualTo(list.size());
|
||||
assertThat(stringBuilder.length()).isEqualTo(otherArray.length);
|
||||
assertThat(stringBuilder.length()).isEqualTo(1);
|
||||
assertThat(stringBuilder.length()).isGreaterThan(otherArray.length - 1);
|
||||
assertThat(stringBuilder.length()).isGreaterThanOrEqualTo(otherArray.length + 1);
|
||||
assertThat(stringBuilder.length()).isLessThan(otherArray.length - 3);
|
||||
assertThat(stringBuilder.length()).isLessThanOrEqualTo(1 - otherArray.length);
|
||||
}
|
||||
|
||||
private void java8Optional() {
|
||||
Optional<String> opt = Optional.empty();
|
||||
|
||||
assertThat(opt.isPresent()).isEqualTo(true);
|
||||
assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(false);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE);
|
||||
assertThat(opt.isPresent()).isTrue();
|
||||
|
||||
assertThat(opt.isPresent()).isEqualTo(false);
|
||||
assertThat(opt.isPresent()).isEqualTo(Boolean.FALSE);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(true);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE);
|
||||
assertThat(opt.isPresent()).isFalse();
|
||||
|
||||
assertThat(opt.get()).isEqualTo("foo");
|
||||
assertThat(opt.get()).isSameAs("foo");
|
||||
|
||||
assertThat(opt).isEqualTo(Optional.of("foo"));
|
||||
assertThat(opt).isEqualTo(Optional.ofNullable("foo"));
|
||||
assertThat(opt).isNotEqualTo(Optional.of("foo"));
|
||||
assertThat(opt).isNotEqualTo(Optional.ofNullable("foo"));
|
||||
|
||||
assertThat(opt).isEqualTo(Optional.empty());
|
||||
assertThat(opt).isNotEqualTo(Optional.empty());
|
||||
assertThat(opt).isPresent();
|
||||
}
|
||||
|
||||
private void assertThatGuavaOptional() {
|
||||
com.google.common.base.Optional<String> opt = com.google.common.base.Optional.absent();
|
||||
|
||||
assertThat(opt.isPresent()).isEqualTo(true);
|
||||
assertThat(opt.isPresent()).isEqualTo(Boolean.TRUE);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(false);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(Boolean.FALSE);
|
||||
assertThat(opt.isPresent()).isTrue();
|
||||
|
||||
assertThat(opt.isPresent()).isEqualTo(false);
|
||||
assertThat(opt.isPresent()).isEqualTo(Boolean.FALSE);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(true);
|
||||
assertThat(opt.isPresent()).isNotEqualTo(Boolean.TRUE);
|
||||
assertThat(opt.isPresent()).isFalse();
|
||||
|
||||
assertThat(opt.get()).isEqualTo("foo");
|
||||
assertThat(opt.get()).isSameAs("foo");
|
||||
assertThat(opt.get()).isNotEqualTo("foo");
|
||||
assertThat(opt.get()).isNotSameAs("foo");
|
||||
|
||||
assertThat(opt).isEqualTo(com.google.common.base.Optional.of("foo"));
|
||||
assertThat(opt).isEqualTo(com.google.common.base.Optional.fromNullable("foo"));
|
||||
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.of("foo"));
|
||||
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.fromNullable("foo"));
|
||||
|
||||
assertThat(opt).isEqualTo(com.google.common.base.Optional.absent());
|
||||
assertThat(opt).isNotEqualTo(com.google.common.base.Optional.absent());
|
||||
assertThat(opt).isAbsent();
|
||||
}
|
||||
|
||||
private void assertThatInstance() {
|
||||
String foo = "foo";
|
||||
assertThat(foo instanceof String).isTrue();
|
||||
assertThat(foo).isInstanceOf(String.class);
|
||||
assertThat(foo).isNotInstanceOf(String.class);
|
||||
}
|
||||
|
||||
private void junitAssertions() {
|
||||
assertFalse(!(new int[3].length == new ArrayList<Integer>().size()));
|
||||
assertThat(!(new int[3].length == new ArrayList<Integer>().size())).isFalse();
|
||||
assertThat((new int[3].length == new ArrayList<Integer>().size())).isTrue();
|
||||
assertThat(new int[3].length == new ArrayList<Integer>().size()).isTrue();
|
||||
assertThat(new int[3].length).isEqualTo(new ArrayList<Integer>().size());
|
||||
assertThat(new int[3]).hasSameSizeAs(new ArrayList<Integer>());
|
||||
|
||||
assertTrue(true);
|
||||
assertTrue("message", true);
|
||||
assertFalse(true);
|
||||
assertFalse("message", true);
|
||||
assertEquals(1L, 2L);
|
||||
assertEquals("message", 1L, 2L);
|
||||
assertNotEquals(1L, 2L);
|
||||
assertNotEquals("message", 1L, 2L);
|
||||
assertEquals(4.0, 4.4, 3.3);
|
||||
assertThat(3.0).isCloseTo(4.0, Offset.offset(2.3));
|
||||
assertThat(new int[1]).isEqualTo(new int[2]);
|
||||
|
||||
String foo = "foo";
|
||||
String bar = "bar";
|
||||
|
||||
assertTrue(foo == "foo");
|
||||
assertTrue("oh no!", foo == "foo");
|
||||
assertFalse(foo == "bar");
|
||||
assertFalse("boom!", foo == "bar");
|
||||
|
||||
assertNull(foo);
|
||||
assertNull("oh no!", foo);
|
||||
assertNotNull(foo);
|
||||
assertNotNull("oh no!", foo);
|
||||
|
||||
assertEquals(bar, foo);
|
||||
assertEquals("equals", bar, foo);
|
||||
assertNotEquals(bar, foo);
|
||||
assertNotEquals("equals", bar, foo);
|
||||
|
||||
assertSame(bar, foo);
|
||||
assertSame("same", bar, foo);
|
||||
assertNotSame(bar, foo);
|
||||
assertNotSame("same", bar, foo);
|
||||
|
||||
assertEquals(1.0, 2.0, 0.1);
|
||||
assertEquals("equals", 1.0, 2.0, 0.1);
|
||||
assertEquals(1.0f, 2.0f, 0.1f);
|
||||
assertEquals("equals", 1.0f, 2.0f, 0.1f);
|
||||
|
||||
assertNotEquals(1.0, 2.0);
|
||||
assertNotEquals(1.0, 2.0, 0.1);
|
||||
assertNotEquals("equals", 1.0, 2.0);
|
||||
assertNotEquals("equals", 1.0, 2.0, 0.1);
|
||||
assertNotEquals(1.0f, 2.0f);
|
||||
assertNotEquals(1.0f, 2.0f, 0.1f);
|
||||
assertNotEquals("equals", 1.0f, 2.0f);
|
||||
assertNotEquals("equals", 1.0f, 2.0f, 0.1f);
|
||||
|
||||
assertArrayEquals(new int[2], new int[1]);
|
||||
assertArrayEquals("array equals", new int[2], new int[1]);
|
||||
|
||||
assertArrayEquals(new double[2], new double[1], 1.0);
|
||||
assertArrayEquals("array equals", new double[2], new double[1], 1.0);
|
||||
assertArrayEquals(new float[2], new float[1], 1.0f);
|
||||
assertArrayEquals("array equals", new float[2], new float[1], 1.0f);
|
||||
|
||||
|
||||
assertThat(foo == "foo").isTrue();
|
||||
assertThat(foo == "foo").as("oh no!").isTrue();
|
||||
assertThat(foo == "bar").isFalse();
|
||||
assertThat(foo == "bar").as("boom!").isFalse();
|
||||
|
||||
assertThat(foo).isNull();
|
||||
assertThat(foo).as("oh no!").isNull();
|
||||
assertThat(foo).isNotNull();
|
||||
assertThat(foo).as("oh no!").isNotNull();
|
||||
|
||||
assertThat(foo).isEqualTo(bar);
|
||||
assertThat(foo).as("equals").isEqualTo(bar);
|
||||
assertThat(foo).isNotEqualTo(bar);
|
||||
assertThat(foo).as("equals").isNotEqualTo(bar);
|
||||
|
||||
assertThat(foo).isSameAs(bar);
|
||||
assertThat(foo).as("same").isSameAs(bar);
|
||||
assertThat(foo).isNotSameAs(bar);
|
||||
assertThat(foo).as("same").isNotSameAs(bar);
|
||||
|
||||
assertThat(2.0).isEqualTo(1.0);
|
||||
assertThat(2.0).isCloseTo(1.0, offset(0.1));
|
||||
assertThat(2.0).as("equals").isEqualTo(1.0);
|
||||
assertThat(2.0).as("equals").isCloseTo(1.0, offset(0.1));
|
||||
assertThat(2.0f).isEqualTo(1.0f);
|
||||
assertThat(2.0f).isCloseTo(1.0f, offset(0.1f));
|
||||
assertThat(2.0f).as("equals").isEqualTo(1.0f);
|
||||
assertThat(2.0f).as("equals").isCloseTo(1.0f, offset(0.1f));
|
||||
|
||||
assertThat(2.0).isNotEqualTo(1.0);
|
||||
assertThat(2.0).isNotCloseTo(1.0, offset(0.1));
|
||||
assertThat(2.0).as("equals").isNotEqualTo(1.0);
|
||||
assertThat(2.0).as("equals").isNotCloseTo(1.0, offset(0.1));
|
||||
assertThat(2.0f).isNotEqualTo(1.0f);
|
||||
assertThat(2.0f).isNotCloseTo(1.0f, offset(0.1f));
|
||||
assertThat(2.0f).as("equals").isNotEqualTo(1.0f);
|
||||
assertThat(2.0f).as("equals").isNotCloseTo(1.0f, offset(0.1f));
|
||||
|
||||
assertThat(new int[1]).isEqualTo(new int[2]);
|
||||
assertThat(new int[1]).as("array equals").isEqualTo(new int[2]);
|
||||
|
||||
assertThat(new double[1]).containsExactly(new double[2], offset(1.0));
|
||||
assertThat(new double[1]).as("array equals").containsExactly(new double[2], offset(1.0));
|
||||
assertThat(new float[1]).containsExactly(new float[2], offset(1.0f));
|
||||
assertThat(new float[1]).as("array equals").containsExactly(new float[2], offset(1.0f));
|
||||
|
||||
assertThat(new Object()).extracting("toString");
|
||||
assertThat(new Object()).extracting(Object::toString, Object::hashCode);
|
||||
}
|
||||
|
||||
private void findReferences() {
|
||||
Contact contact = new Contact();
|
||||
List<Contact> contactList = Collections.emptyList();
|
||||
|
||||
assertThat(contact).extracting("name").isEqualTo("foo");
|
||||
assertThat(contact).extracting("age", "country", "address.street", "street", "address.noMailings", "address.REALLYnoMAILINGS").containsExactly(1, "Elmst. 42");
|
||||
assertThat(contact).extracting(Extractors.byName("name")).isEqualTo("foo");
|
||||
assertThat(contact).extracting(Extractors.resultOf("getStreet")).isEqualTo("foo");
|
||||
assertThat(contact).extracting(Extractors.resultOf("getStreet"), Extractors.byName("narf")).isEqualTo("foo");
|
||||
|
||||
assertThat(contactList).extracting("name").isEqualTo("foo");
|
||||
assertThat(contactList).extracting("name", "moar").isEqualTo("foo");
|
||||
assertThat(contactList).extracting("name", String.class).isEqualTo("foo");
|
||||
assertThat(contactList).extracting(Extractors.byName("name")).isEqualTo("foo");
|
||||
assertThat(contactList).extracting(Extractors.resultOf("getStreet"), Extractors.byName("narf")).isEqualTo("foo");
|
||||
assertThat(contactList).extractingResultOf("getStreet").isEqualTo("foo");
|
||||
assertThat(contactList).extractingResultOf("getStreet", String.class).isEqualTo("foo");
|
||||
assertThat(contactList).flatExtracting("age", "address.street", "street").containsExactly(1, "Elmst. 42");
|
||||
assertThat(contactList).flatExtracting("age").containsExactly(1, "Elmst. 42");
|
||||
}
|
||||
|
||||
public class Contact {
|
||||
private String name;
|
||||
private Integer age;
|
||||
private Address address;
|
||||
|
||||
public String getStreet() {
|
||||
return address.getStreet();
|
||||
}
|
||||
}
|
||||
|
||||
public class Address {
|
||||
private String street;
|
||||
private String country;
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public boolean isNoMailings() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Boolean getREALLYnoMAILINGS() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -11,13 +11,17 @@ import de.platon42.intellij.jupiter.TestDataPath
|
||||
import de.platon42.intellij.jupiter.TestJdk
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.DisplayNameGeneration
|
||||
import org.junit.jupiter.api.DisplayNameGenerator
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.lang.reflect.Method
|
||||
|
||||
@ExtendWith(LightCodeInsightExtension::class)
|
||||
@TestDataPath("src/test/resources")
|
||||
@TestJdk(LanguageLevel.JDK_1_8, annotations = true, useInternal = true)
|
||||
@AddLocalJarToModule(Assertions::class)
|
||||
@DisplayNameGeneration(AbstractCajonTest.CutOffFixtureDisplayNameGenerator::class)
|
||||
abstract class AbstractCajonTest {
|
||||
|
||||
// See https://github.com/junit-team/junit5/issues/157, should be resolved with junit5 5.5 M2
|
||||
@ -64,4 +68,11 @@ abstract class AbstractCajonTest {
|
||||
assertThat(quickfixes).`as`("Fixes matched by $regex: ${myFixture.getAllQuickFixes().map { it.text }}").hasSize(expectedFixes)
|
||||
quickfixes.forEach(myFixture::launchAction)
|
||||
}
|
||||
|
||||
class CutOffFixtureDisplayNameGenerator : DisplayNameGenerator.ReplaceUnderscores() {
|
||||
override fun generateDisplayNameForMethod(testClass: Class<*>?, testMethod: Method?): String {
|
||||
val nameForMethod = super.generateDisplayNameForMethod(testClass, testMethod)
|
||||
return nameForMethod.substringBefore("$")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package de.platon42.intellij.plugins.cajon.inspections
|
||||
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import de.platon42.intellij.jupiter.AddLocalJarToModule
|
||||
import de.platon42.intellij.jupiter.MyFixture
|
||||
import de.platon42.intellij.jupiter.TestDataSubPath
|
||||
import de.platon42.intellij.plugins.cajon.AbstractCajonTest
|
||||
import org.assertj.core.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
@AddLocalJarToModule(Assertions::class, Test::class, org.junit.Test::class)
|
||||
internal class AssumeThatInsteadOfReturnInspectionTest : AbstractCajonTest() {
|
||||
|
||||
@Test
|
||||
@TestDataSubPath("inspections/AssumeThat")
|
||||
internal fun conditional_returns_can_be_replaced_by_assumeThat(@MyFixture myFixture: JavaCodeInsightTestFixture) {
|
||||
runTest {
|
||||
myFixture.enableInspections(AssumeThatInsteadOfReturnInspection::class.java)
|
||||
myFixture.configureByFile("AssumeThatBefore.java")
|
||||
executeQuickFixes(myFixture, Regex.fromLiteral("Replace if statement by assumeTrue()"), 4)
|
||||
myFixture.checkResultByFile("AssumeThatAfter.java")
|
||||
}
|
||||
}
|
||||
}
|
151
src/test/resources/inspections/AssumeThat/AssumeThatAfter.java
Normal file
151
src/test/resources/inspections/AssumeThat/AssumeThatAfter.java
Normal file
@ -0,0 +1,151 @@
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
public class AssumeThat {
|
||||
|
||||
@Test
|
||||
public void junit4_return_very_early() {
|
||||
assumeThat(new Random().nextBoolean()).isFalse();
|
||||
System.out.println("sweet!"); // single else statement
|
||||
String foobar = System.getProperty("foobar");
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_in_else_branch_with_declaration_in_code_block_and_lots_of_comments() {
|
||||
// primary comments
|
||||
assumeThat(new Random().nextBoolean()).isTrue();
|
||||
{
|
||||
// Block start comment will be retained
|
||||
String anotherString = "narf"; // This one is likely to be kept
|
||||
assertThat(foobar).isNotEmpty();
|
||||
assertThat(foobar).isEqualTo(anotherString);
|
||||
// Block end comment is also going to be retained
|
||||
} /* weird places */
|
||||
// well, well, let's do some checks
|
||||
String foobar = System.getProperty("foobar");
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
public void junit5_return_after_call_without_else_branch() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
assumeThat(foobar.equals("Volkswagen")).isFalse();
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.TestTemplate
|
||||
public void junit5_return_inside_recursion_with_comments() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
if (foobar != null) {
|
||||
assumeThat(!foobar.equals("Volkswagen")).isTrue();
|
||||
// I doubted this comment will be retained -- but surprise!
|
||||
assertThat(foobar).isNotEmpty();
|
||||
// we might keep this one alright.
|
||||
foobar = "narf";
|
||||
// And the final one? Again what learned.
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
if(foobar.length() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).endsWith("!!!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
assertThat(foobar).isNotNull();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_subroutine() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
assertStuff(foobar);
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_deep_subroutine() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
firstMethod();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_deep_subroutine_with_recursion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
firstMethodWithPotentialRecursion();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_no_harm_with_infinite_recursion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
infiniteRecursion();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
private void assertStuff(String foobar) {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
assertThat(foobar).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
private void firstMethod() {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertStuff("narf");
|
||||
}
|
||||
}
|
||||
|
||||
private void firstMethodWithPotentialRecursion() {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertStuff("narf");
|
||||
} else {
|
||||
infiniteRecursion();
|
||||
}
|
||||
}
|
||||
|
||||
private void infiniteRecursion() {
|
||||
secondaryRecursion();
|
||||
secondaryRecursion();
|
||||
}
|
||||
|
||||
private void secondaryRecursion() {
|
||||
infiniteRecursion();
|
||||
infiniteRecursion();
|
||||
}
|
||||
}
|
156
src/test/resources/inspections/AssumeThat/AssumeThatBefore.java
Normal file
156
src/test/resources/inspections/AssumeThat/AssumeThatBefore.java
Normal file
@ -0,0 +1,156 @@
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class AssumeThat {
|
||||
|
||||
@Test
|
||||
public void junit4_return_very_early() {
|
||||
if (new Random().nextBoolean()) {
|
||||
return;
|
||||
} else System.out.println("sweet!"); // single else statement
|
||||
String foobar = System.getProperty("foobar");
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_in_else_branch_with_declaration_in_code_block_and_lots_of_comments() {
|
||||
// primary comments
|
||||
if (new Random().nextBoolean()) /* strange place for a comment */ {
|
||||
// Block start comment will be retained
|
||||
String anotherString = "narf"; // This one is likely to be kept
|
||||
assertThat(foobar).isNotEmpty();
|
||||
assertThat(foobar).isEqualTo(anotherString);
|
||||
// Block end comment is also going to be retained
|
||||
} /* weird places */ else /* more weird places */ { // this one is lost
|
||||
return; // Would be sweet to keep this comment, too.
|
||||
} // another comment lost
|
||||
// well, well, let's do some checks
|
||||
String foobar = System.getProperty("foobar");
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.Test
|
||||
public void junit5_return_after_call_without_else_branch() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
if (foobar.equals("Volkswagen")) return; // no need for Volkswagen to perform tests
|
||||
assertThat(foobar).isNotEmpty();
|
||||
}
|
||||
|
||||
@org.junit.jupiter.api.TestTemplate
|
||||
public void junit5_return_inside_recursion_with_comments() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
if (foobar != null) {
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
// I doubted this comment will be retained -- but surprise!
|
||||
assertThat(foobar).isNotEmpty();
|
||||
// we might keep this one alright.
|
||||
foobar = "narf";
|
||||
// And the final one? Again what learned.
|
||||
} else {
|
||||
// ooops, how did that happen?
|
||||
return;
|
||||
}
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
if(foobar.length() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).endsWith("!!!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
assertThat(foobar).isNotNull();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_subroutine() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
assertStuff(foobar);
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_deep_subroutine() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
firstMethod();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_return_after_assertions_in_deep_subroutine_with_recursion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
firstMethodWithPotentialRecursion();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void junit4_no_harm_with_infinite_recursion() {
|
||||
String foobar = System.getProperty("car_manufacturer");
|
||||
infiniteRecursion();
|
||||
if (!foobar.equals("Volkswagen")) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
assertThat(foobar).startsWith("another ecology rapist");
|
||||
}
|
||||
|
||||
private void assertStuff(String foobar) {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertThat(foobar).isNotEmpty();
|
||||
} else {
|
||||
assertThat(foobar).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
private void firstMethod() {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertStuff("narf");
|
||||
}
|
||||
}
|
||||
|
||||
private void firstMethodWithPotentialRecursion() {
|
||||
if (new Random().nextBoolean()) {
|
||||
assertStuff("narf");
|
||||
} else {
|
||||
infiniteRecursion();
|
||||
}
|
||||
}
|
||||
|
||||
private void infiniteRecursion() {
|
||||
secondaryRecursion();
|
||||
secondaryRecursion();
|
||||
}
|
||||
|
||||
private void secondaryRecursion() {
|
||||
infiniteRecursion();
|
||||
infiniteRecursion();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user