6 ms·
Precisely: Better assertions for Python tests
- tom_mellior 6y agoThe original title is "Precisely: better assertions for Python tests", and it's far superior to the one submitted here.
- fnord123 6y agoUnfortunately that is a misleading headline since these are not better assertions for Python tests. These appear to be an attempt to infect Python code with pointless verbosity found in AssertJ or Hamcrest for Java.
- calpaterson 6y agoIt would be great if they could go into more detail on what they've improved over pyhamcrest (https://github.com/hamcrest/PyHamcrest https://github.com/hamcrest/PyHamcrest) which I do use on occasion when there is no other easy way to write a good matcher. That said though, pytest's assertion rewriting goes a long way towards making hamcrest-style assertions redundant. But not completely.
- BerislavLopac 6y agoDo you have an example of the "not completely" case?
- calpaterson 6y agoIt's still not that easy to assert on some of the keys in a dict but not others, especially if you only want to assert on some of the keys nested inside that key, and so on. There are a few other cases that perhaps don't come to mind straight away, many to do with having complex rules for what is allowed to be in another thing.
- BerislavLopac 6y agoI'm not sure what do you mean exactly... If it's something like: assert foo["bar"] == 123 assert foo["baz"]["bam"]["boo"] = "abc" I don't see how is that made easier (and less ambiguous) in hamcrest-style assertions...
- calpaterson 6y agoThe case is more like when you want to assert against some of the contents of a dictionary but not all (say 60% of a 30 key dict), and not all those assertions are based on == (and it's a multilevel nested dict). There's no particurly terse why to write an example I'm afraid.
- mwilliamson 6y ago(I'm the author of precisely) Better error messages was the motivation: PyHamcrest tends to put everything onto one line, which makes it hard to discern structure. In contrast, precisely tries to produce an error message that uses line breaks and indentation to match the structure of the matcher, hopefully making it clear exactly which part of the matcher has failed.
- neolog 6y agoThat sounds like a feature PyHamcrest could add. Did you try adding it there?
- olau 6y agopytest assertion rewrite in the standard Python library would be really, really nice. I don't think the standard lib gets enough love.
- wodenokoto 6y agoWhy choose preceisely over assert all([el in result for el in ['A', 'B']]) There is definitely room for more brainfarts in the above, but introducing a new library with its own semantics into a team also have its costs.
- BerislavLopac 6y agoThis example doesn't test for absence of any other elements, so it's not as precise. That said, I largely agree with you - checking for this exact example from the README file works much better (and IMO more readable) as: assert set(result) == {"a", "b"} The precisely example doesn't even check if the result is a list, so it can be anything.
- quietbritishjim 6y agoThat is better, but doesn't check for incorrectly repeated elements: result = ["a", "b", "b"] assert set(result) == {"a", "b"} In fact that is the first main motivating failure case discussed in the readme. But actually that's simple enough to deal with too: from collections import Counter assert Counter(result) = {"a": 1, "b": 1} But would be trickier for mutable / unhashable types (not sure if "precisely" can deal with those).
- mwilliamson 6y agoYup, precisely should work fine with mutable / unhashable types -- it just relies on equality to check the elements in an iterable. More specifically, writing: contains_exactly("a", "b") is equivalent to: contains_exactly(equal_to("a"), equal_to("b"))
- oli5679 6y agoTo avoid repetitions, can you do this? assert sorted(result) == sorted(['a','b'])
- quietbritishjim 6y ago
- deleted 6y ago[deleted]
- whalesalad 6y agounittest already has a lot of really helpful assertions - I just wish they were more accessible outside of a standard class-based tests. https://docs.python.org/3/library/unittest.html https://docs.python.org/3/library/unittest.html I tend to try and lean on the language as much as possible before pulling in libraries like this. This is the sort of thing that you end up regretting a year or two later when the author abandons the project and you can no longer get help for bugs. Unlike vanilla language assertions, you won't need to rewrite your entire test suite when that situation inevitably comes up. pytest will give you really awesome feedback with vanilla/basic 'assert x in y' statements
- zoozla 6y agoMany years ago I wrote https://github.com/elifiner/affirm https://github.com/elifiner/affirm which replaces the built-in assert statement and provides similar (?) benefits without changing the syntax.
- crazypython 6y agoSee also: https://github.com/Parquery/icontract https://github.com/Parquery/icontract