Skip to content

Commit

Permalink
Merge pull request #33 from ObjectivityLtd/KeyComparator
Browse files Browse the repository at this point in the history
Key comparator
  • Loading branch information
raczeja authored Feb 12, 2021
2 parents 11189cb + 1d9eba5 commit 761d3c0
Show file tree
Hide file tree
Showing 69 changed files with 2,525 additions and 123 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ If you set JAVA_HOME variable:
```
java -jar DBTestCompare-1.0-SNAPSHOT-jar-with-dependencies.jar
```

or to add automatically all drivers from the directory to the classspath (jdbc_drivers/*)
Windows
```
java -cp "DBTestCompare-1.0-SNAPSHOT-jar-with-dependencies.jar;jdbc_drivers/*" uk.co.objectivity.test.db.RunTests
```
Linux
```
java -cp "DBTestCompare-1.0-SNAPSHOT-jar-with-dependencies.jar:jdbc_drivers/*" uk.co.objectivity.test.db.RunTests
```
or e.g.
```
"C:\Program Files\Java\jdk1.8.0_92\bin\java" -jar DBTestCompare-1.0-SNAPSHOT-jar-with-dependencies.jar
Expand All @@ -30,6 +38,7 @@ Application provides following features:
- Supports **all Continuous Integration tools** thanks to TestNG Java unit test framework
- Possibility to compare data between **two different database engines** even for huge data sets
without "Out of memory problem" thanks to incremental solution, more details [here](https://github.com/ObjectivityLtd/DBTestCompare/wiki/Fetch)
- Possibility to compare query to **expected data defined in csv file** and generate **Excel test raport**, more details [here](https://github.com/ObjectivityLtd/DBTestCompare/wiki/KEY)
- Possibility to compare data in **one database engine in the fastest way** using MINUS/EXCEPT Sql operator, more details [here](https://github.com/ObjectivityLtd/DBTestCompare/wiki/Minus)
- **No need to compile program** in order to add new tests - thanks to Test Adapter DataDriven mechanism from TestNG
- Possibility to **execute test in parallel** by setting Threads parameter in connection file.
Expand Down
6 changes: 6 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ steps:
targetPath: './target/test-output'
artifact: 'DBTestCompare$(dBTestCompareVersion).TestResults.$(Build.BuildNumber)'
publishLocation: 'pipeline'

- task: PublishPipelineArtifact@1
inputs:
targetPath: './target/test-definitions'
artifact: 'DBTestCompare$(dBTestCompareVersion).TestDefinitionsResults.$(Build.BuildNumber)'
publishLocation: 'pipeline'

- task: PublishPipelineArtifact@1
inputs:
Expand Down
Binary file removed jdbc_drivers/mysql-connector-java-8.0.19.jar
Binary file not shown.
Binary file added jdbc_drivers/mysql-connector-java-8.0.23.jar
Binary file not shown.
25 changes: 20 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>uk.co.objectivity.test.db</groupId>
Expand All @@ -14,6 +14,9 @@
<log4j.version>2.13.1</log4j.version>
<log4jcore.version>2.13.2</log4jcore.version>
<c3p0.version>0.9.5.5</c3p0.version>
<poi.version>4.1.1</poi.version>
<commons.version>3.9</commons.version>
<sirocco.version>1.0</sirocco.version>
</properties>

<build>
Expand All @@ -36,7 +39,7 @@
<manifestEntries>
<!-- TODO all drivers from directory -->
<Class-Path>jdbc_drivers/mssql-jdbc-8.2.0.jre8.jar jdbc_drivers/mssql-jdbc-8.2.0.jre11.jar jdbc_drivers/mssql-jdbc-8.2.0.jre13.jar jdbc_drivers/tdgssconfig-4.jar
jdbc_drivers/terajdbc-4.jar jdbc_drivers/mysql-connector-java-8.0.19.jar
jdbc_drivers/terajdbc-4.jar jdbc_drivers/mysql-connector-java-8.0.23.jar
jdbc_drivers/postgresql-42.2.11.jar jdbc_drivers/mariadb-java-client-2.6.0.jar jdbc_drivers/snowflake-jdbc-3.9.2.jar</Class-Path>
</manifestEntries>
</archive>
Expand Down Expand Up @@ -72,7 +75,7 @@
<dependency>
<groupId>org.ow2.sirocco</groupId>
<artifactId>sirocco-text-table-formatter</artifactId>
<version>1.0</version>
<version>${sirocco.version}</version>
</dependency>

<!-- used to create JDBC Connection Pool -->
Expand All @@ -91,7 +94,19 @@
<artifactId>log4j-core</artifactId>
<version>${log4jcore.version}</version>
</dependency>
</dependencies>

<!-- used to generate Excel file -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.version}</version>
</dependency>
</dependencies>
</project>

95 changes: 51 additions & 44 deletions src/main/java/uk/co/objectivity/test/db/DBTestCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import uk.co.objectivity.test.db.beans.TestParams;
import uk.co.objectivity.test.db.beans.TestResults;
import uk.co.objectivity.test.db.beans.xml.Compare;
import uk.co.objectivity.test.db.beans.xml.Condition;
import uk.co.objectivity.test.db.utils.Printer;
import uk.co.objectivity.test.db.utils.SavedTimes;
import uk.co.objectivity.test.db.utils.TCMessages;
Expand Down Expand Up @@ -82,50 +83,56 @@ public void testSQLResults() {
}
compare = testParams.getCmpSqlResultsTest().getCompare();
testResults = compare.getCompareMode().getComparator().compare(testParams);
if(!testResults.getOutput().isEmpty())
logInfo2All(testResults.getOutput() + "\r\n", tcMsgs);
logInfo2All("Executed query: \r\n" + testResults.getExecutedQuery(), tcMsgs);

// assertions
if (compare.getCompareMode() == CompareMode.NMB_OF_RESULTS) {
List<uk.co.objectivity.test.db.beans.xml.Assert> assertList = compare.getAssertions();
List<Condition> assertList = compare.getAssertions();
if (assertList != null) {
logInfo2All("Rows count:" + testResults.getNmbOfRows(),tcMsgs);
logInfo2All("Rows count:" + testResults.getNmbOfRows(), tcMsgs);
TestResults effFinalTR = testResults;
assertList.forEach(a -> logInfo2All(a.getAssertType().name() + " " + a.getValue(), tcMsgs));
assertList.forEach(a -> a.getAssertType().assertByType(effFinalTR.getNmbOfRows(), a.getValue()));
assertList.forEach(a -> logInfo2All(a.getConditionType().name() + " " + a.getValue(), tcMsgs));
assertList.forEach(a -> a.getConditionType().assertByType(effFinalTR.getNmbOfRows(), a.getValue()));
int p = getIndexByName(testParams.getTestName());
if(p >= 0){
if (p >= 0) {
savedTimesList.get(p).setTestResult("Passed");
}

}
} else if(compare.getCompareMode() == CompareMode.FETCH || compare.getCompareMode() == CompareMode.FILE) {
Assert.assertEquals(testResults.getNmbOfRows(), Integer.valueOf(0),
"Among " + testResults.getNmbOfComparedRows() +
" compared rows, some differences in SQL queries results found - ");
} else if (compare.getCompareMode() == CompareMode.FETCH || compare.getCompareMode() == CompareMode.FILE
|| compare.getCompareMode() == CompareMode.KEY) {
Assert.assertEquals(testResults.getNmbOfRows(), Integer.valueOf(0),
"Among " + testResults.getNmbOfComparedRows()
+ " compared rows, some differences in SQL queries results found - ");
} else {
Assert.assertEquals(testResults.getNmbOfRows(), Integer.valueOf(0),
"Differences in SQL queries found - ");
}
Assert.assertEquals(testResults.getNmbOfRows(), Integer.valueOf(0),
"Differences in SQL queries found - ");
}

if(compare.getCompareMode() == CompareMode.FETCH || compare.getCompareMode() == CompareMode.FILE){
logInfo2All("TEST PASSED, Compared rows:" + testResults.getNmbOfComparedRows(),tcMsgs);
if (compare.getCompareMode() == CompareMode.FETCH || compare.getCompareMode() == CompareMode.FILE
|| compare.getCompareMode() == CompareMode.KEY) {
logInfo2All("TEST PASSED, Compared rows:" + testResults.getNmbOfComparedRows(), tcMsgs);
} else {
logInfo2All("TEST PASSED", tcMsgs);
}

} catch (AssertionError ae) {
String resultsTextTable = null;
if (compare != null && testResults != null && compare.getCompareMode() != CompareMode.NMB_OF_RESULTS &&
compare.getDiffTableSize() > 0) {
if (compare != null && testResults != null && compare.getCompareMode() != CompareMode.NMB_OF_RESULTS
&& compare.getDiffTableSize() > 0) {
resultsTextTable = Printer.getTextTable(testResults);
log.info(resultsTextTable);
}
logFailed2All(ae, tcMsgs, resultsTextTable);
throw ae;
} catch (Exception e) {
logFailed2All(e, tcMsgs, null);
// it would be better to skip tests which configuration is wrong, and fail only those which really fails
// (AssertionError) but fail is more "visible". Maybe user should choose (configuration) if skip or fail
// it would be better to skip tests which configuration is wrong, and fail only
// those which really fails
// (AssertionError) but fail is more "visible". Maybe user should choose
// (configuration) if skip or fail
// on misconfiguration or i.e. DB problems
// throw new SkipException(e.getMessage());
throw new TestException(e);
Expand All @@ -136,11 +143,9 @@ public void testSQLResults() {

}

public int getIndexByName(String testName)
{
for(SavedTimes _item : savedTimesList)
{
if(_item.getTestName().equals(testName))
public int getIndexByName(String testName) {
for (SavedTimes _item : savedTimesList) {
if (_item.getTestName().equals(testName))
return savedTimesList.indexOf(_item);
}
return -1;
Expand All @@ -159,8 +164,9 @@ private void logFailed2All(Throwable throwable, TCMessages tcMsgs, String additi
}

/**
* For TestNG HTML reports purposes. Without this method it does not display test name provided by getTestName()
* ITest interface). For i.e. Intellij IDEA uses name provided by getTestName() .
* For TestNG HTML reports purposes. Without this method it does not display
* test name provided by getTestName() ITest interface). For i.e. Intellij IDEA
* uses name provided by getTestName() .
*
* @param result - test results
*/
Expand All @@ -178,51 +184,52 @@ public void setResultTestName(ITestResult result) {
log.error(ex);
}
}
@AfterSuite
public void displaySavedTimesStatistics(){

@AfterSuite(enabled = false)
public void displaySavedTimesStatistics() {
savedTimesList.sort(Comparator.comparing(SavedTimes::getDuration).reversed());
Map<String, List<SavedTimes>> savedTimesListGrouped =
savedTimesList.stream().collect(Collectors.groupingBy(w -> w.getTestName()));
Map<String, List<SavedTimes>> savedTimesListGrouped = savedTimesList.stream()
.collect(Collectors.groupingBy(w -> w.getTestName()));

CellStyle cs = new CellStyle(CellStyle.HorizontalAlign.left, CellStyle.AbbreviationStyle.crop,
CellStyle.NullStyle.emptyString);
Table t = new Table(5, BorderStyle.DESIGN_TUBES, ShownBorders
.SURROUND_HEADER_AND_COLUMNS, false, "");
Table t = new Table(5, BorderStyle.DESIGN_TUBES, ShownBorders.SURROUND_HEADER_AND_COLUMNS, false, "");
t.addCell("Test Name", cs);
t.addCell("Measure Type", cs);
t.addCell("Duration min:s:ms", cs);
t.addCell("Compared rows", cs);
t.addCell("Status", cs);
int i=0;
savedTimesListGrouped.forEach((String key, List<SavedTimes> value) -> {
value.forEach((SavedTimes v) -> {
t.addCell(v.getTestName().trim(), cs)
;
t.addCell(v.getTestName().trim(), cs);
t.addCell(v.getMeasureType().trim(), cs);
t.addCell(v.getFormattedDuration().replace("min:s:ms", "").trim(), cs)
;
t.addCell(v.getFormattedDuration().replace("min:s:ms", "").trim(), cs);
t.addCell(v.getNumberOfComparedRows(), cs);
t.addCell(v.getTestResult().trim(), cs);
});
});
String stringTable = "Statistics of queries execution group by test name(" + savedTimesListGrouped.size() + " rows):\r\n" + t.render();
String stringTable = "Statistics of queries execution group by test name(" + savedTimesListGrouped.size()
+ " rows):\r\n" + t.render();
Printer.addReporterLog(stringTable);

log.log(Level.OFF, "##teamcity[message '"+stringTable+"']");
log.log(Level.OFF, "##teamcity[message '" + stringTable + "']");
log.info(stringTable);

Table ts = new Table(3, BorderStyle.DESIGN_TUBES, ShownBorders
.SURROUND_HEADER_AND_COLUMNS, false, "");
Table ts = new Table(3, BorderStyle.DESIGN_TUBES, ShownBorders.SURROUND_HEADER_AND_COLUMNS, false, "");
ts.addCell("Test Name", cs);
ts.addCell("Measure Type", cs);
ts.addCell("Duration min:s:ms", cs);
savedTimesList.forEach(s -> {ts.addCell(s.getTestName().trim(), cs)
;ts.addCell(s.getMeasureType().trim(), cs);ts.addCell(s.getFormattedDuration().replace("min:s:ms","").trim(), cs);});
savedTimesList.forEach(s -> {
ts.addCell(s.getTestName().trim(), cs);
ts.addCell(s.getMeasureType().trim(), cs);
ts.addCell(s.getFormattedDuration().replace("min:s:ms", "").trim(), cs);
});

stringTable = "Statistics of queries execution sorted by time execution (" + savedTimesList.size() + " rows):\r\n" + ts.render();
stringTable = "Statistics of queries execution sorted by time execution (" + savedTimesList.size()
+ " rows):\r\n" + ts.render();
Printer.addReporterLog(stringTable);

log.log(Level.OFF, "##teamcity[message '"+stringTable+"']");
log.log(Level.OFF, "##teamcity[message '" + stringTable + "']");
log.info(stringTable);

}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/uk/co/objectivity/test/db/RunTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public static void main(String[] args) {
}

static CmpSqlResultsConfig readConfigAndInit() {
log.debug("Scanning tests directory: " + TEST_DIR + "...");
log.debug("Working Directory = " + System.getProperty("user.dir"));
log.debug("Scanning tests directory: \"" + TEST_DIR + "\" ...");
File testsDirFile = new File(TEST_DIR);
if (!testsDirFile.exists()) {
log.error("Tests directory does not exists! Please create directory: " + testsDirFile.getAbsolutePath());
Expand Down
Loading

0 comments on commit 761d3c0

Please sign in to comment.