Skip to content

Commit 9f41e69

Browse files
authored
Merge pull request #2167 from jkeys089/image-comparison-example
add image comparison example
2 parents 6875b25 + 055c353 commit 9f41e69

File tree

15 files changed

+379
-0
lines changed

15 files changed

+379
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Karate Image Comparison
2+
This project is designed to demonstrate basic usage of the [Image Comparison](https://github.com/karatelabs/karate/#compare-image) feature.
3+
4+
## Overview
5+
The [Image Comparison](https://github.com/karatelabs/karate/#compare-image) feature was introduced in [Karate 1.3.0](https://github.com/karatelabs/karate/wiki/1.3.0-Upgrade-Guide).
6+
As a new feature with a number of options and a new UI component we wanted to provide a simple introduction to help users get started.
7+
8+
The included features are numbered 1 through 5 and build on each other.
9+
They are intended to demonstrate how you might start from scratch without any baseline images on a new project:
10+
* `1_establish_baseline.feature` establishes baseline images to use in future test runs
11+
* `2_compare_baseline.feature` compares dynamic screenshots against our baseline images
12+
* `3_custom_rebase.feature` demonstrates the use of the `onShowRebase` handler to customize the filename when rebasing
13+
* `4_generic_rebase.feature` shows a slightly more advanced use of the `onShowRebase` handler that incorporates image comparison configuration options
14+
* `5_custom_config.feature` shows the final scenario that is similar to what you might use in real tests
15+
16+
There is also a [screencast](https://www.youtube.com/watch?v=NIP3-njBR-Q) that demonstrates basic usage of the diff UI in the Karate HTML report.
17+
18+
## Running
19+
The `5_custom_config.feature` is a complete [Karate UI test](https://github.com/karatelabs/karate/tree/master/karate-core) that can be executed by running `ImageComparisonRunner` as a JUnit test.
20+
You will be able to open the HTML report (the file-name will appear at the end of the console log) and refresh it when re-running the test.
21+
22+
To manually run the test execute the following commands:
23+
* Install maven artifacts from the latest [develop](https://github.com/karatelabs/karate/tree/develop) branch locally
24+
```
25+
mvn clean install -P pre-release
26+
```
27+
* Run the test from the `examples/image-comparison` directory
28+
```
29+
mvn clean test -Dtest=ImageComparisonRunner
30+
```
31+
32+
## Debugging
33+
You should be able to use the [Karate extension for Visual Studio Code](https://github.com/karatelabs/karate/wiki/IDE-Support#vs-code-karate-plugin) for stepping-through a test for troubleshooting.

examples/image-comparison/pom.xml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<groupId>com.intuit.karate.examples</groupId>
6+
<artifactId>image-comparison-test</artifactId>
7+
<version>1.0-SNAPSHOT</version>
8+
<packaging>jar</packaging>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<java.version>1.8</java.version>
13+
<maven.compiler.version>3.8.1</maven.compiler.version>
14+
<karate.version>1.3.0-SNAPSHOT</karate.version>
15+
</properties>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>com.intuit.karate</groupId>
20+
<artifactId>karate-junit5</artifactId>
21+
<version>${karate.version}</version>
22+
<scope>test</scope>
23+
</dependency>
24+
</dependencies>
25+
26+
<build>
27+
<testResources>
28+
<testResource>
29+
<directory>src/test/java</directory>
30+
<excludes>
31+
<exclude>**/*.java</exclude>
32+
</excludes>
33+
</testResource>
34+
</testResources>
35+
<plugins>
36+
<plugin>
37+
<groupId>org.apache.maven.plugins</groupId>
38+
<artifactId>maven-compiler-plugin</artifactId>
39+
<version>${maven.compiler.version}</version>
40+
<configuration>
41+
<encoding>UTF-8</encoding>
42+
<source>${java.version}</source>
43+
<target>${java.version}</target>
44+
<compilerArgument>-Werror</compilerArgument>
45+
</configuration>
46+
</plugin>
47+
<plugin>
48+
<groupId>org.apache.maven.plugins</groupId>
49+
<artifactId>maven-surefire-plugin</artifactId>
50+
<version>2.22.2</version>
51+
</plugin>
52+
</plugins>
53+
</build>
54+
55+
</project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<configuration>
3+
4+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
5+
<encoder>
6+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
7+
</encoder>
8+
</appender>
9+
10+
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
11+
<file>target/karate.log</file>
12+
<encoder>
13+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
14+
</encoder>
15+
</appender>
16+
17+
<logger name="com.intuit.karate" level="DEBUG"/>
18+
<logger name="ui" level="DEBUG"/>
19+
20+
<root level="warn">
21+
<appender-ref ref="STDOUT" />
22+
<appender-ref ref="FILE" />
23+
</root>
24+
25+
</configuration>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Feature: Image comparison demo
2+
3+
Background:
4+
* configure driver = { type: 'chrome', screenshotOnFailure: false }
5+
* driver karate.properties['web.url.base']
6+
* driver.emulateDevice(375, 667, 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1')
7+
8+
Scenario: Landing page
9+
* configure imageComparison = { mismatchShouldPass: true }
10+
11+
* def loadingScreenshot = screenshot()
12+
* compareImage { latest: #(loadingScreenshot) }
13+
14+
* waitFor('.welcome')
15+
* def loadedScreenshot = screenshot()
16+
* compareImage { latest: #(loadedScreenshot) }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Feature: Image comparison demo
2+
3+
Background:
4+
* configure driver = { type: 'chrome', screenshotOnFailure: false }
5+
* driver karate.properties['web.url.base']
6+
* driver.emulateDevice(375, 667, 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1')
7+
8+
Scenario: Landing page
9+
* configure imageComparison = { mismatchShouldPass: true }
10+
11+
* def loadingScreenshot = screenshot()
12+
* compareImage { baseline: 'this:screenshots/latest.png', latest: #(loadingScreenshot) }
13+
14+
* waitFor('.welcome')
15+
* def loadedScreenshot = screenshot()
16+
* compareImage { baseline: 'this:screenshots/latest.png', latest: #(loadedScreenshot) }
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Feature: Image comparison demo
2+
3+
Background:
4+
* configure driver = { type: 'chrome', screenshotOnFailure: false }
5+
* driver karate.properties['web.url.base']
6+
* driver.emulateDevice(375, 667, 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1')
7+
8+
Scenario: Landing page
9+
* def loadingScreenshot = screenshot()
10+
* configure imageComparison = { onShowRebase: "(cfg, saveAs) => saveAs('loading.png')", mismatchShouldPass: true }
11+
* compareImage { baseline: 'this:screenshots/latest.png', latest: #(loadingScreenshot) }
12+
13+
* waitFor('.welcome')
14+
* def loadedScreenshot = screenshot()
15+
* configure imageComparison = { onShowRebase: "(cfg, saveAs) => saveAs('loaded.png')", mismatchShouldPass: true }
16+
* compareImage { baseline: 'this:screenshots/latest.png', latest: #(loadedScreenshot) }
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Feature: Image comparison demo
2+
3+
Background:
4+
* configure imageComparison = { onShowRebase: '(cfg, saveAs) => saveAs(cfg.name)', mismatchShouldPass: true }
5+
6+
* configure driver = { type: 'chrome', screenshotOnFailure: false }
7+
* driver karate.properties['web.url.base']
8+
* driver.emulateDevice(375, 667, 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1')
9+
10+
Scenario: Landing page
11+
* def loadingScreenshot = screenshot()
12+
* def loadingOpts =
13+
"""
14+
{
15+
name: 'loading.png'
16+
}
17+
"""
18+
* compareImage { baseline: 'this:screenshots/loading.png', latest: #(loadingScreenshot), options: #(loadingOpts) }
19+
20+
* waitFor('.welcome')
21+
22+
* def loadedScreenshot = screenshot()
23+
* def loadedOpts =
24+
"""
25+
{
26+
name: 'loaded.png'
27+
}
28+
"""
29+
* compareImage { baseline: 'this:screenshots/loaded.png', latest: #(loadedScreenshot), options: #(loadedOpts) }
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Feature: Image comparison demo
2+
3+
Background:
4+
* configure imageComparison = { onShowRebase: '(cfg, saveAs) => saveAs(cfg.name)' }
5+
6+
* configure driver = { type: 'chrome', screenshotOnFailure: false }
7+
* driver karate.properties['web.url.base']
8+
* driver.emulateDevice(375, 667, 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1')
9+
10+
Scenario: Landing page
11+
* def loadingScreenshot = screenshot()
12+
* def loadingOpts =
13+
"""
14+
{
15+
name: 'loading.png',
16+
"ignoredBoxes": [{
17+
"top": 278,
18+
"left": 131,
19+
"bottom": 391,
20+
"right": 246
21+
}]
22+
}
23+
"""
24+
* compareImage { baseline: 'this:screenshots/loading.png', latest: #(loadingScreenshot), options: #(loadingOpts) }
25+
26+
* waitFor('.welcome')
27+
28+
* def loadedScreenshot = screenshot()
29+
* def loadedOpts =
30+
"""
31+
{
32+
name: 'loaded.png',
33+
"ignoredBoxes": [{
34+
"top": 73,
35+
"left": 17,
36+
"bottom": 125,
37+
"right": 188
38+
}]
39+
}
40+
"""
41+
* compareImage { baseline: 'this:screenshots/loaded.png', latest: #(loadedScreenshot), options: #(loadedOpts) }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package ui;
2+
3+
import com.intuit.karate.http.HttpServer;
4+
import com.intuit.karate.junit5.Karate;
5+
import org.junit.jupiter.api.BeforeAll;
6+
7+
class ImageComparisonRunner {
8+
9+
@BeforeAll
10+
public static void beforeAll() {
11+
HttpServer server = MockRunner.start(0);
12+
System.setProperty("web.url.base", "http://localhost:" + server.getPort());
13+
}
14+
15+
@Karate.Test
16+
Karate testUi() {
17+
return Karate.run("classpath:ui/5_custom_config.feature");
18+
}
19+
20+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package ui;
2+
3+
import com.intuit.karate.http.HttpServer;
4+
import com.intuit.karate.http.ServerConfig;
5+
import org.junit.jupiter.api.Test;
6+
7+
/**
8+
* run this as a junit test to start an http server at port 8080 the html page
9+
* can be viewed at http://localhost:8080/ kill / stop this process when done
10+
*/
11+
class MockRunner {
12+
13+
@Test
14+
public void testStart() {
15+
start(8080).waitSync();
16+
}
17+
18+
public static HttpServer start(int port) {
19+
ServerConfig config = new ServerConfig("src/test/java/ui/html")
20+
.autoCreateSession(true);
21+
return HttpServer.config(config).http(port).build();
22+
}
23+
24+
}

0 commit comments

Comments
 (0)