Skip to content

Instantly share code, notes, and snippets.

@adstage-david
Created September 9, 2016 20:50
Show Gist options
  • Save adstage-david/864539c452f9fa54851bab09a40f09fb to your computer and use it in GitHub Desktop.
Save adstage-david/864539c452f9fa54851bab09a40f09fb to your computer and use it in GitHub Desktop.
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