Skip to content

Commit

Permalink
ver 1.18.1; merged the develop branch into the master branch
Browse files Browse the repository at this point in the history
  • Loading branch information
kazurayam committed Jun 22, 2020
2 parents 8205d28 + c591623 commit a061baf
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 104 deletions.
174 changes: 130 additions & 44 deletions Keywords/com/kazurayam/visualtesting/ImageCollectionDifferDriver.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.kazurayam.materials.MaterialPair
import com.kazurayam.materials.MaterialPairs
import com.kazurayam.materials.MaterialRepository
import com.kazurayam.materials.MaterialStorage
import com.kazurayam.materials.TExecutionProfile
import com.kazurayam.materials.TCaseName
import com.kazurayam.materials.TSuiteName
import com.kazurayam.materials.TSuiteResultId
Expand All @@ -29,6 +30,7 @@ public class ImageCollectionDifferDriver {

private MaterialRepository mr_
private TSuiteName capturingTSuiteName_
private TExecutionProfile capturingTExecutionProfile_
private VisualTestingLogger logger_
private Path imageDeltaStatsJson_
private Path comparisonResultBundleFile_
Expand All @@ -37,10 +39,11 @@ public class ImageCollectionDifferDriver {
Objects.requireNonNull(mr, "mr must not be null")
this.mr_ = mr
// call MaterialRepository#markAsCurrent() to specify where to save the image diff files
String tSuiteResultId = GlobalVariable[MGV.CURRENT_TESTSUITE_ID.getName()]
String tSuiteTimestamp = GlobalVariable[MGV.CURRENT_TESTSUITE_TIMESTAMP.getName()]
mr_.markAsCurrent(tSuiteResultId, tSuiteTimestamp)
def tsr = mr_.ensureTSuiteResultPresent(tSuiteResultId, tSuiteTimestamp)
String tSuiteResultId = GlobalVariable[MGV.CURRENT_TESTSUITE_ID.getName()]
String executionProfile = GlobalVariable[MGV.CURRENT_EXECUTION_PROFILE.getName()]
String tSuiteTimestamp = GlobalVariable[MGV.CURRENT_TESTSUITE_TIMESTAMP.getName()]
mr_.markAsCurrent(tSuiteResultId, executionProfile, tSuiteTimestamp)
def tsr = mr_.ensureTSuiteResultPresent(tSuiteResultId, executionProfile, tSuiteTimestamp)
}

void setVisualTestingLogger(VisualTestingLogger logger) {
Expand All @@ -53,35 +56,52 @@ public class ImageCollectionDifferDriver {
* @param ms
* @param options
*/
public boolean chronos(TSuiteName capturingTSuiteName, MaterialStorage ms, ChronosOptions options) {
public boolean chronos(TSuiteName capturingTSuiteName,
TExecutionProfile capturingTExecutionProfile,
MaterialStorage ms,
ChronosOptions options) {
Objects.requireNonNull(capturingTSuiteName, "capturingTSuiteName must not be null")
Objects.requireNonNull(capturingTExecutionProfile, "capturingTExecutionProfile must not be null")
Objects.requireNonNull(ms, "ms must not be null")
Objects.requireNonNull(options, "options must not be null")

// scan the 'Storage' directory to get the statistics of previous runs
ImageDeltaStats stats = this.createImageDeltaStats(ms, capturingTSuiteName, options)

// copy image-delta-stats.json file from Storage dir to the Materials dir to bring it visible in the Materials/index.html
Path toPath1 = mr_.resolveMaterialPath(GlobalVariable[ManagedGlobalVariable.CURRENT_TESTCASE_ID.getName()], ImageDeltaStats.IMAGE_DELTA_STATS_FILE_NAME)
ImageDeltaStats stats = this.createImageDeltaStats(ms,
capturingTSuiteName,
capturingTExecutionProfile,
options)

// copy image-delta-stats.json file from Storage dir to the Materials dir
// to bring it visible in the Materials/index.html
Path toPath1 = mr_.resolveMaterialPath(
GlobalVariable[MGV.CURRENT_TESTCASE_ID.getName()],
ImageDeltaStats.IMAGE_DELTA_STATS_FILE_NAME)
if (this.imageDeltaStatsJson_ != null) {
Files.copy(this.imageDeltaStatsJson_, toPath1, StandardCopyOption.REPLACE_EXISTING)
}

// make image diffs, write the result into the directory named
// 'Materials/<current TSuiteName>/<current Timestamp>/<cuurent TCaseName>'
// 'Materials/<current TSuiteName>/<current ExecutionProfile>/<current Timestamp>/<current TCaseName>'
ImageCollectionDiffer imageCollectionDiffer = new ImageCollectionDiffer(this.mr_)
if (logger_ != null) {
imageCollectionDiffer.setVisualTestingLogger(logger_)
}
MaterialPairs materialPairs = this.createMaterialPairs(this.mr_, capturingTSuiteName)
boolean result = imageCollectionDiffer.makeImageCollectionDifferences(
MaterialPairs materialPairs =
this.createMaterialPairsForChronosMode(this.mr_,
capturingTSuiteName,
capturingTExecutionProfile)
boolean result =
imageCollectionDiffer.makeImageCollectionDifferences(
materialPairs,
new TCaseName( GlobalVariable[ManagedGlobalVariable.CURRENT_TESTCASE_ID.getName()] ),
new TCaseName( GlobalVariable[MGV.CURRENT_TESTCASE_ID.getName()] ),
stats)
WebUI.comment("${ComparisonResultBundle.SERIALIZED_FILE_NAME} files will be saved into ${imageCollectionDiffer.getOutput()}")

// save the comparison-result-bundle.json file into the Materials dir to bring it visible in the Materials/index.html
comparisonResultBundleFile_ = mr_.resolveMaterialPath(GlobalVariable[ManagedGlobalVariable.CURRENT_TESTCASE_ID.getName()],ComparisonResultBundle.SERIALIZED_FILE_NAME)
// save the comparison-result-bundle.json file into the Materials dir
// to bring it visible in the Materials/index.html
comparisonResultBundleFile_ =
mr_.resolveMaterialPath(GlobalVariable[MGV.CURRENT_TESTCASE_ID.getName()],
ComparisonResultBundle.SERIALIZED_FILE_NAME)
Files.copy(imageCollectionDiffer.getOutput(), comparisonResultBundleFile_)
WebUI.comment("copied into ${comparisonResultBundleFile_}")

Expand All @@ -98,52 +118,80 @@ public class ImageCollectionDifferDriver {
* @param mr
* @param criteriaPercentage
*/
public boolean twins(TSuiteName capturingTSuiteName, double criteriaPercentage) {
public boolean twins(TSuiteName capturingTSuiteName,
TExecutionProfile capturingTExecutionProfile,
double criteriaPercentage)
{
Objects.requireNonNull(capturingTSuiteName, "capturingTSuiteName must not be null")
Objects.requireNonNull(capturingTExecutionProfile, "capturingTExecutionProfile must not be null")

WebUI.comment(">>> diff image files will be saved into ${mr_.getCurrentTestSuiteDirectory().toString()}")

ImageCollectionDiffer imageCollectionDiffer = new ImageCollectionDiffer(this.mr_)
if (logger_ != null) {
imageCollectionDiffer.setVisualTestingLogger(logger_)
}
MaterialPairs materialPairs = this.createMaterialPairs(this.mr_, capturingTSuiteName)
boolean result = imageCollectionDiffer.makeImageCollectionDifferences(

MaterialPairs materialPairs =
this.createMaterialPairsForTwinsMode(this.mr_, capturingTSuiteName)

boolean result =
imageCollectionDiffer.makeImageCollectionDifferences(
materialPairs,
new TCaseName( GlobalVariable[ManagedGlobalVariable.CURRENT_TESTCASE_ID.getName()] ),
criteriaPercentage)
new TCaseName( GlobalVariable[MGV.CURRENT_TESTCASE_ID.getName()] ),
criteriaPercentage
)

return result
}

/**
*
* @return
*/
private ImageDeltaStats createImageDeltaStats(MaterialStorage ms,
TSuiteName capturingTSuiteName,
ChronosOptions options ) {
TSuiteName tSuiteNameExam = new TSuiteName( GlobalVariable[ManagedGlobalVariable.CURRENT_TESTSUITE_ID.getName()] )
TSuiteTimestamp tSuiteTimestampExam = new TSuiteTimestamp( GlobalVariable[ManagedGlobalVariable.CURRENT_TESTSUITE_TIMESTAMP.getName()] )
TCaseName tCaseNameExam = new TCaseName( GlobalVariable[ManagedGlobalVariable.CURRENT_TESTCASE_ID.getName()] )

Path previousIDS = StorageScanner.findLatestImageDeltaStats(ms, tSuiteNameExam, tCaseNameExam)
private ImageDeltaStats createImageDeltaStats(MaterialStorage ms,
TSuiteName capturingTSuiteName,
TExecutionProfile capturingTExecutionProfile,
ChronosOptions options )
{
TSuiteName examiningTSuiteName = new TSuiteName( GlobalVariable[MGV.CURRENT_TESTSUITE_ID.getName()] )
TExecutionProfile examiningTExecutionProfile = new TExecutionProfile(GlobalVariable[MGV.CURRENT_EXECUTION_PROFILE.getName()] )
TSuiteTimestamp examiningTSuiteTimestamp = new TSuiteTimestamp( GlobalVariable[MGV.CURRENT_TESTSUITE_TIMESTAMP.getName()] )
TCaseName examiningTCaseName = new TCaseName( GlobalVariable[MGV.CURRENT_TESTCASE_ID.getName()] )

Path previousImageDeltaStats =
StorageScanner.findLatestImageDeltaStats(ms,
examiningTSuiteName,
examiningTExecutionProfile,
examiningTCaseName)
//
StorageScanner storageScanner =
new StorageScanner(
ms,
new StorageScanner.Options.Builder().
previousImageDeltaStats( previousIDS ).
filterDataLessThan( options.getFilterDataLessThan() ).
shiftCriteriaPercentageBy( options.getShiftCriteriaPercentageBy() ).
build())
new StorageScanner.Options.Builder()
.previousImageDeltaStats( previousImageDeltaStats )
.filterDataLessThan( options.getFilterDataLessThan() )
.shiftCriteriaPercentageBy( options.getShiftCriteriaPercentageBy() )
.build()
)

if (logger_ != null) {
storageScanner.setVisualTestingLogger(logger_)
}

// calculate the criteriaPercentages for each screenshot images based on the diffs of previous images
ImageDeltaStats imageDeltaStats = storageScanner.scan(capturingTSuiteName)

// persit the image-delta-stats.json into disk. It will be reused as previousIDS when this script run next time
this.imageDeltaStatsJson_ = storageScanner.persist(imageDeltaStats, tSuiteNameExam, tSuiteTimestampExam, tCaseNameExam)
ImageDeltaStats imageDeltaStats =
storageScanner.scan(capturingTSuiteName,
capturingTExecutionProfile)

// persist the image-delta-stats.json into disk.
// It will be reused as previousImageDeltaStats when this script run next time
this.imageDeltaStatsJson_ =
storageScanner.persist(imageDeltaStats,
examiningTSuiteName,
examiningTExecutionProfile,
examiningTSuiteTimestamp,
examiningTCaseName)

//
return imageDeltaStats
Expand All @@ -155,19 +203,57 @@ public class ImageCollectionDifferDriver {
* @param mr
* @return
*/
private MaterialPairs createMaterialPairs(MaterialRepository mr, TSuiteName capturingTSuiteName) {
MaterialPairs materialPairs = mr.createMaterialPairs(capturingTSuiteName)
private MaterialPairs createMaterialPairsForChronosMode(MaterialRepository mr,
TSuiteName capturingTSuiteName,
TExecutionProfile capturingTExecutionProfile)
{
Objects.requireNonNull(mr, "mr must not be null")
Objects.requireNonNull(capturingTSuiteName, "capturingTSuiteName must not be null")
Objects.requireNonNull(capturingTExecutionProfile, "capturingTExecutionProfile must not be null")

MaterialPairs materialPairs =
mr.createMaterialPairsForChronosMode(capturingTSuiteName, capturingTExecutionProfile)

if (materialPairs.size() == 0) {
KeywordUtil.markFailedAndStop(
"MaterialPairs in the Test Suite \"${capturingTSuiteName.getId()}/${capturingTExecutionProfile.getName()}\" is empty. " +
"Please make sure your test suite for capturing screenshots successfully ran. " +
"You may have executed the test suite for the 1st time, " +
"or you had erased all previous records in the Storage directory. OK. " +
"Don\'t mind it. " +
"The last execution has restored a set of screenshots. " +
"Just try again. " +
"It sould run OK next time.")
}

return materialPairs
}

/**
*
* @param tSuiteName
* @param mr
* @return
*/
private MaterialPairs createMaterialPairsForTwinsMode(MaterialRepository mr,
TSuiteName capturingTSuiteName)
{
Objects.requireNonNull(mr, "mr must not be null")
Objects.requireNonNull(capturingTSuiteName, "capturingTSuiteName must not be null")

MaterialPairs materialPairs =
mr.createMaterialPairsForTwinsMode(capturingTSuiteName)

if (materialPairs.size() == 0) {
KeywordUtil.markFailedAndStop(
"The size of materialPairs of the Test Suite \"${capturingTSuiteName.getId()}\" is found == 0. " +
"MaterialPairs in the Test Suite \"${capturingTSuiteName.getId()}\" is empty. " +
"Please make sure your test suite for capturing screenshots successfully ran. " +
"And you may have executed the test suite for the 1st time, " +
"or you had erased all previous records of its execution in the Storage directory. " +
"You may have executed the test suite for the 1st time, " +
"or you had erased all previous records in the Storage directory. OK. " +
"Don\'t mind it. " +
"The last execution has restored a set of screenshots. " +
"Just try the Test Suite again. " +
"Then it should run OK.")
"Just try again. " +
"It sould run OK next time.")
}

return materialPairs
Expand Down
20 changes: 14 additions & 6 deletions Keywords/com/kazurayam/visualtesting/ImageDiffer.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java.nio.file.Path

import com.kazurayam.materials.MaterialRepository
import com.kazurayam.materials.MaterialStorage
import com.kazurayam.materials.TExecutionProfile
import com.kazurayam.materials.TSuiteName
import com.kazurayam.materials.VisualTestingLogger
import com.kazurayam.visualtesting.ImageCollectionDifferDriver.ChronosOptions
Expand All @@ -27,9 +28,10 @@ public class ImageDiffer {
* @param testSuiteId
* @param options
*/
boolean runChronos(String testSuiteId, ChronosOptions options) {
boolean runChronos(String testSuiteId, String executionProfile, ChronosOptions options) {

Objects.requireNonNull(testSuiteId, "testSuiteId must not be null")
Objects.requireNonNull(executionProfile, "executionProfile must not be null")
Objects.requireNonNull(options, "options must not be null")

/*
Expand All @@ -42,15 +44,16 @@ public class ImageDiffer {

/*
* make image diffs, write the result into the directory
* 'Materials/47news.chronos_exam/yyyyMMdd_hhmmss/ImageDiff_new' which is
* 'Materials/<current TSuiteName>/<current Timestamp>/<cuurent TCaseName>'
* 'Materials/47news.chronos_exam/default/yyyyMMdd_hhmmss/ImageDiff_new'
* which is in the format of
* 'Materials/<current TSuiteName>/<Execution Profile>/<current Timestamp>/<current TCaseName>'
*/

driver_ = new ImageCollectionDifferDriver(mr)
VisualTestingLogger logger = new VisualTestingLoggerImpl()
driver_.setVisualTestingLogger(logger)

return driver_.chronos(new TSuiteName(testSuiteId), ms, options)
return driver_.chronos(new TSuiteName(testSuiteId), new TExecutionProfile(executionProfile), ms, options)
}


Expand All @@ -60,8 +63,9 @@ public class ImageDiffer {
* @param testSuiteId
* @param criteriaPercentage
*/
boolean runTwins(String testSuiteId, double criteriaPercentage) {
boolean runTwins(String testSuiteId, String executionProfile, double criteriaPercentage) {
Objects.requireNonNull(testSuiteId, "testSuiteId must not be null")
Objects.requireNonNull(executionProfile, "executionProfile must not be null")
if (criteriaPercentage < 0.0 || criteriaPercentage > 100.0) {
throw new IllegalArgumentException("criteriaPercentage(${criteriaPercentage} must be a number in range of 0.0 to 100.0)")
}
Expand All @@ -81,9 +85,13 @@ public class ImageDiffer {
VisualTestingLogger logger = new VisualTestingLoggerImpl()
driver_.setVisualTestingLogger(logger)

return driver_.twins(new TSuiteName(testSuiteId), criteriaPercentage)
return driver_.twins(new TSuiteName(testSuiteId), new TExecutionProfile(executionProfile), criteriaPercentage)
}

/**
*
* @return
*/
public Path getComparisonResultBundleFile() {
if (this.driver_ != null) {
return this.driver_.getComparisonResultBundleFile()
Expand Down
17 changes: 10 additions & 7 deletions Keywords/com/kazurayam/visualtesting/ManagedGlobalVariable.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ import internal.GlobalVariable

public enum ManagedGlobalVariable {

CURRENT_TESTSUITE_ID ('VT_CURRENT_TESTSUITE_ID'),
CURRENT_TESTSUITE_TIMESTAMP ('VT_CURRENT_TESTSUITE_TIMESTAMP'),
CURRENT_TESTCASE_ID ('VT_CURRENT_TESTCASE_ID'),
LAST_EXECUTED_TESTSUITE_ID ('VT_LAST_EXECUTED_TESTSUITE_ID'),
MATERIAL_REPOSITORY ('VT_MATERIAL_REPOSITORY'),
MATERIAL_STORAGE ('VT_MATERIAL_STORAGE'),
REPORTS_ACCESSOR ('VT_REPORTS_ACCESSOR')
CURRENT_TESTSUITE_ID ('VT_CURRENT_TESTSUITE_ID'),
CURRENT_EXECUTION_PROFILE ('VT_CURRENT_EXECUTION_PROFILE'),
CURRENT_TESTSUITE_TIMESTAMP ('VT_CURRENT_TESTSUITE_TIMESTAMP'),
CURRENT_TESTCASE_ID ('VT_CURRENT_TESTCASE_ID'),
LAST_EXECUTED_TESTSUITE_ID ('VT_LAST_EXECUTED_TESTSUITE_ID'),
LAST_APPLIED_EXECUTION_PROFILE ('VT_LAST_APPLIED_EXECUTION_PROFILE'),
MATERIAL_REPOSITORY ('VT_MATERIAL_REPOSITORY'),
MATERIAL_STORAGE ('VT_MATERIAL_STORAGE'),
REPORTS_ACCESSOR ('VT_REPORTS_ACCESSOR')
;

private String name_

public ManagedGlobalVariable(String name) {
Expand Down
Loading

0 comments on commit a061baf

Please sign in to comment.