/** * Decides the kind of local search that will be applied to the Test Suite. * * @return a <code>TestSuiteLocalSearch</code> instance to use for local * search */ public static TestSuiteLocalSearch selectTestSuiteLocalSearch() { return new TestSuiteLocalSearch(); }
@SuppressWarnings("unchecked") @Override public boolean localSearch(LocalSearchObjective<? extends Chromosome> objective) { TestSuiteLocalSearch localSearch = TestSuiteLocalSearch.selectTestSuiteLocalSearch(); return localSearch.doSearch(this, (LocalSearchObjective<TestSuiteChromosome>) objective); }
TestBranchPair(TestChromosome test, List<BranchCondition> pathCondition, BranchCondition branchCondition) { this.test = test; this.branch = branchCondition; this.pathCondition = pathCondition; this.ranking = computeRanking(pathCondition, branchCondition); }
/** * Applies DSE on the test case of the suite * * @param suite * @param testIndex * @param test * @param objective * @return */ private boolean applyDSE(TestSuiteChromosome suite, int testIndex, TestChromosome test, LocalSearchObjective<TestSuiteChromosome> objective) { TestSuiteLocalSearchObjective testSuiteObject = TestSuiteLocalSearchObjective .buildNewTestSuiteLocalSearchObjective(objective.getFitnessFunctions(), suite, testIndex); DSETestCaseLocalSearch dseTestCaseLocalSearch = new DSETestCaseLocalSearch(suite); boolean improved = dseTestCaseLocalSearch.doSearch(test, testSuiteObject); return improved; }
private boolean reachesUncoveredBranch(TestChromosome test, Set<Branch> uncoveredBranches) { Set<Branch> testCoveredBranches = getCoveredBranches(test); for (Branch b : testCoveredBranches) { Branch negate = b.negate(); if (uncoveredBranches.contains(negate)) { return true; } } return false; }
private void calculateUncoveredBranches(TestChromosome newTestChromosome) { if (Properties.DSE_NEGATE_ALL_CONDITIONS == true) { final List<BranchCondition> pathCondition = pathConditions.get(newTestChromosome); for (BranchCondition targetBranchCondition : pathCondition) { if (!unsolvableBranchConditions.contains(targetBranchCondition)) { unsolvedBranchConditions .add(new TestBranchPair(newTestChromosome, pathCondition, targetBranchCondition)); } } } else { calculateUncoveredBranches(); } }
/** * Create path constraints for all tests in a test suite * * @param testSuite */ private void createPathConstraints(TestSuiteChromosome testSuite) { for (TestChromosome test : testSuite.getTestChromosomes()) { updatePathConstraints(test); } calculateUncoveredBranches(); }
/** * Creates a Local Search objective for a TestCase that will be optimized * using a containing TestSuite to measure the changes in fitness values. * * @param fitness * the list of fitness functions to use to compute the fitness of * the TestSuiteChromosome * @param suite * a TestSuite chromosome that will be subjected to local search * @param index * a test index (between 0 and the test suite length) that will * be used to modify the testchromosome each time a changed has * been applied. */ private TestSuiteLocalSearchObjective(List<TestSuiteFitnessFunction> fitness, TestSuiteChromosome suite, int index) { this.fitnessFunctions.addAll(fitness); this.suite = suite; this.testIndex = index; for (TestSuiteFitnessFunction ff : fitness) { if (ff.isMaximizationFunction()) isMaximization = true; else isMaximization = false; break; } updateLastFitness(); updateLastCoverage(); }
/** * Get a new candidate for negation * * @return */ private TestBranchPair getNextBranchCondition() { TestBranchPair pair; pair = getNextTestBranchPair(); if (Properties.DSE_NEGATE_ALL_CONDITIONS == true) { return pair; } String index = getBranchIndex(pair.branch); if (!unsolvedBranchConditions.isEmpty()) { while (solutionAttempts.containsKey(index) && solutionAttempts.get(index) >= Properties.CONSTRAINT_SOLUTION_ATTEMPTS && !unsolvedBranchConditions.isEmpty()) { logger.info("Reached maximum number of attempts for branch " + index); pair = getNextTestBranchPair(); index = getBranchIndex(pair.branch); } } if (!solutionAttempts.containsKey(index)) solutionAttempts.put(index, 1); else solutionAttempts.put(index, solutionAttempts.get(index) + 1); return pair; }
/** * Ensure that all branches are executed twice */ private void restoreBranchCoverage(TestSuiteChromosome individual, TestSuiteFitnessFunction objective) { logger.debug("Adding branches already covered previously"); BranchCoverageMap branchMap = BranchCoverageMap.getInstance(); Set<Integer> uncoveredTrueBranches = new LinkedHashSet<Integer>(branchMap.getCoveredTrueBranches()); Set<Integer> uncoveredFalseBranches = new LinkedHashSet<Integer>(branchMap.getCoveredFalseBranches()); uncoveredTrueBranches.removeAll(getCoveredTrueBranches(individual)); uncoveredFalseBranches.removeAll(getCoveredFalseBranches(individual)); for (Integer branchId : uncoveredTrueBranches) { individual.addTest(branchMap.getTestCoveringTrue(branchId).clone()); } for (Integer branchId : uncoveredFalseBranches) { individual.addTest(branchMap.getTestCoveringFalse(branchId).clone()); } }
/** * Replaces the test case at position <code>testIndex</code> with the passed * TestChromosome. */ @Override public boolean hasImproved(TestChromosome testCase) { return hasChanged(testCase) < 0; }
public Branch negate() { return new Branch(branchIndex, !isTrueBranch); }
/** * Determine the set of variable referenced by this constraint * * @param constraint * @return */ private Set<Variable<?>> getVariables(Constraint<?> constraint) { Set<Variable<?>> variables = new HashSet<Variable<?>>(); getVariables(constraint.getLeftOperand(), variables); getVariables(constraint.getRightOperand(), variables); return variables; }
/** * Returns the set of all branches that are not covered both-wise * * @param coveredBranches * @return */ private static Set<Branch> getUncoveredBranches(Set<Branch> coveredBranches) { Set<Branch> uncoveredBranches = new HashSet<Branch>(); for (Branch b : coveredBranches) { final Branch negate = b.negate(); if (!coveredBranches.contains(negate)) { uncoveredBranches.add(negate); } } return uncoveredBranches; }
/** * Creates a new <code>TestSuiteLocalSearchObjective</code> for a given list * of fitness functions, a test suite and a <code>testIndex</code> for * replacing an optimised test case (i.e. a test case over which was applied * local search) * * @param fitness * the list of fitness functions to be used on the modified test * suite * @param suite * the original test suite * @param index * the index (between 0 and the suite length) that will be * replaced with a new test case * @return */ public static TestSuiteLocalSearchObjective buildNewTestSuiteLocalSearchObjective( List<FitnessFunction<? extends Chromosome>> fitness, TestSuiteChromosome suite, int index) { List<TestSuiteFitnessFunction> ffs = new ArrayList<>(); for (FitnessFunction<? extends Chromosome> ff : fitness) { TestSuiteFitnessFunction tff = (TestSuiteFitnessFunction) ff; ffs.add(tff); } return new TestSuiteLocalSearchObjective(ffs, suite, index); }
/** * Returns the set covered branches by this suite * * @param suite * @return */ private static Set<Branch> getCoveredBranches(TestSuiteChromosome suite) { final Set<Branch> suiteCoveredBranches = new HashSet<Branch>(); for (TestChromosome test : suite.getTestChromosomes()) { final Set<Branch> testCoveredBranches = getCoveredBranches(test); suiteCoveredBranches.addAll(testCoveredBranches); } return suiteCoveredBranches; }
/** * Applies AVM on the test case in the suite * * @param suite * @param testIndex * @param test * @param localSearchObjective * @return */ private boolean applyAVM(TestSuiteChromosome suite, int testIndex, TestChromosome test, LocalSearchObjective<TestSuiteChromosome> objective) { logger.debug("Local search on test " + testIndex + ", current fitness: " + suite.getFitness()); final List<FitnessFunction<? extends Chromosome>> fitnessFunctions = objective.getFitnessFunctions(); TestSuiteLocalSearchObjective testCaseLocalSearchObjective = TestSuiteLocalSearchObjective .buildNewTestSuiteLocalSearchObjective(fitnessFunctions, suite, testIndex); AVMTestCaseLocalSearch testCaselocalSearch = new AVMTestCaseLocalSearch(); boolean improved = testCaselocalSearch.doSearch(test, testCaseLocalSearchObjective); return improved; }
/** * Returns true if by replacing the test case at position * <code>testIndex</code> with the argument <code>testCase</code>, the * resulting test suite has not worsened the fitness */ @Override public boolean hasNotWorsened(TestChromosome testCase) { return hasChanged(testCase) < 1; }
/** * Returns the set of covered branches by this test * * @param test * @return */ private static Set<Branch> getCoveredBranches(TestChromosome test) { final Set<Branch> testCoveredBranches = new HashSet<Branch>(); ExecutionTrace trace = test.getLastExecutionResult().getTrace(); { Set<Integer> coveredTrueBranchIndexesInTrace = trace.getCoveredTrueBranches(); for (Integer branchIndex : coveredTrueBranchIndexesInTrace) { Branch b = new Branch(branchIndex, true); testCoveredBranches.add(b); } } { Set<Integer> coveredFalseBranchIndexesInTrace = trace.getCoveredFalseBranches(); for (Integer branchIndex : coveredFalseBranchIndexesInTrace) { Branch b = new Branch(branchIndex, false); testCoveredBranches.add(b); } } return testCoveredBranches; }
/** * Apply cone of influence reduction to constraints with respect to the last * constraint in the list * * @param constraints * @return */ private List<Constraint<?>> reduce(List<Constraint<?>> constraints) { Constraint<?> target = constraints.get(constraints.size() - 1); Set<Variable<?>> dependencies = getVariables(target); LinkedList<Constraint<?>> coi = new LinkedList<Constraint<?>>(); if (dependencies.size() <= 0) return coi; coi.add(target); for (int i = constraints.size() - 2; i >= 0; i--) { Constraint<?> constraint = constraints.get(i); Set<Variable<?>> variables = getVariables(constraint); for (Variable<?> var : dependencies) { if (variables.contains(var)) { dependencies.addAll(variables); coi.addFirst(constraint); break; } } } return coi; }