Live data from Hacker News

Multiple assertions are fine in a unit test

stackoverflow.blog

81–90 of 348 posts

Re: Multiple assertions are fine in a unit test

#81

Things I find awkward with unit test (and it might just be me) is Inwant to write a test like def testLotsOfWaysTofail(): d = {"Handle Null": (None, foobar), "Don't allow under 13 to do it": (11, foobar), "or old age pensioner": (77,wobble)} for ... generate a unit test dynamically here I have built metaclasses, I have tried many different options. I am sure there is a near solution. But I never seem to have it right

isn't this just a parametrized test? or do you want to generate the test cases automatically like in property-based testing?

Re: Multiple assertions are fine in a unit test

#82

First off, I do put more than 1 assertion in a test. But it definitely leads to situations where you have to investigate why a test failed, instead of it just being obvious. Like the article, I test 1 thing per test, but sometimes that means multiple assertions about the outcome of a test. IMO there's no point in checking that you got a response in 1 test, and then checking the content/result of that response in anot…

> IMO there's no point in checking that you got a response in 1 test, and then checking the content/result of that response in another test. The useful portion of that test is the response bit. If I understood this part correctly, you are making the dangerous assumption that your tests will run in a particular order.

...which is why it may be worthwhile to chain some assertions together in a single test.

Re: Multiple assertions are fine in a unit test

#83
post #33

Earlier quoted context omitted.

If you’re using pytest you just paramaterize the tests and it tells you the exact failing case. Seems to be a basic feature I would be surprised to know doesn’t exist across almost all commonly used frameworks.

We are using unittest. But thanks for bringing it up, it seems it also has "subtest" support, which might be easier than interpolating the error message in some cases: https://docs.python.org/3/library/unittest.html#distinguishi...

There is also `parameterized` [1] if you want to do it by using decorators.

[1]: https://pypi.org/project/parameterized/

Re: Multiple assertions are fine in a unit test

#85
post #53

Earlier quoted context omitted.

Are there any "rules" in Clean Code that don't need to be disregarded and burned? https://qntm.org/clean

There's plenty of sensible advice in there it's just that he argues for the sensible stuff and the idiotic stuff with equal levels of conviction and if you are junior you aren't going to be able to distinguish them. It would be easier if it were all terrible advice.

Fortunately you readily find the good advice in lots of other places, so you can simply ignore that book.

Re: Multiple assertions are fine in a unit test

#86
post #33

Earlier quoted context omitted.

If you’re using pytest you just paramaterize the tests and it tells you the exact failing case. Seems to be a basic feature I would be surprised to know doesn’t exist across almost all commonly used frameworks.

We are using unittest. But thanks for bringing it up, it seems it also has "subtest" support, which might be easier than interpolating the error message in some cases: https://docs.python.org/3/library/unittest.html#distinguishi...

> We are using unittest.

Unless you need the library style in order to drive it, switch to pytest. Seriously.

- assert rewriting is stellar, so much more comfortable than having to find the right assert* method, and tell people they're using the wrong one in reviews

- runner is a lot more practical and flexible: nodeids, marks, -k, --lf, --sw, ...

- extensions further add flexibility e.g. timeouts, maxfail, xdist (though it has a few drawbacks)

- no need for classes (you can have them, mind, but if functions are sufficient, you can use functions)

- fixtures > setup/teardown

- parameterized tests

Re: Multiple assertions are fine in a unit test

#87

> The excellent book xUnit Test Patterns describes a test smell named Assertion Roulette. It describes situations where it may be difficult to determine exactly which assertion caused a test failure. How is that even possible in the first place? The entire job of an assertion is to wave a flag saying "here! condition failed!". In programming languages and test frameworks I worked with, this typically includes providi…

    it('fails', async () => {
      expect(await somePromise()).toBe(undefined)
      expect(await someOtherPromise()).toBeDefined()
    })
No chance figuring out where it failed, it's likely just gonna run into a test suite timeout with no line reference or anything.

Re: Multiple assertions are fine in a unit test

#88
post #40

Earlier quoted context omitted.

Which ones? I’ve used at least a dozen at this point, across C++, C#, JavaScript, Rust — and all of them throw (the equivalent of) exceptions on assertion failures.

GoogleTest (C++) and Go's built-in testing framework both support non-fatal assertions. They're used for code like this: assert_eq(list.len(), 1) expect_eq(list[0].username, "jdoe") expect_eq(list[0].uid, 1000) The idea being that if multiple properties are incorrect, then all of them will be printed out to the test log.

That seems like it'd easily get confusing, when the assertions are dependent. Which is often the case e.g. if the list is empty, testing the properties of the first item make no sense.

Re: Multiple assertions are fine in a unit test

#89

> The excellent book xUnit Test Patterns describes a test smell named Assertion Roulette. It describes situations where it may be difficult to determine exactly which assertion caused a test failure. How is that even possible in the first place? The entire job of an assertion is to wave a flag saying "here! condition failed!". In programming languages and test frameworks I worked with, this typically includes providi…

I remember writing a small .NET test library for that exact problem - You could pass in a lambda with a complex condition, and it evaluated every piece of the expression separately and pretty printed what part of the condition failed.

So essentially you could write

     Assert(()=>width>0 && x + width 
And you would get:

      Assertion failed: 
      x is 1500
      width is 600
      screenWidth is 1920

It used Expression to do the magic. Amazing debug messages. No moralizing required.

This was a huge boon for us as it was a legacy codebase and we ran tens of thousands of automated tests and it was really difficult to figure out why they failed.

Post reply on HN