Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
TestSmells
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
f00f
TestSmells
Commits
a2fe4cc1
Commit
a2fe4cc1
authored
May 13, 2019
by
Tim Horst
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'refactor' into 'development'
Refactor See merge request
!7
parents
f4f396e0
14de7479
Pipeline
#588
passed with stage
in 40 seconds
Changes
75
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
75 changed files
with
3407 additions
and
1338 deletions
+3407
-1338
.gitignore
.gitignore
+1
-0
build.gradle
build.gradle
+24
-4
src/main/java/testsmell/AbstractSmell.java
src/main/java/testsmell/AbstractSmell.java
+29
-2
src/main/java/testsmell/SmellyElement.java
src/main/java/testsmell/SmellyElement.java
+17
-1
src/main/java/testsmell/TestClass.java
src/main/java/testsmell/TestClass.java
+48
-6
src/main/java/testsmell/TestFile.java
src/main/java/testsmell/TestFile.java
+84
-25
src/main/java/testsmell/TestMethod.java
src/main/java/testsmell/TestMethod.java
+50
-9
src/main/java/testsmell/TestSmellDetector.java
src/main/java/testsmell/TestSmellDetector.java
+46
-36
src/main/java/testsmell/Util.java
src/main/java/testsmell/Util.java
+39
-20
src/main/java/testsmell/package-info.java
src/main/java/testsmell/package-info.java
+7
-0
src/main/java/testsmell/smell/AssertionRoulette.java
src/main/java/testsmell/smell/AssertionRoulette.java
+88
-54
src/main/java/testsmell/smell/ConditionalTestLogic.java
src/main/java/testsmell/smell/ConditionalTestLogic.java
+114
-56
src/main/java/testsmell/smell/ConstructorInitialization.java
src/main/java/testsmell/smell/ConstructorInitialization.java
+69
-28
src/main/java/testsmell/smell/DefaultTest.java
src/main/java/testsmell/smell/DefaultTest.java
+53
-17
src/main/java/testsmell/smell/DependentTest.java
src/main/java/testsmell/smell/DependentTest.java
+0
-138
src/main/java/testsmell/smell/DuplicateAssert.java
src/main/java/testsmell/smell/DuplicateAssert.java
+94
-62
src/main/java/testsmell/smell/EagerTest.java
src/main/java/testsmell/smell/EagerTest.java
+142
-75
src/main/java/testsmell/smell/EmptyTest.java
src/main/java/testsmell/smell/EmptyTest.java
+43
-20
src/main/java/testsmell/smell/ExceptionCatchingThrowing.java
src/main/java/testsmell/smell/ExceptionCatchingThrowing.java
+70
-36
src/main/java/testsmell/smell/GeneralFixture.java
src/main/java/testsmell/smell/GeneralFixture.java
+117
-63
src/main/java/testsmell/smell/IgnoredTest.java
src/main/java/testsmell/smell/IgnoredTest.java
+55
-36
src/main/java/testsmell/smell/LazyTest.java
src/main/java/testsmell/smell/LazyTest.java
+155
-70
src/main/java/testsmell/smell/MagicNumberTest.java
src/main/java/testsmell/smell/MagicNumberTest.java
+78
-46
src/main/java/testsmell/smell/MysteryGuest.java
src/main/java/testsmell/smell/MysteryGuest.java
+78
-81
src/main/java/testsmell/smell/PrintStatement.java
src/main/java/testsmell/smell/PrintStatement.java
+76
-38
src/main/java/testsmell/smell/RedundantAssertion.java
src/main/java/testsmell/smell/RedundantAssertion.java
+88
-41
src/main/java/testsmell/smell/ResourceOptimism.java
src/main/java/testsmell/smell/ResourceOptimism.java
+0
-169
src/main/java/testsmell/smell/SensitiveEquality.java
src/main/java/testsmell/smell/SensitiveEquality.java
+70
-35
src/main/java/testsmell/smell/SleepyTest.java
src/main/java/testsmell/smell/SleepyTest.java
+68
-32
src/main/java/testsmell/smell/UnknownTest.java
src/main/java/testsmell/smell/UnknownTest.java
+84
-44
src/main/java/testsmell/smell/VerboseTest.java
src/main/java/testsmell/smell/VerboseTest.java
+0
-94
src/main/java/testsmell/smell/package-info.java
src/main/java/testsmell/smell/package-info.java
+7
-0
src/test/java/testsmell/TestClassTest.java
src/test/java/testsmell/TestClassTest.java
+22
-0
src/test/java/testsmell/TestFileTest.java
src/test/java/testsmell/TestFileTest.java
+44
-0
src/test/java/testsmell/TestMethodTest.java
src/test/java/testsmell/TestMethodTest.java
+28
-0
src/test/java/testsmell/UtilTest.java
src/test/java/testsmell/UtilTest.java
+139
-0
src/test/java/testsmell/smell/AssertionRouletteTest.java
src/test/java/testsmell/smell/AssertionRouletteTest.java
+52
-0
src/test/java/testsmell/smell/ConditionalTestLogicTest.java
src/test/java/testsmell/smell/ConditionalTestLogicTest.java
+49
-0
src/test/java/testsmell/smell/ConstructorInitializationTest.java
...t/java/testsmell/smell/ConstructorInitializationTest.java
+47
-0
src/test/java/testsmell/smell/DefaultTestTest.java
src/test/java/testsmell/smell/DefaultTestTest.java
+49
-0
src/test/java/testsmell/smell/DuplicateAssertTest.java
src/test/java/testsmell/smell/DuplicateAssertTest.java
+49
-0
src/test/java/testsmell/smell/EagerTestTest.java
src/test/java/testsmell/smell/EagerTestTest.java
+42
-0
src/test/java/testsmell/smell/EmptyTestTest.java
src/test/java/testsmell/smell/EmptyTestTest.java
+49
-0
src/test/java/testsmell/smell/ExceptionCatchingThrowingTest.java
...t/java/testsmell/smell/ExceptionCatchingThrowingTest.java
+49
-0
src/test/java/testsmell/smell/GeneralFixtureTest.java
src/test/java/testsmell/smell/GeneralFixtureTest.java
+49
-0
src/test/java/testsmell/smell/IgnoredTestTest.java
src/test/java/testsmell/smell/IgnoredTestTest.java
+50
-0
src/test/java/testsmell/smell/LazyTestTest.java
src/test/java/testsmell/smell/LazyTestTest.java
+54
-0
src/test/java/testsmell/smell/MagicNumberTestTest.java
src/test/java/testsmell/smell/MagicNumberTestTest.java
+50
-0
src/test/java/testsmell/smell/MysteryGuestTest.java
src/test/java/testsmell/smell/MysteryGuestTest.java
+49
-0
src/test/java/testsmell/smell/PrintStatementTest.java
src/test/java/testsmell/smell/PrintStatementTest.java
+49
-0
src/test/java/testsmell/smell/RedundantAssertionTest.java
src/test/java/testsmell/smell/RedundantAssertionTest.java
+49
-0
src/test/java/testsmell/smell/SensitiveEqualityTest.java
src/test/java/testsmell/smell/SensitiveEqualityTest.java
+49
-0
src/test/java/testsmell/smell/SleepyTestTest.java
src/test/java/testsmell/smell/SleepyTestTest.java
+45
-0
src/test/java/testsmell/smell/UnknownTestTest.java
src/test/java/testsmell/smell/UnknownTestTest.java
+50
-0
src/test/resources/testsmell/smell/ConditionalTest.java
src/test/resources/testsmell/smell/ConditionalTest.java
+11
-0
src/test/resources/testsmell/smell/Cryptographer.java
src/test/resources/testsmell/smell/Cryptographer.java
+6
-0
src/test/resources/testsmell/smell/CryptographerTest.java
src/test/resources/testsmell/smell/CryptographerTest.java
+23
-0
src/test/resources/testsmell/smell/DefaultDependencyResolverTest.java
...ources/testsmell/smell/DefaultDependencyResolverTest.java
+20
-0
src/test/resources/testsmell/smell/DefaultDependencyResolverTest2.java
...urces/testsmell/smell/DefaultDependencyResolverTest2.java
+10
-0
src/test/resources/testsmell/smell/DuplicateAssert.java
src/test/resources/testsmell/smell/DuplicateAssert.java
+12
-0
src/test/resources/testsmell/smell/EmptyTest.java
src/test/resources/testsmell/smell/EmptyTest.java
+8
-0
src/test/resources/testsmell/smell/ExampleUnitTest.java
src/test/resources/testsmell/smell/ExampleUnitTest.java
+17
-0
src/test/resources/testsmell/smell/Exception.java
src/test/resources/testsmell/smell/Exception.java
+39
-0
src/test/resources/testsmell/smell/GeneralFixture.java
src/test/resources/testsmell/smell/GeneralFixture.java
+36
-0
src/test/resources/testsmell/smell/IgnoredTest.java
src/test/resources/testsmell/smell/IgnoredTest.java
+14
-0
src/test/resources/testsmell/smell/MagicTest.java
src/test/resources/testsmell/smell/MagicTest.java
+8
-0
src/test/resources/testsmell/smell/MysteryTest.java
src/test/resources/testsmell/smell/MysteryTest.java
+23
-0
src/test/resources/testsmell/smell/NameSentence.java
src/test/resources/testsmell/smell/NameSentence.java
+89
-0
src/test/resources/testsmell/smell/NameSentenceTest.java
src/test/resources/testsmell/smell/NameSentenceTest.java
+13
-0
src/test/resources/testsmell/smell/PrintTest.java
src/test/resources/testsmell/smell/PrintTest.java
+11
-0
src/test/resources/testsmell/smell/RedundantTest.java
src/test/resources/testsmell/smell/RedundantTest.java
+6
-0
src/test/resources/testsmell/smell/SensitiveTest.java
src/test/resources/testsmell/smell/SensitiveTest.java
+18
-0
src/test/resources/testsmell/smell/SleepyTest.java
src/test/resources/testsmell/smell/SleepyTest.java
+6
-0
src/test/resources/testsmell/smell/TagEncodingTest.java
src/test/resources/testsmell/smell/TagEncodingTest.java
+21
-0
src/test/resources/testsmell/smell/UnknownTest.java
src/test/resources/testsmell/smell/UnknownTest.java
+9
-0
No files found.
.gitignore
View file @
a2fe4cc1
...
...
@@ -26,3 +26,4 @@ hs_err_pid*
.gradle
build
*.iml
/out/
build.gradle
View file @
a2fe4cc1
...
...
@@ -13,15 +13,35 @@ repositories {
}
dependencies
{
compile
'com.github.javaparser:javaparser-core:3.13.10'
compile
'com.opencsv:opencsv:3.9'
implementation
'com.github.javaparser:javaparser-core:3.13.10'
implementation
'com.opencsv:opencsv:3.9'
implementation
'javax.annotation:javax.annotation-api:1.3.2'
implementation
'com.google.code.findbugs:jsr305:3.0.+'
testImplementation
'org.assertj:assertj-core:3.12.+'
testImplementation
'org.junit.jupiter:junit-jupiter-api:5.4.+'
testImplementation
'org.junit.jupiter:junit-jupiter-params:5.4.+'
testRuntimeOnly
'org.junit.jupiter:junit-jupiter-engine:5.4.+'
}
group
=
'nl.f00f'
version
=
'0.0.
2
'
version
=
'0.0.
3
'
archivesBaseName
=
'test-smell-detector'
sourceCompatibility
=
'1.
8
'
sourceCompatibility
=
'1.
11
'
test
{
sourceCompatibility
=
'1.11'
targetCompatibility
=
'1.11'
failFast
=
true
testLogging
{
exceptionFormat
=
'FULL'
showStandardStreams
=
true
}
useJUnitPlatform
()
}
task
javadocJar
(
type:
Jar
)
{
classifier
=
'javadoc'
...
...
src/main/java/testsmell/AbstractSmell.java
View file @
a2fe4cc1
...
...
@@ -5,12 +5,39 @@ import com.github.javaparser.ast.CompilationUnit;
import
java.io.FileNotFoundException
;
import
java.util.List
;
/**
* An abstract class for a smell.
*/
public
abstract
class
AbstractSmell
{
/**
* Retrieves the name of the smell.
* @return The name of the smell
*/
public
abstract
String
getSmellName
();
public
abstract
boolean
getHasSmell
();
/**
* Returns whether there was a smell found or not.
* @return {@code true} if a smell has been found, {@code false} otherwise
*/
public
abstract
boolean
hasSmell
();
public
abstract
void
runAnalysis
(
CompilationUnit
testFileCompilationUnit
,
CompilationUnit
productionFileCompilationUnit
,
String
testFileName
,
String
productionFileName
)
throws
FileNotFoundException
;
/**
* Checks whether the specified smell is present in the file.
* @param testFileCompilationUnit The test file
* @param productionFileCompilationUnit The production file
* @param testFileName The name of the test file
* @param productionFileName The name of the production file
* @throws FileNotFoundException When a file is not found
*/
public
abstract
void
runAnalysis
(
final
CompilationUnit
testFileCompilationUnit
,
final
CompilationUnit
productionFileCompilationUnit
,
final
String
testFileName
,
final
String
productionFileName
)
throws
FileNotFoundException
;
/**
* Returns the list of the methods/classes found in the file.
* @return The list of methods/classes
*/
public
abstract
List
<
SmellyElement
>
getSmellyElements
();
}
src/main/java/testsmell/SmellyElement.java
View file @
a2fe4cc1
...
...
@@ -2,10 +2,26 @@ package testsmell;
import
java.util.Map
;
/**
* An abstract class that represents an element from a file that might be smelly.
*/
public
abstract
class
SmellyElement
{
/**
* Retrieves the name of the element.
* @return The name of the element
*/
public
abstract
String
getElementName
();
public
abstract
boolean
getHasSmell
();
/**
* Returns whether a smell was found in this element or not.
* @return {@code true} if a smell has been found, {@code false} otherwise
*/
public
abstract
boolean
hasSmell
();
/**
* Returns the stored data about this element.
* @return The data stored in this element
*/
public
abstract
Map
<
String
,
String
>
getData
();
}
src/main/java/testsmell/TestClass.java
View file @
a2fe4cc1
package
testsmell
;
import
javax.annotation.Nullable
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* The testclass that will be evaluated for smells.
*/
public
class
TestClass
extends
SmellyElement
{
/**
* The name of the class.
*/
private
String
className
;
/**
* Whether this class has a smell or not.
*/
private
boolean
hasSmell
;
/**
* The data about the methods and the smells they contain.
*/
private
Map
<
String
,
String
>
data
;
public
TestClass
(
String
className
)
{
/**
* Creates a new TestClass instance.
* @param className The name of the class
*/
public
TestClass
(
final
String
className
)
{
this
.
className
=
className
;
data
=
new
HashMap
<>();
}
public
void
setHasSmell
(
boolean
hasSmell
)
{
/**
* Sets the state of whether or not this class has a smell.
* @param hasSmell Whether this class has a smell or not
*/
public
void
setHasSmell
(
final
boolean
hasSmell
)
{
this
.
hasSmell
=
hasSmell
;
}
public
void
addDataItem
(
String
name
,
String
value
)
{
data
.
put
(
name
,
value
);
/**
* Adds an item to the data object.
* @param name The name of the object
* @param value The value of the object
*/
public
void
addDataItem
(
final
String
name
,
final
String
value
)
{
this
.
data
.
put
(
name
,
value
);
}
/**
* Returns the name of the class.
* @return The name of the class
*/
@Override
public
String
getElementName
()
{
return
className
;
}
/**
* Returns whether this class has a smell or not.
* @return {@code true} if a smell has been found, {@code false} otherwise
*/
@Override
public
boolean
getH
asSmell
()
{
public
boolean
h
asSmell
()
{
return
hasSmell
;
}
/**
* Returns the data that this object holds.
* @return The data of this object
*/
@Override
public
Map
<
String
,
String
>
getData
()
{
return
data
;
return
this
.
data
;
}
}
src/main/java/testsmell/TestFile.java
View file @
a2fe4cc1
...
...
@@ -5,50 +5,94 @@ import org.apache.commons.lang3.StringUtils;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* This is an object that serves as a means of combining the testfiles and the productionfiles.
*/
public
class
TestFile
{
/**
* The paths to the test and production files.
*/
private
String
testFilePath
,
productionFilePath
;
/**
* A list of smells that were found in the testfile.
*/
private
List
<
AbstractSmell
>
testSmells
;
/**
* Creates a new testfile object.
* @param testFilePath The path to the test file
* @param productionFilePath The path to the production file
*/
public
TestFile
(
final
String
testFilePath
,
final
String
productionFilePath
)
{
this
.
testFilePath
=
testFilePath
;
this
.
productionFilePath
=
productionFilePath
;
this
.
testSmells
=
new
ArrayList
<>();
}
/**
* Retrieves the filepath of the production file.
* @return The path of the production file
*/
public
String
getProductionFilePath
()
{
return
productionFilePath
;
return
this
.
productionFilePath
;
}
/**
* Retrieves the file path of the test file.
* @return The path of the test file
*/
public
String
getTestFilePath
()
{
return
testFilePath
;
return
t
his
.
t
estFilePath
;
}
/**
* Retrieves the list of smells in the test file.
* @return List of smells in the test file
*/
public
List
<
AbstractSmell
>
getTestSmells
()
{
return
testSmells
;
return
t
his
.
t
estSmells
;
}
public
boolean
getHasProductionFile
()
{
return
((
productionFilePath
!=
null
&&
!
productionFilePath
.
isEmpty
()));
/**
* Returns whether or not there is a production file.
* @return {@code true} if there is a production file, {@code false} otherwise
*/
public
boolean
hasProductionFile
()
{
return
((
this
.
productionFilePath
!=
null
&&
!
this
.
productionFilePath
.
isEmpty
()));
}
public
TestFile
(
String
testFilePath
,
String
productionFilePath
)
{
this
.
testFilePath
=
testFilePath
;
this
.
productionFilePath
=
productionFilePath
;
this
.
testSmells
=
new
ArrayList
<>();
}
public
void
addSmell
(
AbstractSmell
smell
)
{
testSmells
.
add
(
smell
);
}
public
String
getTagName
(){
return
testFilePath
.
split
(
"\\\\"
)[
4
];
/**
* Adds a smell to this file.
* @param smell The smell to add to the file
*/
public
void
addSmell
(
final
AbstractSmell
smell
)
{
this
.
testSmells
.
add
(
smell
);
}
/**
* Retrieves the name of the test file.
* @return The name of the test file
*/
public
String
getTestFileName
(){
int
lastIndex
=
testFilePath
.
lastIndexOf
(
"\\"
);
return
t
estFilePath
.
substring
(
lastIndex
+
1
,
testFilePath
.
length
());
int
lastIndex
=
t
his
.
t
estFilePath
.
lastIndexOf
(
"\\"
);
return
t
his
.
testFilePath
.
substring
(
lastIndex
+
1
,
this
.
testFilePath
.
length
());
}
/**
* Retrieves the name of the test file without the extension.
* @return The name of the test file without the extension
*/
public
String
getTestFileNameWithoutExtension
(){
int
lastIndex
=
getTestFileName
().
lastIndexOf
(
"."
);
return
getTestFileName
().
substring
(
0
,
lastIndex
);
}
/**
* Retrieves the name of the production file without the extension.
* @return The name of the production file without the extension
*/
public
String
getProductionFileNameWithoutExtension
(){
int
lastIndex
=
getProductionFileName
().
lastIndexOf
(
"."
);
if
(
lastIndex
==-
1
)
...
...
@@ -56,30 +100,45 @@ public class TestFile {
return
getProductionFileName
().
substring
(
0
,
lastIndex
);
}
/**
* Retrieves the name of the production file.
* @return The name of the production file
*/
public
String
getProductionFileName
(){
int
lastIndex
=
productionFilePath
.
lastIndexOf
(
"\\"
);
if
(
lastIndex
==-
1
)
return
""
;
return
productionFilePath
.
substring
(
lastIndex
+
1
,
productionFilePath
.
length
());
return
this
.
productionFilePath
.
substring
(
lastIndex
+
1
,
this
.
productionFilePath
.
length
());
}
/**
* Retrieves the relative path of the test file.
* @return The relative path of the test file
*/
public
String
getRelativeTestFilePath
()
{
String
[]
splitString
=
testFilePath
.
split
(
"\\\\"
);
String
[]
splitString
=
t
his
.
t
estFilePath
.
split
(
"\\\\"
);
StringBuilder
stringBuilder
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
stringBuilder
.
append
(
splitString
[
i
]
+
"\\"
);
}
return
testFilePath
.
substring
(
stringBuilder
.
toString
().
length
()).
replace
(
"\\"
,
"/"
);
return
this
.
testFilePath
.
substring
(
stringBuilder
.
toString
().
length
())
.
replace
(
"\\"
,
"/"
);
}
/**
* Retrieves the relative path of the production file.
* @return The relative path of the production file
*/
public
String
getRelativeProductionFilePath
()
{
if
(!
StringUtils
.
isEmpty
(
productionFilePath
))
{
String
[]
splitString
=
productionFilePath
.
split
(
"\\\\"
);
if
(!
StringUtils
.
isEmpty
(
this
.
productionFilePath
))
{
String
[]
splitString
=
this
.
productionFilePath
.
split
(
"\\\\"
);
StringBuilder
stringBuilder
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
stringBuilder
.
append
(
splitString
[
i
]
+
"\\"
);
}
return
productionFilePath
.
substring
(
stringBuilder
.
toString
().
length
()).
replace
(
"\\"
,
"/"
);
return
this
.
productionFilePath
.
substring
(
stringBuilder
.
toString
().
length
())
.
replace
(
"\\"
,
"/"
);
}
else
{
return
""
;
...
...
src/main/java/testsmell/TestMethod.java
View file @
a2fe4cc1
package
testsmell
;
import
javax.annotation.Nullable
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* The testmethod that will be evaluated for smells.
*/
public
class
TestMethod
extends
SmellyElement
{
/**
* The name of the method
*/
private
String
methodName
;
private
boolean
hasSmell
;
/**
* Whether this method has a smell or not.
*/
private
@Nullable
boolean
hasSmell
;
/**
* The data of the method about what smells it has.
*/
private
Map
<
String
,
String
>
data
;
/**
* Creates a new test method object.
* @param methodName The name of the method
*/
public
TestMethod
(
String
methodName
)
{
this
.
methodName
=
methodName
;
data
=
new
HashMap
<>();
this
.
data
=
new
HashMap
<>();
}
public
void
setHasSmell
(
boolean
hasSmell
)
{
/**
* Sets whether the method has a smell or not.
* @param hasSmell Whether the method has a smell or not
*/
public
void
setHasSmell
(
final
boolean
hasSmell
)
{
this
.
hasSmell
=
hasSmell
;
}
public
void
addDataItem
(
String
name
,
String
value
)
{
data
.
put
(
name
,
value
);
/**
* Adds a smell to the data object and whether it is present in the method or not.
* @param name The name of the smell
* @param value Whether the smell is present in the test or not
*/
public
void
addDataItem
(
final
String
name
,
final
String
value
)
{
this
.
data
.
put
(
name
,
value
);
}
/**
* Retrieves the name of the method.
* @return The name of the method
*/
@Override
public
String
getElementName
()
{
return
methodName
;
return
this
.
methodName
;
}
/**
* Retrieves whether this method has a smell or not.
* @return {@code true} if a smell has been found, {@code false} otherwise
*/
@Override
public
boolean
getH
asSmell
()
{
return
hasSmell
;
public
boolean
h
asSmell
()
{
return
this
.
hasSmell
;
}
/**
* Retrieves the data about the smells that this method has.
* @return The data about the smells that this method has
*/
@Override
public
Map
<
String
,
String
>
getData
()
{
return
data
;
return
this
.
data
;
}
}
src/main/java/testsmell/TestSmellDetector.java
View file @
a2fe4cc1
...
...
@@ -12,8 +12,14 @@ import java.util.ArrayList;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* Class that can analyze a test file when given a path.
*/
public
class
TestSmellDetector
{
/**
* A list of testsmells.
*/
private
List
<
AbstractSmell
>
testSmells
;
/**
...
...
@@ -23,31 +29,6 @@ public class TestSmellDetector {
initializeSmells
();
}
private
void
initializeSmells
(){
testSmells
=
new
ArrayList
<>();
testSmells
.
add
(
new
AssertionRoulette
());
testSmells
.
add
(
new
ConditionalTestLogic
());
testSmells
.
add
(
new
ConstructorInitialization
());
testSmells
.
add
(
new
DefaultTest
());
testSmells
.
add
(
new
EmptyTest
());
testSmells
.
add
(
new
ExceptionCatchingThrowing
());
testSmells
.
add
(
new
GeneralFixture
());
testSmells
.
add
(
new
MysteryGuest
());
testSmells
.
add
(
new
PrintStatement
());
testSmells
.
add
(
new
RedundantAssertion
());
testSmells
.
add
(
new
SensitiveEquality
());
testSmells
.
add
(
new
VerboseTest
());
testSmells
.
add
(
new
SleepyTest
());
testSmells
.
add
(
new
EagerTest
());
testSmells
.
add
(
new
LazyTest
());
testSmells
.
add
(
new
DuplicateAssert
());
testSmells
.
add
(
new
UnknownTest
());
testSmells
.
add
(
new
IgnoredTest
());
testSmells
.
add
(
new
ResourceOptimism
());
testSmells
.
add
(
new
MagicNumberTest
());
testSmells
.
add
(
new
DependentTest
());
}
/**
* Factory method that provides a new instance of the TestSmellDetector
*
...
...
@@ -58,18 +39,47 @@ public class TestSmellDetector {
}
/**
* Provides the names of the smells that are being checked for in the code
* Creates an instance of every smell analyzer.
*/
private
void
initializeSmells
(){
this
.
testSmells
=
new
ArrayList
<>();
this
.
testSmells
.
add
(
new
AssertionRoulette
());
this
.
testSmells
.
add
(
new
ConditionalTestLogic
());
this
.
testSmells
.
add
(
new
ConstructorInitialization
());
this
.
testSmells
.
add
(
new
DefaultTest
());
this
.
testSmells
.
add
(
new
EmptyTest
());
this
.
testSmells
.
add
(
new
ExceptionCatchingThrowing
());
this
.
testSmells
.
add
(
new
GeneralFixture
());
this
.
testSmells
.
add
(
new
MysteryGuest
());
this
.
testSmells
.
add
(
new
PrintStatement
());
this
.
testSmells
.
add
(
new
RedundantAssertion
());
this
.
testSmells
.
add
(
new
SensitiveEquality
());
this
.
testSmells
.
add
(
new
SleepyTest
());
this
.
testSmells
.
add
(
new
EagerTest
());
this
.
testSmells
.
add
(
new
LazyTest
());
this
.
testSmells
.
add
(
new
DuplicateAssert
());
this
.
testSmells
.
add
(
new
UnknownTest
());
this
.
testSmells
.
add
(
new
IgnoredTest
());
this
.
testSmells
.
add
(
new
MagicNumberTest
());
}
/**
* Provides the names of the smells that are being checked for in the code.
*
* @return list of smell names
*/
public
List
<
String
>
getTestSmellNames
()
{
return
testSmells
.
stream
().
map
(
AbstractSmell:
:
getSmellName
).
collect
(
Collectors
.
toList
());
return
t
his
.
t
estSmells
.
stream
().
map
(
AbstractSmell:
:
getSmellName
).
collect
(
Collectors
.
toList
());
}
/**
* Loads the java source code file into an AST and then analyzes it for the existence of the different types of test smells
* Loads the java source code file into an AST.
* and then analyzes it for the existence of the different types of test smells
* @param testFile The files to test
* @return A testfile with the data about the smells
* @throws IOException When a file is not found
*/
public
TestFile
detectSmells
(
TestFile
testFile
)
throws
IOException
{
public
TestFile
detectSmells
(
final
TestFile
testFile
)
throws
IOException
{
CompilationUnit
testFileCompilationUnit
=
null
,
productionFileCompilationUnit
=
null
;
FileInputStream
testFileInputStream
,
productionFileInputStream
;
...
...
@@ -82,23 +92,23 @@ public class TestSmellDetector {
if
(!
StringUtils
.
isEmpty
(
testFile
.
getProductionFilePath
())){
JavaParser
parser
=
new
JavaParser
();
productionFileInputStream
=
new
FileInputStream
(
testFile
.
getProductionFilePath
());
productionFileCompilationUnit
=
parser
.
parse
(
productionFileInputStream
).
getResult
().
get
();
productionFileCompilationUnit
=
parser
.
parse
(
productionFileInputStream
)
.
getResult
().
get
();
}
initializeSmells
();
for
(
AbstractSmell
smell
:
testSmells
)
{
for
(
final
AbstractSmell
smell
:
this
.
testSmells
)
{
try
{
smell
.
runAnalysis
(
testFileCompilationUnit
,
productionFileCompilationUnit
,
testFile
.
getTestFileNameWithoutExtension
(),
testFile
.
getProductionFileNameWithoutExtension
());
smell
.
runAnalysis
(
testFileCompilationUnit
,
productionFileCompilationUnit
,
testFile
.
getTestFileNameWithoutExtension
(),
testFile
.
getProductionFileNameWithoutExtension
());
}
catch
(
FileNotFoundException
e
)
{
testFile
.
addSmell
(
null
);
continue
;
}
testFile
.
addSmell
(
smell
);
}
return
testFile
;
}
}
src/main/java/testsmell/Util.java
View file @
a2fe4cc1
...
...
@@ -3,50 +3,69 @@ package testsmell;
import
com.github.javaparser.ast.Modifier
;
import
com.github.javaparser.ast.body.MethodDeclaration
;
/**
* Class used to validate certain method properties.
*/
public
class
Util
{
public
static
boolean
isValidTestMethod
(
MethodDeclaration
n
)
{
/**
* Checks whether the method declaration is a valid method.
* @param n The method declaration
* @return {@code true} if the method is valid, {@code false} otherwise
*/
public
static
boolean
isValidTestMethod
(
final
MethodDeclaration
n
)
{
boolean
valid
=
false
;
if
(!
n
.
getAnnotationByName
(
"Ignore"
).
isPresent
())
{
//only analyze methods that either have a @test annotation (Junit 4) or the method name starts with 'test'
if
(
n
.
getAnnotationByName
(
"Test"
).
isPresent
()
||
n
.
getNameAsString
().
toLowerCase
().
startsWith
(
"test"
))
{
//must be a public method
if
(
n
.
getAnnotationByName
(
"Test"
).
isPresent
()
||
n
.
getNameAsString
().
toLowerCase
().
startsWith
(
"test"
))
{
if
(
n
.
getModifiers
().
contains
(
Modifier
.
publicModifier
()))
{
valid
=
true
;
}
}
}
return
valid
;
}
public
static
boolean
isValidSetupMethod
(
MethodDeclaration
n
)
{
/**
* Checks whether the setup method is valid.
* @param n The method declaration
* @return {@code true} if the method is valid, {@code false} otherwise
*/
public
static
boolean
isValidSetupMethod
(
final
MethodDeclaration
n
)
{
boolean
valid
=
false
;
if
(!
n
.
getAnnotationByName
(
"Ignore"
).
isPresent
())
{
//only analyze methods that either have a @Before annotation (Junit 4) or the method name is 'setUp'
if
(
n
.
getAnnotationByName
(
"Before"
).
isPresent
()
||
n
.
getNameAsString
().
equals
(
"setUp"
))
{
//must be a public method
if
(
n
.
getModifiers
().
contains
(
Modifier
.
publicModifier
()))
{
valid
=
true
;
}
if
(
n
.
getAnnotationByName
(
"Before"
).
isPresent
()
||
n
.
getNameAsString
().
equals
(
"setUp"
)
||
n
.
getAnnotationByName
(
"BeforeEach"
).
isPresent
())
{
valid
=
true
;
}
}
return
valid
;
}
public
static
boolean
isInt
(
String
s
)
/**
* Checks whether a string is an integer.
* @param s The string
* @return {@code true} if the string is an integer, {@code false} otherwise
*/
public
static
boolean
isInt
(
final
String
s
)
{
try
{
int
i
=
Integer
.
parseInt
(
s
);
return
true
;
}
catch
(
NumberFormatException
er
)
{
return
false
;
}
try
{
int
i
=
Integer
.
parseInt
(
s
);
return
true
;
}
catch
(
NumberFormatException
er
)
{
return
false
;
}
}
public
static
boolean
isNumber
(
String
str
)
{
/**
* Checks whether a string is a double.
* @param str The string
* @return {@code true} if the string is a double, {@code false} otherwise
*/
public
static
boolean
isNumber
(
final
String
str
)
{
try
{
double
v
=
Double
.
parseDouble
(
str
);
return
true
;
...
...
src/main/java/testsmell/package-info.java
0 → 100644
View file @
a2fe4cc1
/**
* The support classes for the analyzers.
*/
@ParametersAreNonnullByDefault
package
testsmell
;
import
javax.annotation.ParametersAreNonnullByDefault
;
src/main/java/testsmell/smell/AssertionRoulette.java
View file @
a2fe4cc1
...
...
@@ -4,6 +4,8 @@ import com.github.javaparser.ast.CompilationUnit;
import
com.github.javaparser.ast.body.MethodDeclaration
;
import
com.github.javaparser.ast.expr.MethodCallExpr
;
import
com.github.javaparser.ast.visitor.VoidVisitorAdapter
;
import
javax.annotation.Nullable
;
import
testsmell.AbstractSmell
;