Example of Visual Regression test
(require '[visual-regression :as vr]) | |
(deftask compare-screenshots | |
"Run visual regression specs over the devcards." | |
(let [tmp (core/tmp-dir!)] | |
(fn [next-task] | |
(fn [file-set] | |
(vr/compare-cards "vr") | |
(next-task file-set))))) |
(ns visual-regression | |
(:require | |
[clojure.java.io :as io] | |
[clj-webdriver.taxi :as taxi] | |
[taoensso.timbre :as timbre]) | |
(:import [ru.yandex.qatools.ashot Screenshot] | |
[javax.imageio ImageIO] | |
[ru.yandex.qatools.ashot.comparison ImageDiffer ImageDiff])) | |
(defn start-browser [] | |
(taxi/set-driver! {:browser :phantomjs} "http://localhost:8000/cards")) | |
(def root-path | |
"Where the expected screenshots live and new screenshots will capture to" | |
(str (.getCanonicalPath (clojure.java.io/file ".")) "/screen_shots/")) | |
(defn touch-dir | |
"Creates a directory path if it does not already exist." | |
[dir] | |
(io/make-parents (str dir "touch"))) | |
(defn capture-cards | |
"Take screen shots of every devcard and write them to the output-dir | |
dir. Returns a vector of the file names of all the images captured." | |
[output-dir] | |
(let [driver (start-browser) | |
_ (touch-dir output-dir) | |
title-selector "a.com-rigsomelight-devcards_set-current-path" | |
_ (taxi/wait-until #(-> (taxi/element title-selector))) | |
_ (taxi/window-maximize) | |
card-link-selector "a.com-rigsomelight-devcards-list-group-item" | |
card-count (count (taxi/elements card-link-selector)) | |
file-names (atom [])] | |
(timbre/info "Capturing cards into" output-dir) | |
(doseq [idx (range card-count)] | |
(let [selector (str "div.com-rigsomelight-devcards-list-group a:nth-child(" | |
(inc idx) ")") | |
card-title (taxi/text (str selector " span:nth-child(2)")) | |
img-path (str output-dir card-title ".png")] | |
(timbre/info "Capturing card:" card-title) | |
(taxi/click selector) | |
;; Allow any animations to happen e.g. d3 or React lifecycle methods. | |
(Thread/sleep 3000) | |
(taxi/take-screenshot :file img-path) | |
(swap! file-names conj (str card-title ".png")) | |
(taxi/back))) | |
(taxi/quit) | |
@file-names)) | |
(defn compare-cards | |
"Compares screenshots in the expected and actual directories (generates the actual). | |
Saves diff images in diff-dir. Throws an exception with a list of diffs." | |
[sub-dir] | |
(let [diffs (atom []) | |
expected-dir (str root-path sub-dir "/expected/") | |
actual-dir (str root-path sub-dir "/actual/") | |
diff-dir (str root-path sub-dir "/diff/") | |
_ (touch-dir expected-dir) | |
_ (touch-dir actual-dir) | |
_ (touch-dir diff-dir) | |
imgs (capture-cards (str root-path sub-dir "/actual/"))] | |
(timbre/info "Expected directory" expected-dir) | |
(timbre/info "Actual directory" actual-dir) | |
(timbre/info "Diff directory" diff-dir) | |
(doseq [img-name imgs] | |
(let [expected (ImageIO/read (io/as-file (str expected-dir img-name))) | |
actual (ImageIO/read (io/as-file (str actual-dir img-name))) | |
differ (ImageDiffer.) | |
diff (.makeDiff differ expected actual)] | |
(timbre/info img-name "has a diff size" (.getDiffSize diff)) | |
(when (.hasDiff diff) | |
(swap! diffs conj {:img-name img-name :diff-size (.getDiffSize diff)}) | |
(ImageIO/write (.getMarkedImage diff) | |
"png" | |
(io/as-file (str diff-dir img-name)))))) | |
(if (seq @diffs) | |
(throw (ex-info "Visual Regression Encountered!" | |
{:diffs @diffs})) | |
(timbre/info "No visual regressions encountered.")))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment