Permalink
Browse files

added should-throw, should-faile. Added dynamic creation of runner an…

… reporter in main
  • Loading branch information...
1 parent 34e8f8d commit 6abff04745eefd748e1b9515abff06ec5961e159 @slagyr committed Nov 19, 2010
View
Oops, something went wrong.
View
@@ -1,4 +1,4 @@
-(defproject speclj "1.0.0-SNAPSHOT"
- :description "FIXME: write"
- :dependencies [[org.clojure/clojure "1.2.0"]
- [org.clojure/clojure-contrib "1.2.0"]])
+(defproject speclj "1.0.0"
+ :description "speclj: Pronounced 'speckle', is a Behavior Driven Development framework for Clojure."
+ :dependencies [[org.clojure/clojure "1.2.0"]]
+ :test-path "spec/")
@@ -1,4 +1,4 @@
-(ns speclj.core-test
+(ns speclj.core-spec
(:use
[speclj.core]))
@@ -0,0 +1,61 @@
+(ns speclj.main-spec
+ (:use
+ [speclj.core]
+ [speclj.main])
+ (:require
+ [speclj.run.standard]
+ [speclj.run.vigilant]
+ [speclj.report.console]
+ [speclj.report.silent]))
+
+(describe "speclj main"
+
+ (it "has default configuration"
+ (should= ["spec"] (:spec-dirs default-config))
+ (should= "console" (:reporter default-config))
+ (should= "standard" (:runner default-config)))
+
+ (it "parses no arguments"
+ (should= default-config (parse-args)))
+
+ (it "parses non-option arguments as spec dirs"
+ (should= ["one"] (:spec-dirs (parse-args "one")))
+ (should= ["one" "two"] (:spec-dirs (parse-args "one" "two")))
+ (should= ["one" "two" "three"] (:spec-dirs (parse-args "one" "two" "three"))))
+
+ (it "parses the runner argument"
+ (should= "fridge" (:runner (parse-args "--runner=fridge")))
+ (should= "freezer" (:runner (parse-args "--runner=freezer"))))
+
+ (it "parses the reporter argument"
+ (should= "april" (:reporter (parse-args "--reporter=april")))
+ (should= "mary-jane" (:reporter (parse-args "--reporter=mary-jane"))))
+
+ (it "dynaimcally loads StandardRunner"
+ (let [runner (load-runner "standard")]
+ (should-not= nil runner)
+ (should= speclj.run.standard.StandardRunner (class runner))))
+
+ (it "dynaimcally loads VigilantRunner"
+ (let [runner (load-runner "vigilant")]
+ (should-not= nil runner)
+ (should= speclj.run.vigilant.VigilantRunner (class runner))))
+
+ (it "throws exception with unrecognized runner"
+ (should-throw Exception "Failed to load runner: blah" (load-runner "blah")))
+
+ (it "dynaimcally loads ConsoleReporter"
+ (let [reporter (load-reporter "console")]
+ (should-not= nil reporter)
+ (should= speclj.report.console.ConsoleReporter (class reporter))))
+
+ (it "dynaimcally loads SilentReporter"
+ (let [reporter (load-reporter "silent")]
+ (should-not= nil reporter)
+ (should= speclj.report.silent.SilentReporter (class reporter))))
+
+ (it "throws exception with unrecognized reporter"
+ (should-throw Exception "Failed to load reporter: blah" (load-reporter "blah")))
+ )
+
+(conclude-single-file-run)
@@ -1,4 +1,4 @@
-(ns speclj.reporting-test
+(ns speclj.reporting-spec
(:use
[speclj.core]
[speclj.reporting]))
@@ -0,0 +1,155 @@
+(ns speclj.run.vigilant-spec
+ (:use
+ [speclj.core]
+ [speclj.run.vigilant]
+ [clojure.java.io :only (file copy make-input-stream)]))
+
+(def tmp-dir (file "_tmp"))
+(def test-dir (file "_tmp/test"))
+(def src-dir (file "_tmp/src"))
+(def spec-dirs [(.getPath test-dir)])
+
+(defn delete-tmp-dir []
+ (doseq [file (reverse (file-seq tmp-dir))]
+ (if (not (.delete file))
+ (throw (str "Failed to delete file: " file)))))
+
+(defn write-tmp-file [name content]
+ (let [file (file tmp-dir name)]
+ (copy (make-input-stream (.getBytes content) {}) file)
+ file))
+
+(defn tweak-mod-time [runner file tweak]
+ (let [listing (.listing runner)
+ tracker (get @listing file)]
+ (if tracker
+ (swap! listing assoc file (new-file-tracker (.ns tracker) (tweak (.mod-time tracker)) (.dependencies tracker))))))
+
+(defn fake-ns-to-file [ns]
+ (file src-dir (ns-to-filename ns)))
+
+(describe "Vigilant Runner"
+ (before (doseq [dir [tmp-dir test-dir src-dir]] (.mkdir dir)))
+ (after (delete-tmp-dir))
+ (with runner (new-vigilant-runner))
+ (around [_] (binding [ns-to-file fake-ns-to-file] (_)))
+
+ (it "detects no changes with empty directory"
+ (should= 0 (count (updated-files @runner spec-dirs))))
+
+ (it "detects changes on first check"
+ (write-tmp-file "test/one.clj" "(ns one)")
+ (let [updates (updated-files @runner spec-dirs)]
+ (should= 1 (count updates))
+ (should= "one.clj" (.getName (first updates)))))
+
+ (it "detects changes new files"
+ (updated-files @runner spec-dirs)
+ (write-tmp-file "test/one.clj" "()")
+ (let [updates (updated-files @runner spec-dirs)]
+ (should= 1 (count updates))
+ (should= "one.clj" (.getName (first updates)))))
+
+ (it "detects changes on changed files"
+ (let [tmp-file (write-tmp-file "test/one.clj" "(ns one)")]
+ (track-files @runner tmp-file)
+ (tweak-mod-time @runner tmp-file dec))
+ (let [updates (updated-files @runner spec-dirs)]
+ (should= 1 (count updates))
+ (should= "one.clj" (.getName (first updates)))))
+
+ (it "doesn't detect changes on unchanged files"
+ (track-files @runner (write-tmp-file "test/one.clj" "(ns one)"))
+ (should= 0 (count (updated-files @runner spec-dirs))))
+
+ (it "detects file dependencies based on :use"
+ (let [src-file (write-tmp-file "src/core.clj" "(ns core)")
+ test-file (write-tmp-file "test/core-test.clj" "(ns core-test (:use [core]))")]
+ (track-files @runner test-file)
+ (tweak-mod-time @runner src-file dec)
+ (tweak-mod-time @runner test-file dec))
+ (let [updates (updated-files @runner spec-dirs)]
+ (should= 2 (count updates))
+ (should= "core-test.clj" (.getName (first (next updates))))
+ (should= "core.clj" (.getName (first updates)))))
+
+ (it "stops tracking files that have been deleted, along with their dependencies"
+ (let [src-file1 (write-tmp-file "src/src1.clj" "(ns src1)")
+ src-file2 (write-tmp-file "src/src2.clj" "(ns src2)")
+ test-file1 (write-tmp-file "test/test1.clj" "(ns test1 (:use [src1][src2]))")
+ test-file2 (write-tmp-file "test/test2.clj" "(ns test2 (:use [src2]))")]
+ (track-files @runner test-file1 test-file2)
+ (should-not= nil (get @(.listing @runner) test-file1))
+ (should-not= nil (get @(.listing @runner) test-file2))
+ (should-not= nil (get @(.listing @runner) src-file1))
+ (should-not= nil (get @(.listing @runner) src-file2))
+ (.delete test-file1)
+ (clean-deleted-files @runner)
+ (should= 0 (count (updated-files @runner spec-dirs)))
+ (should= nil (get @(.listing @runner) test-file1))
+ (should= nil (get @(.listing @runner) src-file1))
+ (should-not= nil (get @(.listing @runner) test-file2))
+ (should-not= nil (get @(.listing @runner) src-file2))))
+
+ (it "stops tracking files that have been deleted, along with their NESTED dependencies"
+ (let [src-file1 (write-tmp-file "src/src1.clj" "(ns src1 (:use [src2]))")
+ src-file2 (write-tmp-file "src/src2.clj" "(ns src2)")
+ test-file1 (write-tmp-file "test/test1.clj" "(ns test1 (:use [src1]))")]
+ (track-files @runner test-file1)
+ (should-not= nil (get @(.listing @runner) test-file1))
+ (should-not= nil (get @(.listing @runner) src-file1))
+ (should-not= nil (get @(.listing @runner) src-file2))
+ (.delete test-file1)
+ (clean-deleted-files @runner)
+ (should= 0 (count (updated-files @runner spec-dirs)))
+ (should= nil (get @(.listing @runner) test-file1))
+ (should= nil (get @(.listing @runner) src-file1))
+ (should= nil (get @(.listing @runner) src-file2))))
+
+ (it "finds dependents of a given file"
+ (let [src-file1 (write-tmp-file "src/src1.clj" "(ns src1)")
+ src-file2 (write-tmp-file "src/src2.clj" "(ns src2)")
+ test-file1 (write-tmp-file "test/test1.clj" "(ns test1 (:use [src1][src2]))")
+ test-file2 (write-tmp-file "test/test2.clj" "(ns test2 (:use [src2]))")]
+ (track-files @runner test-file1 test-file2)
+ (should= [] (dependents-of @(.listing @runner) test-file1))
+ (should= [] (dependents-of @(.listing @runner) test-file2))
+ (should= [test-file1] (dependents-of @(.listing @runner) src-file1))
+ (should= #{test-file1 test-file2} (set (dependents-of @(.listing @runner) src-file2)))))
+
+ (it "pulls no ns form a file that doens't contain one"
+ (should= nil (read-ns-form (write-tmp-file "test/one.clj" "()")))
+ (should= nil (read-ns-form (write-tmp-file "test/one.clj" "; hello")))
+ (should= nil (read-ns-form (write-tmp-file "test/one.clj" "; (ns blah)"))))
+
+ (it "pulls read ns form from files"
+ (should= '(ns blah) (read-ns-form (write-tmp-file "test/one.clj" "(ns blah)")))
+ (should= '(ns foo) (read-ns-form (write-tmp-file "test/one.clj" "; blah\n(ns foo)")))
+ (should= '(ns blah (:use [foo]) (:require [bar])) (read-ns-form (write-tmp-file "test/one.clj" "(ns blah (:use [foo])(:require [bar]))"))))
+
+ (it "pulls dependencies out of ns form"
+ (should= '#{blah} (dependencies-in-ns '(ns foo (:use [blah]))))
+ (should= '#{bar} (dependencies-in-ns '(ns foo (:use [bar]))))
+ (should= '#{fizz} (dependencies-in-ns '(ns foo (:use fizz))))
+ (should= '#{fizz} (dependencies-in-ns '(ns foo (:require fizz))))
+ (should= '#{one two three} (dependencies-in-ns '(ns foo (:use [one] [two] [three]))))
+ (should= '#{one two three} (dependencies-in-ns '(ns foo (:require [one] [two] [three]))))
+ (should= '#{root.one root.two} (dependencies-in-ns '(ns foo (:use [root [one] [two]]))))
+ (should= '#{root.one root.two} (dependencies-in-ns '(ns foo (:require [root [one] [two]]))))
+ (should= '#{one two} (dependencies-in-ns '(ns foo (:use [one :only (foo)] [two :exclude (bar)]))))
+ (should= '#{one two} (dependencies-in-ns '(ns foo (:require [one :as o] [two :as t]))))
+ (should= '#{one.two one.three} (dependencies-in-ns '(ns foo (:use [one [two :only (foo)] [three :exclude (bar)]]))))
+ (should= '#{one.two one.three} (dependencies-in-ns '(ns foo (:require [one [two :as t] [three :as tr]]))))
+ (should= '#{root.one.child.grandchild root.two} (dependencies-in-ns '(ns foo (:use [root [one [child [grandchild]]] [two]]))))
+ )
+
+ (it "converts ns names into filenames"
+ (should= "foo.clj" (ns-to-filename "foo"))
+ (should= "bar.clj" (ns-to-filename "bar"))
+ (should= "foo/bar.clj" (ns-to-filename "foo.bar"))
+ (should= "foo_bar.clj" (ns-to-filename "foo-bar"))
+ (should= "foo_bar/fizz_bang.clj" (ns-to-filename "foo-bar.fizz-bang")))
+
+ )
+
+(conclude-single-file-run)
@@ -1,10 +1,10 @@
-(ns speclj.running-test
+(ns speclj.running-spec
(:use
[speclj.core]
[speclj.running :only (*runner*)]
[speclj.run.standard :only (new-standard-runner)]
[speclj.reporting :only (*reporter*)]
- [speclj.report.silence :only (new-silent-reporter)])
+ [speclj.report.silent :only (new-silent-reporter)])
(:import (speclj SpecFailure)))
(describe "MultiRunner"
@@ -0,0 +1,79 @@
+(ns speclj.should-spec
+ (:use
+ [speclj.core]
+ [speclj.spec-helper]
+ [speclj.util :only (endl)]))
+
+(describe "Should Assertions: "
+ (it "should tests truthy"
+ (should-pass! (should true))
+ (should-fail! (should false)))
+
+ (it "should= tests equality"
+ (should-pass! (should= 1 1))
+ (should-pass! (should= "hello" "hello"))
+ (should-fail! (should= 1 2))
+ (should-fail! (should= "hello" "goodbye")))
+
+ (it "should failure message is nice"
+ (should= "Expected truthy but was: <false>" (failure-message (should false)))
+ (should= "Expected truthy but was: <>" (failure-message (should nil))))
+
+ (it "should= failure message is nice"
+ (should=
+ (str "Expected: <1>" endl " got: <2> (using =)")
+ (failure-message (should= 1 2))))
+
+ (it "should_not= tests inequality"
+ (should-pass! (should-not= 1 2))
+ (should-fail! (should-not= 1 1)))
+
+ (it "should_not= failure message is nice"
+ (should=
+ (str "Expected: <1>" endl "not to =: <1>")
+ (failure-message (should-not= 1 1))))
+
+ (it "should-fail is an automatic failure"
+ (should-fail! (should-fail))
+ (should= "Forced failure" (failure-message (should-fail))))
+
+ (it "should-fail can take a string as the error message"
+ (should-fail! (should-fail "some message"))
+ (should= "some message" (failure-message (should-fail "some message"))))
+
+ (it "should-throw tests that any Throwable is thrown"
+ (should-pass! (should-throw (throw (Throwable. "error"))))
+ (should-fail! (should-throw (+ 1 1)))
+ (should= (str "Expected java.lang.Throwable thrown from: (+ 1 1)" endl
+ " but got: <nothing thrown>")
+ (failure-message (should-throw (+ 1 1)))))
+
+ (it "should-throw can test an expected throwable type"
+ (should-pass! (should-throw NullPointerException (throw (NullPointerException.))))
+ (should-pass! (should-throw Exception (throw (NullPointerException.))))
+ (should-fail! (should-throw NullPointerException (throw (Exception.))))
+ (should-fail! (should-throw NullPointerException (+ 1 1)))
+ (should= (str "Expected java.lang.NullPointerException thrown from: (+ 1 1)" endl
+ " but got: <nothing thrown>")
+ (failure-message (should-throw NullPointerException (+ 1 1))))
+ (should= (str "Expected java.lang.NullPointerException thrown from: (throw (Exception. \"some message\"))" endl
+ " but got: java.lang.Exception: some message")
+ (failure-message (should-throw NullPointerException (throw (Exception. "some message"))))))
+
+ (it "should-throw can test the message of the exception"
+ (should-pass! (should-throw Exception "My message" (throw (Exception. "My message"))))
+ (should-fail! (should-throw Exception "My message" (throw (Exception. "Not my message"))))
+ (should-fail! (should-throw Exception "My message" (throw (Error. "My message"))))
+ (should-fail! (should-throw Exception "My message" (+ 1 1)))
+ (should= (str "Expected exception message didn't match" endl "Expected: <My message>" endl " got: <Not my message> (using =)")
+ (failure-message (should-throw Exception "My message" (throw (Exception. "Not my message"))))))
+
+ (it "should-not-throw tests that nothing was thrown"
+ (should-pass! (should-not-throw (+ 1 1)))
+ (should-fail! (should-not-throw (throw (Throwable. "error"))))
+ (should= (str "Expected nothing thrown from: (throw (Throwable. \"error\"))" endl
+ " but got: java.lang.Throwable: error")
+ (failure-message (should-not-throw (throw (Throwable. "error"))))))
+ )
+
+(conclude-single-file-run)
@@ -1,4 +1,4 @@
-(ns speclj.test-help
+(ns speclj.spec-helper
(:import [speclj SpecFailure]))
(defmacro run-result [& body]
View
@@ -35,7 +35,7 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="file://$MODULE_DIR$/test" />
+ <root url="file://$MODULE_DIR$/spec" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -0,0 +1,13 @@
+(ns leiningen.spec
+ (:use
+ [speclj.running :only (*runner* report)]
+ [speclj.run.standard :only (new-standard-runner)]
+ [speclj.reporting :only (active-reporter)]
+ [leiningen.compile :only [eval-in-project]])
+ (:import
+ [java.io File]))
+
+(defn spec [project & args]
+ (println "lein args: " args)
+ (let [exec-form `(~'do (~'use 'speclj.main)(~'run '~@args))]
+ (eval-in-project project exec-form nil nil nil)))
Binary file not shown.
Oops, something went wrong.

0 comments on commit 6abff04

Please sign in to comment.