Skip to content

Commit 5b92a32

Browse files
author
Gregory Gay
committed
Added the method pair coverage criterion from the EvoSuite tutorial.
1 parent 5c472d3 commit 5b92a32

File tree

13 files changed

+568
-2
lines changed

13 files changed

+568
-2
lines changed

client/src/main/java/org/evosuite/Properties.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ public enum StoppingCondition {
591591
public static StoppingCondition STOPPING_CONDITION = StoppingCondition.MAXTIME;
592592

593593
public enum CrossoverFunction {
594-
SINGLEPOINTRELATIVE, SINGLEPOINTFIXED, SINGLEPOINT, COVERAGE
594+
SINGLEPOINTRELATIVE, SINGLEPOINTFIXED, SINGLEPOINT, COVERAGE, MIDDLE
595595
}
596596

597597
/** Constant <code>CROSSOVER_FUNCTION</code> */
@@ -1447,7 +1447,7 @@ public enum AlternativeFitnessCalculationMode {
14471447
public enum Criterion {
14481448
EXCEPTION, DEFUSE, ALLDEFS, BRANCH, CBRANCH, STRONGMUTATION, WEAKMUTATION,
14491449
MUTATION, STATEMENT, RHO, AMBIGUITY, IBRANCH, READABILITY,
1450-
ONLYBRANCH, ONLYMUTATION, METHODTRACE, METHOD, METHODNOEXCEPTION, LINE, ONLYLINE, OUTPUT, INPUT,
1450+
ONLYBRANCH, ONLYMUTATION, METHODTRACE, METHOD, METHODNOEXCEPTION, METHODPAIR, LINE, ONLYLINE, OUTPUT, INPUT,
14511451
REGRESSION, REGRESSIONTESTS, TRYCATCH
14521452
}
14531453

client/src/main/java/org/evosuite/TestSuiteGenerator.java

+3
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ private void printTestCriterion(Criterion criterion) {
884884
case METHODNOEXCEPTION:
885885
LoggingUtils.getEvoLogger().info(" - No-Exception Top-Level Method Coverage");
886886
break;
887+
case METHODPAIR:
888+
LoggingUtils.getEvoLogger().info(" - Method-Pair Coverage");
889+
break;
887890
case LINE:
888891
LoggingUtils.getEvoLogger().info(" - Line Coverage");
889892
break;

client/src/main/java/org/evosuite/coverage/CoverageCriteriaAnalyzer.java

+2
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ public static RuntimeVariable getCoverageVariable(Properties.Criterion criterion
166166
return RuntimeVariable.MethodCoverage;
167167
case METHODNOEXCEPTION:
168168
return RuntimeVariable.MethodNoExceptionCoverage;
169+
case METHODPAIR:
170+
//return RuntimeVariable.
169171
case ONLYLINE:
170172
case LINE:
171173
return RuntimeVariable.LineCoverage;

client/src/main/java/org/evosuite/coverage/FitnessFunctions.java

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
import org.evosuite.coverage.line.LineCoverageSuiteFitness;
4848
import org.evosuite.coverage.line.OnlyLineCoverageSuiteFitness;
4949
import org.evosuite.coverage.method.*;
50+
import org.evosuite.coverage.methodpair.MethodPairCoverageFactory;
51+
import org.evosuite.coverage.methodpair.MethodPairSuiteFitness;
5052
import org.evosuite.coverage.mutation.*;
5153
import org.evosuite.coverage.readability.ReadabilitySuiteFitness;
5254
import org.evosuite.coverage.rho.RhoCoverageFactory;
@@ -117,6 +119,8 @@ public static TestSuiteFitnessFunction getFitnessFunction(Criterion criterion) {
117119
return new MethodCoverageSuiteFitness();
118120
case METHODNOEXCEPTION:
119121
return new MethodNoExceptionCoverageSuiteFitness();
122+
case METHODPAIR:
123+
return new MethodPairSuiteFitness();
120124
case ONLYLINE:
121125
return new OnlyLineCoverageSuiteFitness();
122126
case LINE:
@@ -179,6 +183,8 @@ public static TestFitnessFactory<? extends TestFitnessFunction> getFitnessFactor
179183
return new MethodCoverageFactory();
180184
case METHODNOEXCEPTION:
181185
return new MethodNoExceptionCoverageFactory();
186+
case METHODPAIR:
187+
return new MethodPairCoverageFactory();
182188
case LINE:
183189
return new LineCoverageFactory();
184190
case ONLYLINE:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* Factory that assembles a list of pairs of method calls.
3+
* Part of EvoSuite tutorial.
4+
*
5+
* @author Gregory Gay
6+
* Copyright (C) 2010-2016 Gordon Fraser, Andrea Arcuri and EvoSuite
7+
* contributors
8+
*
9+
* This file is part of EvoSuite.
10+
*
11+
* EvoSuite is free software: you can redistribute it and/or modify it
12+
* under the terms of the GNU Lesser General Public License as published
13+
* by the Free Software Foundation, either version 3.0 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* EvoSuite is distributed in the hope that it will be useful, but
17+
* WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public
22+
* License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
23+
*/
24+
25+
package org.evosuite.coverage.methodpair;
26+
27+
import java.lang.reflect.Constructor;
28+
import java.lang.reflect.Method;
29+
import java.util.ArrayList;
30+
import java.util.LinkedHashSet;
31+
import java.util.List;
32+
import java.util.Set;
33+
34+
import org.evosuite.Properties;
35+
import org.evosuite.setup.TestUsageChecker;
36+
import org.evosuite.testsuite.AbstractFitnessFactory;
37+
import org.mockito.asm.Type;
38+
39+
public class MethodPairCoverageFactory extends AbstractFitnessFactory<MethodPairTestFitness> {
40+
41+
@Override
42+
public List getCoverageGoals() {
43+
List<MethodPairTestFitness> goals = new ArrayList<>();
44+
45+
String className = Properties.TARGET_CLASS;
46+
Class<?> clazz = Properties.getInitializedTargetClass();
47+
Set<String> constructors = getUsableConstructors(clazz);
48+
Set<String> methods = getUsableMethods(clazz);
49+
50+
51+
// Pair each constructor with each method and add to goals.
52+
for(String constructor:constructors){
53+
for(String method: methods){
54+
goals.add(new MethodPairTestFitness(className, constructor, method));
55+
}
56+
}
57+
58+
// Pair each method with each other method and add to goals.
59+
for(String method1: methods){
60+
for(String method2: methods){
61+
goals.add(new MethodPairTestFitness(className,method1,method2));
62+
}
63+
}
64+
65+
return goals;
66+
}
67+
68+
/**
69+
* Returns a list of constructors in the correct format (name + descriptor).
70+
* Uses reflection to get a list of constructors declared by CUT.
71+
* For each, produces name and descriptor.
72+
* @param clazz - class under test
73+
* @return set of constructors
74+
*/
75+
protected Set<String> getUsableConstructors(Class<?> clazz){
76+
Set<String> constructors = new LinkedHashSet<>();
77+
78+
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
79+
for(Constructor<?> c: allConstructors){
80+
if(TestUsageChecker.canUse(c)){
81+
String methodName = "<init>"+Type.getConstructorDescriptor(c);
82+
constructors.add(methodName);
83+
}
84+
}
85+
86+
return constructors;
87+
}
88+
89+
/**
90+
* Returns a list of methods in the correct format (name + descriptor).
91+
* Uses reflection to get a list of methods declared by CUT.
92+
* For each, produces name and descriptor.
93+
* @param clazz - class under test
94+
* @return set of constructors
95+
*/
96+
protected Set<String> getUsableMethods(Class<?> clazz){
97+
Set<String> methods = new LinkedHashSet<>();
98+
99+
Method[] allMethods = clazz.getDeclaredMethods();
100+
for(Method m: allMethods){
101+
if(TestUsageChecker.canUse(m)){
102+
String methodName = m.getName()+Type.getMethodDescriptor(m);
103+
methods.add(methodName);
104+
}
105+
}
106+
107+
return methods;
108+
}
109+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* New fitness function, based on pairs of method calls.
3+
* Part of EvoSuite tutorial.
4+
*
5+
* @author Gregory Gay
6+
* Copyright (C) 2010-2016 Gordon Fraser, Andrea Arcuri and EvoSuite
7+
* contributors
8+
*
9+
* This file is part of EvoSuite.
10+
*
11+
* EvoSuite is free software: you can redistribute it and/or modify it
12+
* under the terms of the GNU Lesser General Public License as published
13+
* by the Free Software Foundation, either version 3.0 of the License, or
14+
* (at your option) any later version.
15+
*
16+
* EvoSuite is distributed in the hope that it will be useful, but
17+
* WITHOUT ANY WARRANTY; without even the implied warranty of
18+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public
22+
* License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>.
23+
*/
24+
25+
package org.evosuite.coverage.methodpair;
26+
27+
import java.util.HashSet;
28+
import java.util.List;
29+
import java.util.Set;
30+
31+
import org.evosuite.testcase.ExecutableChromosome;
32+
import org.evosuite.testcase.execution.ExecutionResult;
33+
import org.evosuite.testsuite.AbstractTestSuiteChromosome;
34+
import org.evosuite.testsuite.TestSuiteFitnessFunction;
35+
36+
public class MethodPairSuiteFitness extends TestSuiteFitnessFunction {
37+
38+
// Track the method pairs.
39+
private final Set<MethodPairTestFitness> allMethodPairs = new HashSet<>();
40+
41+
public MethodPairSuiteFitness(){
42+
// Get method pairs from the fitness factory.
43+
allMethodPairs.addAll(new MethodPairCoverageFactory().getCoverageGoals());
44+
}
45+
46+
@Override
47+
public double getFitness(AbstractTestSuiteChromosome<? extends ExecutableChromosome> individual) {
48+
double fitness = 0.0;
49+
50+
// Run all tests and gather the execution results.
51+
List<ExecutionResult> results = runTestSuite(individual);
52+
Set<MethodPairTestFitness> coveredMethodPairs = new HashSet<>();
53+
54+
// Go through and look for covered goals.
55+
for(MethodPairTestFitness goal: allMethodPairs){
56+
for(ExecutionResult result: results){
57+
if(goal.isCovered(result)){
58+
coveredMethodPairs.add(goal);
59+
break;
60+
}
61+
}
62+
}
63+
64+
// Fitness is the total number of goals - the number of covered goals.
65+
// If all goals are covered, fitness will be 0.
66+
fitness = allMethodPairs.size() - coveredMethodPairs.size();
67+
68+
// Penalize fitness if the test suite times out.
69+
for (ExecutionResult result : results) {
70+
if (result.hasTimeout() || result.hasTestException()) {
71+
fitness = allMethodPairs.size();
72+
break;
73+
}
74+
}
75+
76+
// Update the fitness score for the suite.
77+
updateIndividual(this, individual, fitness);
78+
individual.setNumOfCoveredGoals(this, coveredMethodPairs.size());
79+
if(!allMethodPairs.isEmpty()){
80+
individual.setCoverage(this, (double) coveredMethodPairs.size() / (double) allMethodPairs.size());
81+
}else{
82+
individual.setCoverage(this, 1.0);
83+
}
84+
return fitness;
85+
}
86+
87+
}

0 commit comments

Comments
 (0)