Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>You test case is more useless than a turd in the middle of the dining room table unless you put a comment in front of it that explains what it assumes, what it attempts, and what you expect to happen as a result.

This is why I found Gherkin/Cucumber (and BDD in general) to be a total revelation when I first encountered it. No one should be writing tests any other way IMO.

https://cucumber.io/docs/gherkin/reference/



Gherkin/Cucumber reintroduce the very problem TDD/BDD was intended to solve: Documentation falling out of sync with the implementation.

The revelation of TDD, which was later rebranded as BDD to deal with the confusion that arose with other types of testing, was that if your documentation was also executable the machine could be used to prove that the documentation is true. The Gherkin/Cucumber themselves are not executable and require you to re-document the function in another language with no facilities to ensure that the two are consistent with each other.

If you are attentive enough to ensure that the documentation and the implementation are aligned, you may as well write it in plain English. It will give you all of the same benefits without the annoying syntax.


TDD wasn't rebranded BDD.

BDD is a QA concern, primarily used for QA tests against a written (BDD) requirement.

TDD is about unit testing, which is about testing the implementation BY developers FOR other developers.

TDD says nothing about the correctness of the software against a spec, only that a given implementation aligns with a developer's intention.


If unit tests are not testing the behaviour, it's being done wrong.

If they are, the only difference between TDD and BDD is where, in which form, and by whom is that behaviour defined.


Unit tests assert implementation behaviour to aid refactoring. If developers misunderstand the spec, the unit tests can be valid. They don't assert developer understanding.

Say it with me, unit tests are to aid refactoring.

If we mix QA and implementation details just because both sides use the word "test" it ends in trouble.

QA should be blind to unit test coverage or even usage at all, they're totally independent concerns.

A passing unit test says nothing against correctness of product against a spec or design... only that it works and continues to work as a developer intended, to aid the work of future developers, even if they misunderstood the spec.

Your comment is at the core of why QA is a total mess. Everyone is confused about what "test" means in different contexts.

Why have a QA function at all with 100% unit test coverage? Because the unit tests may encode misunderstanding by developers. They're there to fight entropy, not wrongness.

QA, using BDD and other tools, ensure the product is correct, regardless of how well it fights entropy by unit tests.


Unit tests (class or method as the unit) hinder refactoring by binding to low level implementation details. When you refactor, by definition you are changing what the factors (units) are. Generally, your unit tests will then be testing implementation details that no longer exist. By strongly coypling to implementation details, unit test suites suffer an extremely large ripple effect on refactoring.

Tests in general can only help you refactor code at a lower level of granularity than what you are testing. Something lower than unit level is a contradiction.

Of course, you can instead test business behavior which isn't as volatile in refactoring and change your definition of unit to be a unit of practical business requirements...


If a unit test covers function f(a,b) to ensure it always returns the right answer in the domain of a,b

But a developer looks at f(a,b) and realises a new implementation could be 10x faster.

The developer re-writes the function, the tests still pass. Without that test they couldn't be sure their rewrite didn't break the expected behaviour.

What you're talking about is changing interfaces and structure when refactoring. Yes, unit tests can make that more painful. But you bin your old tests and write new ones.

If your unit tests are not cheap to dispose of, run or rewrite ... that's your core problem.

If your unit tests are not testing discrete units, instead testing the combined behaviour of many units (the re-factoring of structure pain) ... then you have bigger issues than the tests; namely understanding the difference and applicability between unit and integration tests.


> If your unit tests are not testing discrete units, instead testing the combined behaviour of many units

This is a very naive idea of unit tests. In the real world applications have a dependency hierarchy with more than two levels. If you want to test anything other than the leaves in that hierarchy you are by definition testing the behaviour of many units.

Sounds like what you're saying is that unit tests are only applicable to leaves in the dependency hierarchy. I could agree with that, but that's not what the world describes as unit tests. That would also make unit tests quite useless.


> Thay would also make unit tests quite useless

Not so. Their use is to aid refactoring of those nodes. Also the leaf node can contain calls to other code (leafish) if that code too is unit tested.

They're the sum of their parts.

Integration tests used lightly to test specific integration occurs (ie f() not only meets X constraint but calls y() in a certain way to do so) if that's important.

The fact that most codebases unit tests are a fragile mess, and that many devs find tests a burden highlights just how poorly the topic is understood.


> Their use is to aid refactoring of those nodes

Sure. But there are codebases where leaves are less than 20% of the code. Yet testing preachers are saying that unit tests are the most important part (e.g. Martin Fowler's Testing Pyramid). Though again, they use a different definition of unit tests: everything is a unit if you mock enough.

> how poorly the topic is understood

Well, at least one of the reasons is that people focus too much on test classification. You need to decide what is important to test, how is just implementation detail. If that's your approach, you'll realize that you're getting the most value from integration tests. The only downside to this is losing Testing Church membership. But that happens when you apply logic and reason.

Instead, everybody decides that "we write unit tests", without thinking what needs to be tested and recognizing limitations of unit tests.


>Your comment is at the core of why QA is a total mess. Everyone is confused about what "test" means in different contexts.

Particularly the important differences between unit, integration, and e2e testing. Many people use the words interchangeably when they are completely different concerns.

Unit test your library code that has no external dependencies, integration test your classes that implement those libraries, and e2e test your application that is built with those classes. There are varying philosophies to which are more useful, but it's an important distinction to maintain in terminology.


This sounds like a good theory but the practice of it is really hard. Pretty quickly you end up with tests that "say" one thing but have nuanced different behavior in the underlying implementation.

Then try to debug a "document"...

I like the idea. But having tried it at scale, it becomes a mess. Code I can understand. I can read English comments. I can't debug English.


We have it at scale, and no, it doesn't become a mess.

We use Spock, which make "comments" a very expected thing, which helps us not let tests without comments pass a code review.

Just use a tool that helps you and stop writing stupid tests whose impl code looks worse than the code being tested.



Then why all the comments?

I know what typical code does. This code looks simple but that's misleading when you're trying to understand a failure. You want consistency and clarity. You want readablity like code is readable not like a book is readable.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: