Live data from Hacker News

Questions to ask yourself when writing tests

charemza.name

51–60 of 98 posts

Re: Questions to ask yourself when writing tests

#51
The most important thing here seems to be "For every part of my code change, if I break the code, will a test fail?". Or as I'd put it "if you break the code deliberately does the test actually fail?".

Seen quite a few tests in my time that don't capture the functionality they think they are. They pass but wouldn't be able to tell if the underlying functionality they capture is genuinely broken. This is why I guess the standard practice is to go test red before you go test green.

Re: Questions to ask yourself when writing tests

#52

The author does not cover any question related to application security. Things like is this parameter/input value properly sanitized, does this piece is/is not vulnerable to injection attacks, does this piece of code performs authentication/authorization checks? Is RBAC properly implemented for this method?

I agree with some cases, but "is this parameter/input value properly sanitized" is a bit weird. It should only every apply to a) the db framework, b) those N really weird cases that have to break the abstraction and don't use the db framework. If you have to test every input, then the problem is on a completely different level than missing a test.

Re: Questions to ask yourself when writing tests

#53
post #41
post #39

Earlier quoted context omitted.

> ... micro level unit testing, driven by people like Uncle Bob. "The structure of your tests should not be a mirror of the structure of your code. The fact that you have a class named X should not automatically imply that you have a test class named XTest." "The structure of the tests must not reflect the structure of the production code, because that much coupling makes the system fragile and obstructs refactoring.…

I really wish Uncle Bob would provide code examples with his blog posts and videos. I struggle to imagine what my tests would look like if I followed this. Possibly as my tests are so tightly coupled right now that refactoring is actually not possible in some cases. Does anyone know of explations of this with a more hands-on approach, or is this simply a collection of ideas that can’t really be shown?

I've been wondering about that for a while.

So far, I've not been able to find any examples of test architecture that follows those principles online or in my day job.

I've also been too lazy to do a side project and explore a more decoupled and scalable test suite. Maybe I should get off my arse and finally do it.

Re: Questions to ask yourself when writing tests

#54
Here are some more questions:

How much business value is this test adding? That is, if this test failed and we ignored it, how much would the business suffer?

Is the code easy to test? That is, does the design have lots of self-contained components with well-described input/outputs & conditions/assumptions? Do the docs clearly communicate that?

Will the test still work if we change the implementation? How much work to update/remove the tests if the behaviour has to change to follow new business requirements?

Re: Questions to ask yourself when writing tests

#55

Earlier quoted context omitted.

The problem is that, in my observation over a number of codebases with many developers: A lot of unit tests end up testing the implementation. When you go to refactor, these tests break which slows you down. To me it seems nearly impossible not to end up with these kinds of net negative tests when you follow a micro approach. I mean the approach outlined in books and blogs where you write a test and then write only a…

what's wrong with just deleting these now-irrelevant tests?

Nothing. Integration tests are your hypothesis/experiment. Unit tests are your lab setup.

Re: Questions to ask yourself when writing tests

#56
post #44
post #38

Earlier quoted context omitted.

> If more methods were written to not call out to disk or some external service (e.g., a database or API) and we had a main method that handled the external communication, then the unit tests would be much less fragile. I am not really following. You can write a seperate function that handles database query, then call this function in your code under test, or one of your argument in the code under test is the databse…

Rather than having 3 different business logic methods that call out to the database, you have each construct a command object and then have a separate service that calls out to the database based on these commands. You can then test the 3 business logic methods by testing that they construct the correct commands based on their parameters.

Yeah, exactly. To put it another way: get your business logic components to return data structures (a list of DB actions or an updated dict), and your core controller to turn those data structures into DB calls. Then your tests simply say: here’s a certain environment, what action do you think should be performed?

If you think this sounds like mocking, you’re right (it is like mocking, it isn’t mocking). It has the bonus of making it easier to inspect the logic & expose it to the user ("hey I’m about to do these things, does that sound ok to you?").

Re: Questions to ask yourself when writing tests

#57

Earlier quoted context omitted.

>Can I do this faster if I don’t write a test? The answer is always no. I think the answer is mostly no but it's dangerous to think that it's always no. I've been given many stories in the past for which writing a realistic automated test would have taken days, manual verification took minutes and the code was fairly isolated and did not get changed very frequently. Writing a test under those circumstances is actuall…

I would be very surprised if an automated test literally took days to write when a manual test is just minutes. Also the time savings still pay off later, as automated tests usually take seconds to run and there’s no training required - once it’s in the test suite and the test suite runs are automated, it will always run and quickly identify a failure - no “oops, we forgot to show Jim the Intern that he had to test t…

Let me help expand your imagination: what if the code is for sshing to prod and needs a ssh-agent or a password typed in? Would you leave those cress on your CI system? Would Security be happy with that?

Re: Questions to ask yourself when writing tests

#58

Earlier quoted context omitted.

The problem is that, in my observation over a number of codebases with many developers: A lot of unit tests end up testing the implementation. When you go to refactor, these tests break which slows you down. To me it seems nearly impossible not to end up with these kinds of net negative tests when you follow a micro approach. I mean the approach outlined in books and blogs where you write a test and then write only a…

what's wrong with just deleting these now-irrelevant tests?

You can delete them but the fact that they are irrelevant now even though you didn't change the behaviour of the software means that it was a waste of time writing them in the first place.

Secondly it decreases your confidence in the refactor. In a classic refactor, nothing should break. This is because a good set of tests are a way of documenting and verifying the design/behaviour of the system.

Finally, often in a codebase with micro tests, there will be an expectation that you replace one set of micro tests with another.

Re: Questions to ask yourself when writing tests

#59
post #38
post #27

Earlier quoted context omitted.

> I am so sick of having to code in extremely brittle codebases that are impossible to refactor because of the sheer volume of UTs that are tightly coupled to very specific implementation details I think this comes from "unit tests" where they have assertions such as assertThisOtherSpecificMethodNameWasCalledWithTheseSpecificallyNamedParameters If more methods were written to not call out to disk or some external ser…

> If more methods were written to not call out to disk or some external service (e.g., a database or API) and we had a main method that handled the external communication, then the unit tests would be much less fragile. I am not really following. You can write a seperate function that handles database query, then call this function in your code under test, or one of your argument in the code under test is the databse…

Then maybe just consider doing functional testing. Assertion code in a mock is, by definition, code that tests an implementation. In the example given, suppose you wanted to replace the database with a nosql version. Now you have to throw away or modify your tests even though the behaviour of your system has not changed

Re: Questions to ask yourself when writing tests

#60
post #47
post #40

Earlier quoted context omitted.

> can you expand on why this is bad? Because most of the time, it reduces "test precision". Which means when such a test detects an issue, there's now a bigger area of the code where the issue could be located. > Doesn't efficiency outweigh respecting feature boundaries in tests? In the end, what we're trying to minimize here is feature development time. This of course depends on the feedback loop duration (build + r…

> Because most of the time, it reduces "test precision". Which means when such a test detects an issue, there's now a bigger area of the code where the issue could be located. Tests are not a debug tool. Tests are here to tell you when you broke something. When this happen you can get your debugging toolbox out: stack traces, profilers and things like GDB. And then follow the steps your test script did.

All the projects I've most enjoyed working on had clear, explicit test failures, which almost always gave me enough information to hunt down what I'd broken and where. Obviously that's not realistic for some kinds of projects. But even in a legacy C project, if I had to pull out stack traces and profilers and GDB every single time I wanted to understand why a test failed, I would say I'm working in a pretty terrible codebase.
Post reply on HN