/** * Some useful debug information * * @param coveredBranches * @param coveredMethods * @param fitness */ private void printStatusMessages( AbstractTestSuiteChromosome<? extends ExecutableChromosome> suite, int coveredBranches, double fitness) { if (coveredBranches > maxCoveredBranches) { maxCoveredBranches = coveredBranches; logger.info( "(Branches) Best individual covers " + coveredBranches + "/" + (totalBranches * 2) + " branches"); logger.info( "Fitness: " + fitness + ", size: " + suite.size() + ", length: " + suite.totalLengthOfTestCases()); } if (fitness < bestFitness) { logger.info( "(Fitness) Best individual covers " + coveredBranches + "/" + (totalBranches * 2) + " branches"); bestFitness = fitness; logger.info( "Fitness: " + fitness + ", size: " + suite.size() + ", length: " + suite.totalLengthOfTestCases()); } }
/** * {@inheritDoc} * * <p>Execute all tests and count covered branches */ @Override public double getFitness(AbstractTestSuiteChromosome<? extends ExecutableChromosome> suite) { logger.trace("Calculating branch fitness"); double fitness = 0.0; List<ExecutionResult> results = runTestSuite(suite); Map<Integer, Double> trueDistance = new HashMap<Integer, Double>(); Map<Integer, Double> falseDistance = new HashMap<Integer, Double>(); Map<Integer, Integer> predicateCount = new HashMap<Integer, Integer>(); // Collect stats in the traces boolean hasTimeoutOrTestException = analyzeTraces(suite, results, predicateCount, trueDistance, falseDistance); // Collect branch distances of covered branches int numCoveredBranches = 0; for (Integer key : predicateCount.keySet()) { double df = 0.0; double dt = 0.0; int numExecuted = predicateCount.get(key); if (removedBranchesT.contains(key)) numExecuted++; if (removedBranchesF.contains(key)) numExecuted++; if (trueDistance.containsKey(key)) { dt = trueDistance.get(key); } if (falseDistance.containsKey(key)) { df = falseDistance.get(key); } // If the branch predicate was only executed once, then add 1 if (numExecuted == 1) { fitness += 1.0; } else { fitness += normalize(df) + normalize(dt); } if (falseDistance.containsKey(key) && (Double.compare(df, 0.0) == 0)) numCoveredBranches++; if (trueDistance.containsKey(key) && (Double.compare(dt, 0.0) == 0)) numCoveredBranches++; } // +1 for every branch that was not executed fitness += 2 * (totalBranches - predicateCount.size()); printStatusMessages(suite, numCoveredBranches, fitness); // Calculate coverage int coverage = numCoveredBranches; coverage += removedBranchesF.size(); coverage += removedBranchesT.size(); if (totalGoals > 0) suite.setCoverage(this, (double) coverage / (double) totalGoals); else suite.setCoverage(this, 1); suite.setNumOfCoveredGoals(this, coverage); suite.setNumOfNotCoveredGoals(this, totalGoals - coverage); if (hasTimeoutOrTestException) { logger.info("Test suite has timed out, setting fitness to max value " + (totalBranches * 2)); fitness = totalBranches * 2; // suite.setCoverage(0.0); } updateIndividual(this, suite, fitness); assert (coverage <= totalGoals) : "Covered " + coverage + " vs total goals " + totalGoals; assert (fitness >= 0.0); assert (fitness != 0.0 || coverage == totalGoals) : "Fitness: " + fitness + ", " + "coverage: " + coverage + "/" + totalGoals; assert (suite.getCoverage(this) <= 1.0) && (suite.getCoverage(this) >= 0.0) : "Wrong coverage value " + suite.getCoverage(this); return fitness; }
/** * Iterate over all execution results and summarize statistics * * @param results * @param predicateCount * @param callCount * @param trueDistance * @param falseDistance * @return */ private boolean analyzeTraces( AbstractTestSuiteChromosome<? extends ExecutableChromosome> suite, List<ExecutionResult> results, Map<Integer, Integer> predicateCount, Map<Integer, Double> trueDistance, Map<Integer, Double> falseDistance) { boolean hasTimeoutOrTestException = false; for (ExecutionResult result : results) { if (result.hasTimeout() || result.hasTestException()) { hasTimeoutOrTestException = true; continue; } for (Entry<Integer, Integer> entry : result.getTrace().getPredicateExecutionCount().entrySet()) { if (!branchesId.contains(entry.getKey()) || (removedBranchesT.contains(entry.getKey()) && removedBranchesF.contains(entry.getKey()))) continue; if (!predicateCount.containsKey(entry.getKey())) predicateCount.put(entry.getKey(), entry.getValue()); else { predicateCount.put(entry.getKey(), predicateCount.get(entry.getKey()) + entry.getValue()); } } for (Entry<Integer, Double> entry : result.getTrace().getTrueDistances().entrySet()) { if (!branchesId.contains(entry.getKey()) || removedBranchesT.contains(entry.getKey())) continue; if (!trueDistance.containsKey(entry.getKey())) trueDistance.put(entry.getKey(), entry.getValue()); else { trueDistance.put( entry.getKey(), Math.min(trueDistance.get(entry.getKey()), entry.getValue())); } if ((Double.compare(entry.getValue(), 0.0) == 0)) { result.test.addCoveredGoal(branchCoverageTrueMap.get(entry.getKey())); if (Properties.TEST_ARCHIVE) { TestsArchive.instance.putTest(this, branchCoverageTrueMap.get(entry.getKey()), result); toRemoveBranchesT.add(entry.getKey()); suite.isToBeUpdated(true); } } } for (Entry<Integer, Double> entry : result.getTrace().getFalseDistances().entrySet()) { if (!branchesId.contains(entry.getKey()) || removedBranchesF.contains(entry.getKey())) continue; if (!falseDistance.containsKey(entry.getKey())) falseDistance.put(entry.getKey(), entry.getValue()); else { falseDistance.put( entry.getKey(), Math.min(falseDistance.get(entry.getKey()), entry.getValue())); } if ((Double.compare(entry.getValue(), 0.0) == 0)) { result.test.addCoveredGoal(branchCoverageFalseMap.get(entry.getKey())); if (Properties.TEST_ARCHIVE) { TestsArchive.instance.putTest(this, branchCoverageFalseMap.get(entry.getKey()), result); toRemoveBranchesF.add(entry.getKey()); suite.isToBeUpdated(true); } } } } return hasTimeoutOrTestException; }