-
Notifications
You must be signed in to change notification settings - Fork 9
Description
A case that came out of testifying the cc rules that Pedro ran into was needing to verify the last element of a collection. The position mattered because it was checking the linker args, which is important in C++.
He was also checking the collection contains some other values, so the resulting code to do that and check the last element was cumbersome. Something like:
libs = <construct libs>
expect.that_collection(libs).contains_at_least(...)
expect.where(...).that_str(libs[-1]).equals(...)
This would be slightly more ergonomic by having a contains_at method, which checks both the value and offset:
libs = expect.that_collect(<construct libs>)
libs.contains_at_least(...)
libs.offset(-1).equals(...)
This allows an error message like:
expected: foo
got: bar
where
offset=-1
within list:
0: a
1: bar
(A nicer message like "got wrong value at offset -1" would require some changes to how context is recorded and displayed, which would be nice, but out of scope for this FR)
The name can be bikeshed a bit:
index(): not an option; lists already have an index function which return the position of
the argument, so using that name with a different behavior would be confusingelement_at(): slightly more fluenty, but much longer than offsetoffset(): short, and relatively clearget(): analogous to Java lists and maps. But could be confused with maps, and not really
a common term for getting an element from a list.
There were a couple other ideas to solve this problem; I'll note them for completeness:
contains_at()method: it doesn't compose as well; checking that the string matched
e.g. "foo_*.o" would be a bit more cumbersome. I'll note that havingoffset()makes
implementing a conveniencecontains_at()very simple.- A way to include the position when checking, similar to how DictSubject.contains_exactly()
includes checking the keys. Maybe aCollectionSubject.items()method, or an include_offset
arg for contains_at_least(), or anfoo.enumerated()method? And then you assert on the 2-tuples of (position, value).
Another idea was a specialized contains_at() method, but this doesn't compose as well. In Pedro's case, he was using equals, but it's easy to imagine needing to match a pattern like "foo_*.o" or some such.