Open rickeylev opened 1 year ago
Another way to do this would be to support a NoneSubject
because quite often None
is a special value from the business logic point of view and it is definitely not an int
or str
. Maybe doing env.expect.that_<foo>(actual).is_none()
would be also good. If we were not using fluent APIs we could just do env.expect.is_none(actual)
.
That said supporting None
in the equals
method is important as well from API ergonomics point of view.
See #93 for more details, but why not just solve it with a generic Optional
type?
IMO it should be an error to have a none value for something you've declared as a string. If you want that to be possible, it should be declared as a subjects.optional(subjects.str)
def optional(factory):
def new_factory(value, *, meta):
# Optimisations could be done here to just pull all the methods from the parent and add the method is_none()
def some():
if value == None:
meta.add_failure("Wanted a value, but got None", None)
return factory(value, meta = meta)
def is_none():
if value != None:
meta.add_failure("Wanted None, but got a value", value)
return struct(some = some, is_none = is_none)
Support for None is very spotty. I think IntSubject supports it, maybe string, but not all of them. None doesn't happen much in rule code per-se, more so in utility functions. It's common enough that not having this makes using rules_testing a bit of a pain.
So implement allowing a None as the actual value and having None passed to equals() and not_equals(). Basic support should be pretty easy (i.e. just asserting None on a None value). Handling a None actual value for all the other assertions might be more involved -- almost all of them assume they are working with a non-None value. We can start with basic and go from there, though.
Subjects to update: