fukamachi/prove

How to test contents from another file?

4lph4-Ph4un opened this issue · 6 comments

Hi! I'm fairly new to Lisps and I'm currently using Prove to get a good headstart by writing a set of learning tests of the CLisp -language properties. As you can image, for learning one would like to implement test hierarchically to get a nice indented output per topics and subtopics. However my testfiles are getting quite long already so it would be nice to be able to split some of the code into other modules. How can this be done. let's assume there's something simple like this:

(defpackage #:master-class-test-types
  (:use #:cl #:prove)

(in-package #:master-class-test-types)


(plan nil)

(subtest (format nil "Lisp types can be typed into two major categories:~@
                      ATOMIC TYPES and LISTS:")
  (subtest "The following types are called ATOMIC:"
    (subtest "NUMBER types such:"
      (subtest "REAL NUMBERS like:"
	(subtest "RATIONAL NUMBERS:"
	  ;; Testing Integers:
	  (let ((fixture-int      123)
		(fixture-pos-int +123)
		(fixture-neg-int -123))
	    (subtest (format nil "INTEGERS (E.G):~@
                                  ~@T-  ~D~@
                                  ~@T- ~@D~@
                                  ~@T- ~@D"
			     fixture-int
			     fixture-pos-int
			     fixture-neg-int)
	      (is-type fixture-int     'integer)
	      (is-type fixture-pos-int 'integer)
	      (is-type fixture-neg-int 'integer)
	      (subtest "Integers also have two distinct subtypes:"
		(pass (format
		       nil
		       "- \"fixnum\"~@
                        ~@T~@T- Smaller efficient integers between~@
                        ~@T~@T  [ -2^15, 2^15 - 1]"))
		(pass (format
		       nil
		       "- \"bignum\"~@
                        ~@T~@T- Non-Fixnums which size is limited to the memory~@
                        ~@T~@T  allocated to Lisp itself. Slower performing")))))
	  (let ((fixture-binary #b1010)
		(fixture-hex    #x0a)
		(fixture-octal  #o12))
	    (subtest (format nil "Allowing NON-DECIMAL REPRESENTATION (E.G):~@
                                  ~@T- ~B (binary - prefix \"#b\")~@
                                  ~@T- ~X (hexadecimal - prefix \"#x\")~@
                                  ~@T- ~O (octal - prefix \"#o\")"
			     fixture-binary
			     fixture-hex
			     fixture-octal)
	      (is-type fixture-binary 'integer)
	      (is-type fixture-hex    'integer)
	      (is-type fixture-octal  'integer)))
	  (let ((fixture-ratio-a 1/2)
		(fixture-ratio-b 3/5))
	    ;; We use "~S" to print as "write"
	    (subtest (format nil "RATIOS (E.G):~@
                                  ~@T- ~D~@
                                  ~@T- ~D"
			     fixture-ratio-a
			     fixture-ratio-b)
	      (is-type fixture-ratio-a 'ratio)
	      (is-type fixture-ratio-b 'ratio)
	      (subtest "Functions performing division always produce RATIOS:"
		(is-type (/ 1 2) 'ratio)))))
	;; Testing Floats:
	;; "s0" would not be needed since short is default
	(let ((fixture-short  (float 2/3 1.0s0)) 
	      (fixture-single (float 2/3 1.0f0))
	      (fixture-double (float 2/3 1.0d0))
	      (fixture-long   (float 2/3 1.0l0)))
	  (subtest (format nil "FLOATING POINTS ~@
                                (E.G - demonstrated with repeating decimal 2/3):~@
                                ~@T- ~F (short [default or \"s0\"])~@
                                ~@T- ~F (single [\"f0\"])~@
                                ~@T- ~F (double [\"d0\"])~@
                                ~@T- ~F (long [\"l0\"])"
			   fixture-short
			   fixture-single
			   fixture-double
			   fixture-long)
	    (is-type fixture-short  'short-float)
	    (is-type fixture-single 'single-float)
	    (is-type fixture-double 'double-float)
	    (is-type fixture-long   'long-float)
	    (subtest "Are all subtypes of FLOAT:"
	      (is-type fixture-short  'float)
	      (is-type fixture-single 'float)
	      (is-type fixture-double 'float)
	      (is-type fixture-long   'float))))))
    (subtest "CHARACTER and STRING types:"
      (let ((fixture-char-a #\f)
	    (fixture-char-b #\o)
	    (fixture-char-c #\o))
	(subtest (format nil "CHARACTERS are prefixed with \"#\\\" (EG):~@
			      ~@T- ~@C~@
                              ~@T- ~@C~@
                              ~@T- ~@C"
			 fixture-char-a
			 fixture-char-b
			 fixture-char-c)
	  (is-type fixture-char-a 'character)
	  (is-type fixture-char-b 'character)
	  (is-type fixture-char-c 'character)))
      (let ((fixture-string-foo "foo")
	    (fixture-string-bar "bar"))
	(subtest (format
		  nil
		  "Strings are encapsulated with double quotes (E.G):~@
                  ~@T- ~S~@
                  ~@T- ~S"
		  fixture-string-foo
		  fixture-string-bar)	  
	  (is-type fixture-string-foo 'string)
	  (is-type fixture-string-bar 'string))))))
(finalize)

Now for brewitiy if I would like to break file contents more like:

(subtest (format nil "Lisp types can be typed into two major categories:~@
                      ATOMIC TYPES and LISTS:")
  (subtest "The following types are called ATOMIC:"
    (subtest "NUMBER types such:"
      ;; RUN TESTS THAT RESIDE IN OTHER FILE FOR NUMBER TYPES
      )
    (subtest "CHARACTER and STRING types:"
     ;; RUN TESTS THAT RESIDE IN OTHER FILE FOR CHARACTER AND STRING TYPES   
     )))
(finalize)

I tried tampering with asdf -modules but the issue with them is that I cannot get the output and test order to preserve the topical hierarchy I'm aiming for.

Any tips? :D Anyone?

Hello there,

it would be nice to be able to split some of the code into other modules.

Looks like you think "one file = one module", are you ? But this is not necessary. I didn't get exactly what you want to break, but it seems to me you could just use several files, and place them into the same package. Write defpackage once, and (in-package #:master-class-test-types) in any file. They would just have to be declared in order in the .asd.

To discuss more, I suggest stack overflow/code review, since this isn't specifically about Prove.

Also, Rove by the same author is seen as the continuation of Prove. It is at least better at showing error traces, where Prove doesn't show much.

Ah, Thankyou! I'll check what you just suggested! :) The issue is not strictly about files needing to be separate modules, but rather how to split code over multiple files and retain the the output as it would've been produced by the non-modular code in the upper example (the output of tests having subtests of subtests where declared):

The lower part of the upper example:

 (subtest "CHARACTER and STRING types:"
      (let ((fixture-char-a #\f)
	    (fixture-char-b #\o)
	    (fixture-char-c #\o))
	(subtest (format nil "CHARACTERS are prefixed with \"#\\\" (EG):~@
			      ~@T- ~@C~@
                              ~@T- ~@C~@
                              ~@T- ~@C"
			 fixture-char-a
			 fixture-char-b
			 fixture-char-c)
	  (is-type fixture-char-a 'character)
	  (is-type fixture-char-b 'character)
	  (is-type fixture-char-c 'character)))
      (let ((fixture-string-foo "foo")
	    (fixture-string-bar "bar"))
	(subtest (format
		  nil
		  "Strings are encapsulated with double quotes (E.G):~@
                  ~@T- ~S~@
                  ~@T- ~S"
		  fixture-string-foo
		  fixture-string-bar)	  
	  (is-type fixture-string-foo 'string)
	  (is-type fixture-string-bar 'string))))

How to keep this subtest on it's original file while getting child subtests from another?

(subtest "CHARACTER and STRING types:"
   ;; The stuff that used to be here is now on different file
)

macros ?

or a simpler organization ;)

Simpler organization doesn't really cut it if the output must be a hierarchical list of outputs, i think? But that was the point of the original question. Which was to contemplate does Prove employ any direct feature for such? Therefore I find answers containing "change your specification for outcome" totally unhelpful (if I indeed gathered that correctly along the lines ;) ).
What would be a good source to find out information how to create such macros that would enable this structure? It's really all about learning!

Hmmm! Just encapsulated the needed subtests into a macro and that did the trick! Everything runs nice and smoothly! Thanks for the tip! The sheer malleability and flexibility of Lisp doesn't seize to amaze me! :)