racket / rackunit

Other
18 stars 34 forks source link

add check-within #95

Closed AlexKnauth closed 6 years ago

AlexKnauth commented 6 years ago

Solves #94.

This pull request adds check-within, which is like check-= except that it looks into structured data using equal?/within, which is defined in terms of equal?/recur. For example this check passes by looking into the lists:

(check-within (list (list 1.0) '() (list 2.0 3.0))
              (list (list 0.9999) '() (list 2.001 3.0))
              0.1)
AlexKnauth commented 6 years ago

(Re: 2, other data structures) The only data structures that might need a special case here are the ones that:

  1. have sub-parts but don't cooperate with equal?/recur when they compare their sub-parts, and
  2. those sub-parts can be numbers that would be interpreted as "good enough" even when they might be a little bit off.

(1) holds for strings, byte strings, regular expressions, flvectors, extflvectors, and fxvectors (and hash-tables with different keys: https://github.com/racket/rackunit/pull/95#issuecomment-412308811). However, strings and regular expressions don't contain numbers in the usual way, and byte string elements aren't usually interpreted as "good enough" when they're off by any amount, so (2) doesn't hold for byte strings. Both (1) and (2) hold for flvectors, which is why there's a case for it.

But fxvectors are a bit trickier. They contain numbers, but they can only contain discrete numbers, so I'm not sure whether (2) applies. I'm not sure whether most people using fxvectors would consider an element to be "good enough" if it were a bit off from what it should be.

AlexKnauth commented 6 years ago

(Re: 3, if it doesn't contain numbers) Then it compares everything within it with equal?:

> (check-within '(a (b #:x x) "this does not use numbers")
                '(a (b #:x x) "this does not use numbers")
                0.1)
;succeeds
> (check-within '(a (b #:x x) "this does not use numbers")
                '(a (b #:x x) "this dose not use numbers")
                0.1)
;--------------------
;. FAILURE
;name:       check-within
;location:   unsaved-editor:5:0
;params:
;  '((a (b #:x x) "this does not use numbers")
;    (a (b #:x x) "this dose not use numbers")
;    0.1)
;--------------------

The failure message could be better; I'll try to change it to say:

--------------------
. FAILURE
name:       check-within
location:   unsaved-editor:5:0
actual:     '(a (b #:x x) "this does not use numbers")
expected:   '(a (b #:x x) "this dose not use numbers")
--------------------

Update:

Done, this in now the failure message

AlexKnauth commented 6 years ago

(Re: 1, test case for flvectors) Done.

AlexKnauth commented 6 years ago

(Re: 2, other data structures)

I've found that (1) also holds for hash tables with different sets of keys, but not for hash tables with the same set of keys. That means this fails:

(check-within (hash 3 'a 10 'b)
              (hash 3.001 'a 10 'b)
              0.1)
;failure

But this succeeds:

(check-within (hash 'a 3 'b 10)
              (hash 'a 3.001 'b 10)
              0.1)

However, this makes sense because a hash-table key is not considered "good enough" if it's a little bit off, since it would be impossible to look up without the exact equal?-correct number.

AlexKnauth commented 6 years ago

@bennn What do you think about the fxvector issue? Would the elements of fxvectors be interpreted as "good enough" when they're a little bit off?

bennn commented 6 years ago

What do you think about the fxvector issue? Would the elements of fxvectors be interpreted as "good enough" when they're a little bit off?

I think no.

If there's a need for this, it'd be easy to add it later right?

AlexKnauth commented 6 years ago

Yes that's true. I'll work on documenting check-within this evening.

AlexKnauth commented 6 years ago

Added documentation.