
fitnesse.responders.testHistory.HistoryComparer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fitnesse Show documentation
Show all versions of fitnesse Show documentation
The fully integrated standalone wiki, and acceptance testing framework.
The newest version!
package fitnesse.responders.testHistory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.SAXException;
import fitnesse.reporting.history.InvalidReportException;
import fitnesse.reporting.history.TestExecutionReport;
import fitnesse.testsystems.slim.HtmlTableScanner;
public class HistoryComparer {
// min for match is .8 content score + .2 topology bonus.
static final double MIN_MATCH_SCORE = .8;
static final double MAX_MATCH_SCORE = 1.2;
private static final String blankTable = "
";
private HtmlTableScanner firstScanner;
private HtmlTableScanner secondScanner;
String firstFileContent = "";
String secondFileContent = "";
List firstTableResults = new ArrayList<>();
List secondTableResults = new ArrayList<>();
List matchedTables = new ArrayList<>();
List resultContent = new ArrayList<>();
public String getFileContent(String filePath) throws IOException, SAXException, InvalidReportException {
return attemptGetFileContent(filePath);
}
private String attemptGetFileContent(String filePath) throws IOException, SAXException, InvalidReportException {
TestExecutionReport report = readTestExecutionReport(filePath);
if (!exactlyOneReport(report))
return null;
return report.getContentsOfReport(0);
}
private TestExecutionReport readTestExecutionReport(String filePath) throws IOException, SAXException, InvalidReportException {
return new TestExecutionReport(new File(filePath));
}
private boolean exactlyOneReport(TestExecutionReport report) {
return report.getResults().size() == 1;
}
public double findScoreByFirstTableIndex(int firstIndex) {
for (MatchedPair match : matchedTables)
if (match.first == firstIndex)
return match.matchScore;
return 0.0;
}
public String findScoreByFirstTableIndexAsStringAsPercent(int firstIndex) {
double score = findScoreByFirstTableIndex(firstIndex);
return String.format("%10.2f", (score / MAX_MATCH_SCORE) * 100);
}
public boolean allTablesMatch() {
return matchesAreNotNull()
&& thereAreEnoughMatches()
&& allMatchScoresAreHigh();
}
private boolean matchesAreNotNull() {
return matchedTables != null && firstTableResults != null;
}
private boolean thereAreEnoughMatches() {
return !matchedTables.isEmpty() && matchedTables.size() == firstTableResults.size();
}
private boolean allMatchScoresAreHigh() {
for (MatchedPair match : matchedTables) {
if (match.matchScore < (MAX_MATCH_SCORE - .01))
return false;
}
return true;
}
public boolean compare(String firstFilePath, String secondFilePath) throws IOException, SAXException, InvalidReportException {
if (firstFilePath.equals(secondFilePath))
return false;
initializeFileContents(firstFilePath, secondFilePath);
return grabAndCompareTablesFromHtml();
}
public boolean grabAndCompareTablesFromHtml() {
initializeComparerHelpers();
if (firstScanner.getTableCount() == 0 || secondScanner.getTableCount() == 0)
return false;
TableListComparer comparer = new TableListComparer(firstScanner, secondScanner);
comparer.compareAllTables();
matchedTables = comparer.tableMatches;
getTableTextFromScanners();
lineUpTheTables();
addBlanksToUnmatchingRows();
makePassFailResultsFromMatches();
return true;
}
private void initializeComparerHelpers() {
matchedTables = new ArrayList<>();
resultContent = new ArrayList<>();
firstScanner = new HtmlTableScanner(firstFileContent);
secondScanner = new HtmlTableScanner(secondFileContent);
}
public void lineUpTheTables() {
for (int currentMatch = 0; currentMatch < matchedTables.size(); currentMatch++)
lineUpMatch(currentMatch);
lineUpLastRow();
}
private void lineUpMatch(int currentMatch) {
insertBlanksUntilMatchLinesUp(new FirstResultAdjustmentStrategy(), currentMatch);
insertBlanksUntilMatchLinesUp(new SecondResultAdjustmentStrategy(), currentMatch);
}
private void insertBlanksUntilMatchLinesUp(ResultAdjustmentStrategy adjustmentStrategy, int currentMatch) {
while (adjustmentStrategy.matchIsNotLinedUp(currentMatch)) {
adjustmentStrategy.insertBlankTableBefore(currentMatch);
incrementRemaingMatchesToCompensateForInsertion(adjustmentStrategy, currentMatch);
}
}
private void incrementRemaingMatchesToCompensateForInsertion(ResultAdjustmentStrategy adjustmentStrategy, int currentMatch) {
for (int matchToAdjust = currentMatch; matchToAdjust < matchedTables.size(); matchToAdjust++) {
matchedTables.set(matchToAdjust, adjustmentStrategy.getAdjustedMatch(matchToAdjust));
}
}
private interface ResultAdjustmentStrategy {
boolean matchIsNotLinedUp(int matchIndex);
void insertBlankTableBefore(int matchIndex);
MatchedPair getAdjustedMatch(int matchIndex);
}
private class FirstResultAdjustmentStrategy implements ResultAdjustmentStrategy {
@Override
public boolean matchIsNotLinedUp(int matchIndex) {
MatchedPair matchedPair = matchedTables.get(matchIndex);
return matchedPair.first < matchedPair.second;
}
@Override
public void insertBlankTableBefore(int matchIndex) {
firstTableResults.add(matchedTables.get(matchIndex).first, blankTable);
}
@Override
public MatchedPair getAdjustedMatch(int matchIndex) {
MatchedPair matchedPair = matchedTables.get(matchIndex);
return new MatchedPair(matchedPair.first + 1, matchedPair.second, matchedPair.matchScore);
}
}
private class SecondResultAdjustmentStrategy implements ResultAdjustmentStrategy {
@Override
public boolean matchIsNotLinedUp(int matchIndex) {
MatchedPair matchedPair = matchedTables.get(matchIndex);
return matchedPair.first > matchedPair.second;
}
@Override
public void insertBlankTableBefore(int matchIndex) {
secondTableResults.add(matchedTables.get(matchIndex).second, blankTable);
}
@Override
public MatchedPair getAdjustedMatch(int matchIndex) {
MatchedPair matchedPair = matchedTables.get(matchIndex);
return new MatchedPair(matchedPair.first, matchedPair.second + 1, matchedPair.matchScore);
}
}
private void lineUpLastRow() {
while (firstTableResults.size() > secondTableResults.size())
secondTableResults.add(blankTable);
while (secondTableResults.size() > firstTableResults.size())
firstTableResults.add(blankTable);
}
public void addBlanksToUnmatchingRows() {
for (int tableIndex = 0; tableIndex < firstTableResults.size(); tableIndex++) {
if (tablesDontMatchAndArentBlank(tableIndex)) {
insetBlanksToSplitTheRow(tableIndex);
incrementMatchedPairsIfBelowTheInsertedBlank(tableIndex);
}
}
}
private boolean tablesDontMatchAndArentBlank(int tableIndex) {
return !thereIsAMatchForTableWithIndex(tableIndex) && firstAndSecondTableAreNotBlank(tableIndex);
}
private boolean thereIsAMatchForTableWithIndex(int tableIndex) {
return findScoreByFirstTableIndex(tableIndex) > 0.1;
}
private boolean firstAndSecondTableAreNotBlank(int tableIndex) {
return !(firstTableResults.get(tableIndex).equals(blankTable) || secondTableResults.get(tableIndex).equals(blankTable));
}
private void incrementMatchedPairsIfBelowTheInsertedBlank(int tableIndex) {
for (int j = 0; j < matchedTables.size(); j++) {
MatchedPair match = matchedTables.get(j);
if (match.first > tableIndex)
matchedTables.set(j, new MatchedPair(match.first + 1, match.second + 1, match.matchScore));
}
}
private void insetBlanksToSplitTheRow(int tableIndex) {
secondTableResults.add(tableIndex, blankTable);
firstTableResults.add(tableIndex + 1, blankTable);
}
private void getTableTextFromScanners() {
firstTableResults = new ArrayList<>();
secondTableResults = new ArrayList<>();
for (int i = 0; i < firstScanner.getTableCount(); i++)
firstTableResults.add(firstScanner.getTable(i).toHtml());
for (int i = 0; i < secondScanner.getTableCount(); i++)
secondTableResults.add(secondScanner.getTable(i).toHtml());
}
public void makePassFailResultsFromMatches() {
for (int i = 0; i < firstTableResults.size(); i++) {
String result = "fail";
for (MatchedPair match : matchedTables)
if (match.first == i && match.matchScore >= 1.19)
result = "pass";
resultContent.add(result);
}
}
private void initializeFileContents(String firstFilePath, String secondFilePath) throws IOException, SAXException, InvalidReportException {
String content = getFileContent(firstFilePath);
firstFileContent = content == null ? "" : content;
content = getFileContent(secondFilePath);
secondFileContent = content == null ? "" : content;
}
public List getResultContent() {
return resultContent;
}
static class MatchedPair {
int first;
int second;
double matchScore;
public MatchedPair(Integer first, Integer second, double matchScore) {
this.first = first;
this.second = second;
this.matchScore = matchScore;
}
@Override
public String toString() {
return "[first: " + first + ", second: " + second + ", matchScore: " + matchScore + "]";
}
@Override
public int hashCode() {
return this.first + this.second;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
MatchedPair match = (MatchedPair) obj;
return (this.first == match.first && this.second == match.second);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy