I was ambivalent on unit tests until I discovered how much the mere act of writing them was finding bugs. I very vividly remember writing a test for a ~40 loc class of pure functions. I started out thinking the exercise was a waste of time. This class is simple, has no mutable state, and should have no reason to change. Why bother testing it? By the time I was done writing the test I had found three major bugs in tha…
That reminds me of this time I wrote some code to add a method to Python string objects. The first reply to my issue on it in the bug tracker was "We shouldn't accept this, it's trivial to implement in your own code, see: XXXX". The second reply was "You have a bug in your implementation in the first reply." It took a couple years to be accepted.
The day I started believing in unit tests
221–230 of 269 posts
Re: The day I started believing in unit tests
#222Earlier quoted context omitted.
You could have watch the program and observed the failure, why need to write a test to be “surprised” it failed
A huge benefit of tests is their regression protection against future changes, often by other engineers. You don’t get that from ad hoc manual execution.
Re: The day I started believing in unit tests
#223Earlier quoted context omitted.
>1. It talks to a database. >3. It touches the file system. These are BS. Maybe they made sense in the beforetimes when when we didn't have Docker containers or SSDs, but nowadays there's no reason you can't stand up a mini test database as part of your unit test suite. It's way simpler than mocking.
100% this. A guy I work with just rebuilt our CI/CD pipeline and we're spinning up a database and all dependent services in containers. There are no mocks and it works great. In previous lives, I worked on tests that mocked everything. We spent more time creating and maintaining mocks than writing the actual tests.
Re: The day I started believing in unit tests
#224Earlier quoted context omitted.
100% this. A guy I work with just rebuilt our CI/CD pipeline and we're spinning up a database and all dependent services in containers. There are no mocks and it works great. In previous lives, I worked on tests that mocked everything. We spent more time creating and maintaining mocks than writing the actual tests.
I think those are still considered "integration" tests in the traditional way of thinking. The problem is that a lot of applications don't do much other than interact with external resources, to the point where isolated unit tests are rare or only cover non-critical code, while just about any substantive test is an "integration" test.
Re: The day I started believing in unit tests
#225Earlier quoted context omitted.
It matters enough that the question "does static typing dramatically reduce the benefits of unit testing" is an open question or at least seriously discussed in the industry. All other replies are about dynamic languages.
Having static types is like having an automatic, exhaustively comprehensive, efficient unit test generator for the classes of bugs whose units tests are the most boring and annoying to write and maintain. Static types don't prevent you from needing unit tests, they free you up to focus on writing tests that are actually interesting.
Re: The day I started believing in unit tests
#226Earlier quoted context omitted.
> End-to-end tests are unit tests, generally speaking. Generally, in the software industry, those terms are not considered the same thing, they are at opposite ends of a spectrum. Unit tests are testing more isolated/individual functionality while the end to end test is testing an entire business flow. Here's an example of one end to end test (with validations happening at each step): 1-System A sends Inventory avail…
> Here's an example of one end to end test Bad example, perhaps, but that's also a unit test[1]. Step 8 is dependent on the state of step 1, and everything else in between, so it cannot be reduced any further (at last not without doing stupid things). That is your minimum viable unit; the individual, isolated functionality. [1] At least so long as you don't do something that couples it with other tests, like modifyin…
Typically, in end to end testing, tests are run within the same shared QA system and are semi-isolated based on choice of specific data (e.g. customers, products, orders, vendors, etc.). If this test causes a different test to fail, or vice-versa, then you have found a bug.
If we call that entire sequence of steps a "unit" test, would you start with testing the entire sequence of steps, or would you recommend testing the individual steps first?
And if we did test the individual steps first, we would give that testing a different name? Like maybe "sub-unit" testing?
Re: The day I started believing in unit tests
#227I was ambivalent on unit tests until I discovered how much the mere act of writing them was finding bugs. I very vividly remember writing a test for a ~40 loc class of pure functions. I started out thinking the exercise was a waste of time. This class is simple, has no mutable state, and should have no reason to change. Why bother testing it? By the time I was done writing the test I had found three major bugs in tha…
Was this statically or dynamically typed language?
Re: The day I started believing in unit tests
#228Earlier quoted context omitted.
> Here's an example of one end to end test Bad example, perhaps, but that's also a unit test[1]. Step 8 is dependent on the state of step 1, and everything else in between, so it cannot be reduced any further (at last not without doing stupid things). That is your minimum viable unit; the individual, isolated functionality. [1] At least so long as you don't do something that couples it with other tests, like modifyin…
Every step updates shared databases (frequently plural). In the case of the fulfillment step, the following systems+databases were involved: ERP, WMS, Shipping. Typically, in end to end testing, tests are run within the same shared QA system and are semi-isolated based on choice of specific data (e.g. customers, products, orders, vendors, etc.). If this test causes a different test to fail, or vice-versa, then you ha…
That's fine. It all happens within a single unit. A unit should mutate shared state within the unit. Testing would be pretty much useless without.
> If we call that entire sequence of steps a "unit" test, would you start with testing the entire sequence of steps, or would you recommend testing the individual steps first?
For all intents and purposes, you can't test the individual steps. All subsequent steps are dependent on the change in inventory state in step 1. And the product of step one is undoubtedly internal state, so there is no way for the test to observe the state change in isolation (unless you do something stupid). You have to carry out the subsequent steps to be able to infer that the inventory was, in fact, updated appropriately.
After all, the whole reason you are testing those steps together is because you recognize that they represent a single instance of functionality. You don't really get to choose (unless you choose to do something stupid, I suppose).
> And if we did test the individual steps first, we would give that testing a different name?
If the individual steps can be tested individually (ignoring a case of you doing something stupid), it's not actually and end-to-end process, so your example would make no sense. Granted, we have already questioned if it is a bad example.
Re: The day I started believing in unit tests
#229Earlier quoted context omitted.
Was this statically or dynamically typed language?
I don't think it really matters. Major bugs are not "oh this can be null", major bugs are "this combination of preconditions yield a business logic edge case that wasn't accounted for". Static typing doesn't really help more than dynamic typing in these cases.
Not true. Even today the majority of security bugs are simple buffer overflows, for example. The subtle bugs are more memorable, but that doesn't mean they're actually more common.
> major bugs are "this combination of preconditions yield a business logic edge case that wasn't accounted for". Static typing doesn't really help more than dynamic typing in these cases.
It absolutely does, if you put a little bit of effort into actually using it. Represent your business logic invariants in the type system, then the compiler won't let you accidentally violate them.
Re: The day I started believing in unit tests
#230Earlier quoted context omitted.
I don't think it really matters. Major bugs are not "oh this can be null", major bugs are "this combination of preconditions yield a business logic edge case that wasn't accounted for". Static typing doesn't really help more than dynamic typing in these cases.
>"this combination of preconditions yield a business logic edge case that wasn't accounted for". Static typing doesn't really help more than dynamic typing in these cases. Depends on the language and the business logic. Types are a way of specifying preconditions and postconditions; a more expressive type system lets you rule out more edge cases by making illegal states unrepresentable. In particular, I'm pretty sure…