fukamachi / prove

Yet another unit testing framework for Common Lisp
218 stars 23 forks source link

How to test contents from another file? #55

Closed 4lph4-Ph4un closed 6 years ago

4lph4-Ph4un commented 6 years ago

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.

4lph4-Ph4un commented 6 years ago

Any tips? :D Anyone?

vindarel commented 6 years ago

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.

4lph4-Ph4un commented 6 years ago

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
)
vindarel commented 6 years ago

macros ?

or a simpler organization ;)

4lph4-Ph4un commented 6 years ago

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!

4lph4-Ph4un commented 6 years ago

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! :)