Skip to content

Commit

Permalink
Allow test suite tests to reference directories.
Browse files Browse the repository at this point in the history
Issue #14 - Allow test suites to reference test directories as well
as individual test files. Directories are loaded in the same way as
directory suites except the containing test suite is defined in the
test file and not inferred from the directory name.
  • Loading branch information
lkitching committed Oct 22, 2018
1 parent b1046c0 commit ce5fe62
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 26 deletions.
71 changes: 45 additions & 26 deletions src/rdf_validator/test_cases.clj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
[rdf-validator.util :as util])
(:import [java.io File]))

(defn- load-source-test [suite-name source]
(defn- load-source-test
"Loads a test definition from the specified data source. Infers the test type and name from the name of
the source."
[suite-name source]
(let [[n ext] (util/split-file-name-extension (util/get-file-name source))
type (some-> ext keyword)]
(if (= :sparql type)
Expand Down Expand Up @@ -47,36 +50,65 @@
[f]
(edn/read-string {:readers {'resource resolve-test-resource}} (slurp f)))

(defn- ^File resolve-test-file
"Resolves a test source path against the parent test suite file."
[^File suite-file test-source]
(let [suite-dir (.getParentFile suite-file)]
(io/file suite-dir test-source)))

(defn- resolve-test-source
"Resolves a test definition into an absolute data source."
[^File suite-file test-source]
(cond
(string? test-source)
(let [suite-dir (.getParentFile suite-file)]
(io/file suite-dir test-source))
(resolve-test-file suite-file test-source)

(util/url? test-source)
test-source

:else
(throw (ex-info "Test source must be either a string or resource" {:source test-source}))))

(defn- normalise-test
"Normalises a test definition into a map."
[test suite-file suite-name]
(defn- load-directory-tests
"Loads all tests defined within the specified directory."
[suite-name ^File dir]
(let [search (fn search [^File f]
(if (.isDirectory f)
(mapcat search (.listFiles f))
[(load-source-test suite-name f)]))]
(vec (remove nil? (search dir)))))

(defn- load-directory-test-suite
"Recursively loads all tests contained within the given directory."
[^File dir]
(let [suite-name (-> (.getName dir)
(string/lower-case)
(keyword))
tests (load-directory-tests suite-name dir)]
{suite-name {:tests tests}}))

(defn- normalise-tests
"Loads normalised test definitions from a test source referenced within an EDN test suite file.
The source may resolve to multiple contained test definitions."
[suite-file suite-name test]
(cond
(string? test)
(recur {:source test} suite-file suite-name)
(let [test-file (resolve-test-file suite-file test)]
(if (.isDirectory test-file)
(load-directory-tests suite-name test-file)
(if-let [t (load-source-test suite-name test-file)]
[t])))

(util/url? test)
(load-source-test suite-name test)
(if-let [t (load-source-test suite-name test)]
[t])

(map? test)
(let [test-source (resolve-test-source suite-file (:source test))]
{:type (or (:type test) (infer-source-test-type test-source))
:source test-source
:name (or (:name test) (infer-source-test-name test-source))
:suite suite-name})
[{:type (or (:type test) (infer-source-test-type test-source))
:source test-source
:name (or (:name test) (infer-source-test-name test-source))
:suite suite-name}])

:else
(throw (ex-info "Test definition must be either a string or a map" {:suite suite-name}))))
Expand All @@ -86,7 +118,7 @@
[source-file suite-name suite]
(cond
(vector? suite) (recur source-file suite-name {:tests suite})
(map? suite) (update suite :tests #(mapv (fn [t] (normalise-test t source-file suite-name)) %))
(map? suite) (update suite :tests #(vec (mapcat (fn [t] (normalise-tests source-file suite-name t)) %)))
:else (throw (ex-info "Suite definition must be a vector or a map" {:suite suite}))))

(defmethod load-file-test-suite :edn [f]
Expand All @@ -100,19 +132,6 @@
(defmethod load-file-test-suite :default [f]
nil)

(defn- load-directory-test-suite
"Recursively loads all tests contained within the given directory."
[^File dir]
(let [suite (-> (.getName dir)
(string/lower-case)
(keyword))
search (fn search [^File f]
(if (.isDirectory f)
(mapcat search (.listFiles f))
[(load-source-test suite f)]))
tests (vec (remove nil? (search dir)))]
{suite {:tests tests}}))

(defn load-test-suite
"Loads a test suite definition map from a given file. If a file is passed it is considered to contain
a single test of a type inferred from the file extension. If a directory is given the suite is constructed
Expand Down
13 changes: 13 additions & 0 deletions test/rdf_validator/test_cases_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@
:name "select"}]}}
suite))))

(deftest load-test-suite-referencing-directory
(let [f (io/file "test/suites/dir.edn")
suite (load-test-suite f)]
(is (= {:dir {:tests [{:type :sparql
:source (io/file "test/suites/queries/ask.sparql")
:suite :dir
:name "ask"}
{:type :sparql
:source (io/file "test/suites/queries/select.sparql")
:suite :dir
:name "select"}]}}
suite))))

(deftest load-test-suite-with-resources
(let [f (io/file "test/suites/with-resources.edn")
suite (load-test-suite f)]
Expand Down
1 change: 1 addition & 0 deletions test/suites/dir.edn
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{:dir ["queries"]}

0 comments on commit ce5fe62

Please sign in to comment.