Broken, but promising, version: generates interesting tests for multi-arg
functions, but breaks on some of them for reasons I don't yet understand.
This commit is contained in:
parent
f9325526ab
commit
0125723c83
17
README.md
17
README.md
|
@ -2,6 +2,23 @@
|
||||||
|
|
||||||
A Clojure library designed to generate charaterisation tests.
|
A Clojure library designed to generate charaterisation tests.
|
||||||
|
|
||||||
|
### WARNING! Currently broken
|
||||||
|
|
||||||
|
In trying to make testgen generate tests for functions of more than one argument, I've broken it. It's not completely broken - it generates interesting and useful tests for simple functions like this:
|
||||||
|
|
||||||
|
(generate-test '(defn n-of [arg n]
|
||||||
|
"Return a list of n instances of arg"
|
||||||
|
(cond
|
||||||
|
(zero? n) nil
|
||||||
|
true (cons arg (n-of arg (dec n))))) '(1 2))
|
||||||
|
|
||||||
|
This is clearly very promising behaviour. However, it currently won't eat its own dogfood, failing with:
|
||||||
|
|
||||||
|
user=> (generate-tests "src/testgen/core.clj")
|
||||||
|
IllegalArgumentException Don't know how to create ISeq from: java.lang.Double clojure.lang.RT.seqFrom (RT.java:505)
|
||||||
|
|
||||||
|
I have not yet got to the bottom of this bug :-(
|
||||||
|
|
||||||
## What are 'characterisation tests'?
|
## What are 'characterisation tests'?
|
||||||
|
|
||||||
Characterisation tests are a suite of tests which characterise the behaviour of a corpus of code. That is to say, they describe, and test, what it does now, whether that's correct or not. Otherwise, they are like unit tests. In fact, they are unit tests - except that unit tests are normally written to describe the desired behaviour of a corpus of code; these describe the actual behaviour.
|
Characterisation tests are a suite of tests which characterise the behaviour of a corpus of code. That is to say, they describe, and test, what it does now, whether that's correct or not. Otherwise, they are like unit tests. In fact, they are unit tests - except that unit tests are normally written to describe the desired behaviour of a corpus of code; these describe the actual behaviour.
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
(ns testgen.core
|
(ns testgen.core
|
||||||
(:use clojure.java.io
|
(:use clojure.java.io
|
||||||
clojure.pprint))
|
clojure.pprint
|
||||||
|
clojure.math.combinatorics))
|
||||||
|
|
||||||
|
|
||||||
(defn maybe-quote [val]
|
(defn maybe-quote [val]
|
||||||
"Convert val into a form in which, after being passed through the pretty
|
"Convert val into a form in which, after being passed through the pretty
|
||||||
|
@ -9,8 +11,9 @@
|
||||||
(symbol? val) (list 'symbol (str val))
|
(symbol? val) (list 'symbol (str val))
|
||||||
true (list 'quote val)))
|
true (list 'quote val)))
|
||||||
|
|
||||||
(defn generate-assertion [fnname & args]
|
(defn generate-assertion [fnname args]
|
||||||
"Generate an appropiate assertion for these arguments passed to this function"
|
"Generate an appropiate assertion for these arguments passed to this function"
|
||||||
|
(print (str "Generating assertion for " (cons fnname args)))
|
||||||
(try
|
(try
|
||||||
(let [val (eval (cons fnname args))]
|
(let [val (eval (cons fnname args))]
|
||||||
(list 'is (list '= (cons fnname args) (maybe-quote val))))
|
(list 'is (list '= (cons fnname args) (maybe-quote val))))
|
||||||
|
@ -23,7 +26,9 @@
|
||||||
(vector? arg)
|
(vector? arg)
|
||||||
(map? arg))))
|
(map? arg))))
|
||||||
|
|
||||||
(def generic-args '(nil () (quote (a :b "c")) true "test" :test 0 22/7 0.0001 -0.0001))
|
;; (def generic-args '(nil () (quote (a :b "c")) "test" true :test 0 Integer/MAX_VALUE 22/7 0.0001 -0.0001))
|
||||||
|
(def generic-args '(nil () (quote (a :b "c")) "test" true :test 0))
|
||||||
|
;; (def generic-args nil)
|
||||||
|
|
||||||
(defn constants [form]
|
(defn constants [form]
|
||||||
"return a list of all elements in this form which are constants"
|
"return a list of all elements in this form which are constants"
|
||||||
|
@ -48,14 +53,31 @@
|
||||||
true (cons arg (n-of arg (dec n)))))
|
true (cons arg (n-of arg (dec n)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; This version of generate-test tries to generate good tests for functions of one
|
||||||
|
;; argument. It works.
|
||||||
|
;; (defn generate-test [fndef extra-vars]
|
||||||
|
;; "Generate a test for this function definition"
|
||||||
|
;; (cond (or (= (first fndef) 'def)(= (first fndef) 'defn))
|
||||||
|
;; (let [name (first (rest fndef))
|
||||||
|
;; potential-args (find-interesting-args fndef extra-vars)]
|
||||||
|
;; (list 'deftest (symbol (str "test-" name))
|
||||||
|
;; (concat (list 'testing (str name))
|
||||||
|
;; (map #(generate-assertion name (list %)) potential-args))))))
|
||||||
|
|
||||||
|
;; This version of generate-test tries to generate good tests for functions of one or more than one
|
||||||
|
;; argument. Unfortunately, it is borked.
|
||||||
(defn generate-test [fndef extra-vars]
|
(defn generate-test [fndef extra-vars]
|
||||||
|
"Generate a test for this function definition"
|
||||||
(cond (or (= (first fndef) 'def)(= (first fndef) 'defn))
|
(cond (or (= (first fndef) 'def)(= (first fndef) 'defn))
|
||||||
(let [name (first (rest fndef))
|
(let [name (first (rest fndef))
|
||||||
potential-args (find-interesting-args fndef extra-vars)]
|
potential-args (find-interesting-args fndef extra-vars)]
|
||||||
|
(try
|
||||||
(list 'deftest (symbol (str "test-" name))
|
(list 'deftest (symbol (str "test-" name))
|
||||||
(concat (list 'testing (str name))
|
(concat (list 'testing (str name))
|
||||||
(map #(generate-assertion name %)
|
(map #(generate-assertion name %)
|
||||||
(cond (= ))))))
|
(cond (vector? (nth fndef 2)) (apply cartesian-product (n-of potential-args (count (nth fndef 2))))
|
||||||
|
true (map #(list %) potential-args)))))
|
||||||
|
(catch Exception any)))))
|
||||||
|
|
||||||
;; generating a test file
|
;; generating a test file
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue