Skip to content
This repository has been archived by the owner on May 23, 2022. It is now read-only.

Commit

Permalink
Better reporting for rejected properties.
Browse files Browse the repository at this point in the history
This helps with #20 and #15. As for the latter, I still don't know whether to provide special handling for assertion-based tests or not.
  • Loading branch information
robotlolita committed Apr 21, 2013
1 parent 560991f commit e457718
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 45 deletions.
53 changes: 27 additions & 26 deletions src/check.ls
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,15 @@ with-defaults = (config = {}) -> ({} <<< default-config) <<< config
# Retrieves a normalised Status tag for the Result.
#
# :: Result -> ResultStatus
status = (result) ->
| result.ok is true => \passed
| result.ok is false => \failed
| result.ok instanceof Error => \errored
| otherwise => \ignored
status = (result) -> result.kind or \rejected


#### λ failed-p
# :internal:
# Checks if a Result failed.
#
# :: Result -> Bool
failed-p = (result) -> (status result) in <[ failed errored ]>
failed-p = (result) -> (status result) in <[ failed rejected ]>


### -- Helpers for presenting a Report ---------------------------------
Expand Down Expand Up @@ -156,22 +152,27 @@ label-histogram = (report) ->
# :: Report -> String
describe-failures = (report) ->
label = (as) ->
| as.length => ": The following labels were provided: #{JSON.stringify as}"
| as.length => "» The following labels were provided: #{JSON.stringify as}"
| otherwise => ''

error-for = (a) ->
| a instanceof Error => ": Threw #{a.stack or a}\n"
| otherwise => ''
error-for = (kind, e) ->
| kind is \failed => "» Threw #{e?.stack or e}\n"
| otherwise => ''

arg = (a, n) -> " #n - #{a.value} (#{a.generator})"

arg = (a, n) -> " #n - #{JSON.stringify a.value} (#{a.generator})"

rejection-for = (kind, e) ->
if kind != \rejected => ''
else => "» Reason: #{JSON.stringify e.value}\n"

errors = report.failed.map (a, n) -> """
: Failure \##{n + 1} --------------------
#{label a.labels}
#{error-for a.ok}
: The following arguments were provided:
#{a.arguments.map arg .join '\n '}
"""
: Failure \##{n + 1} -----------------------------------------------------------
#{rejection-for a.kind, a}
#{label a.labels}
#{error-for a.kind, a.value}
» The following arguments were provided:
#{a.arguments.map arg .join '\n '}
"""
switch
| errors.join '' .trim! => errors.join '\n---\n'
| otherwise => ''
Expand Down Expand Up @@ -225,10 +226,10 @@ Report = Base.derive {
@all.push result
result.labels.map (a) ~> @labels.[]"#a".push result
switch status result
| \passed => @passed.push result
| \failed => @failed.push result
| \errored => @failed.push result
| \ignored => @ignored.push result
| \held => @passed.push result
| \failed => @failed.push result
| \rejected => @failed.push result
| \ignored => @ignored.push result

##### λ to-string
# Provides a human-readable presentation of this Report.
Expand Down Expand Up @@ -263,10 +264,10 @@ check = (max, property) -->
report.add result

switch status result
| \passed => --max
| \failed => should-run = false
| \errored => should-run = false
| \ignored => if ++ignored > 1000 => should-run = false
| \held => --max
| \rejected => should-run = false
| \failed => should-run = false
| \ignored => if ++ignored > 1000 => should-run = false

report.verdict = | ignored > 1000 => \abandoned
| max > 0 => \failed
Expand Down
70 changes: 51 additions & 19 deletions src/property.ls
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,49 @@
### -- Aliases ---------------------------------------------------------
frozen = Object.freeze


### -- Property result types -------------------------------------------

#### λ make-result
# Constructs a Result object.
#
# :: String -> [a] -> [String] -> Maybe Bool -> Result
make-result = (kind, value, args, labels) -->
kind : kind
value : value
labels : labels
arguments : args


#### λ invalidate
# Invalidates the property for the given arguments (they're not valid).
#
# :: [a] -> Result
invalidate = (args) -->
make-result \ignored, null, args, []


#### λ hold
# Constructs a Result for a successful property.
#
# :: [a] -> [String] -> Result
hold = make-result \held, true


#### λ reject
# Rejects the property with the given reason.
#
# :: [a] -> [String] -> Result
reject = make-result \rejected


#### λ fail
# Constructs a Result for a failed property (one that errored out).
#
# :: [a] -> [String] -> Result
fail = make-result \failed


### -- Helpers ---------------------------------------------------------

#### λ values
Expand All @@ -57,34 +100,23 @@ classify = (args, prop) -->

#### λ verify
# Verifies if the property's invariant's hold for the arguments.
# :: [a] -> Property -> Bool
verify = (args, prop) -->
# :: [a] -> [String] -> Property -> Bool
verify = (args, labels, prop) -->
try
!!(prop.invariant ...(values args))
result = prop.invariant ...(values args)
if result is true => hold args, labels
else => reject result, args, labels
catch e
e

#### λ invalidate
# Invalidates the property for the given arguments (they're not valid).
# :: [a] -> Property -> Result
invalidate = (args, prop) -->
make-result args, [], null
fail e, args, labels


#### λ apply-property
# Applies a property to some arguments.
# :: [a] -> Property -> Result
apply-property = (args, prop) -->
| valid-p args, prop => make-result args, (classify args, prop), (verify args, prop)
| otherwise => invalidate args, prop
| valid-p args, prop => verify args, (classify args, prop), prop
| otherwise => invalidate args

#### λ make-result
# Constructs a Result object.
# :: [a] -> [String] -> Maybe Bool -> Result
make-result = (args, labels, ok) -->
ok : ok
labels : labels
arguments : args

### -- Core implementation ---------------------------------------------

Expand Down

0 comments on commit e457718

Please sign in to comment.