HN user

aslakhellesoy

208 karma

[ my public key: https://keybase.io/aslakhellesoy; my proof: https://keybase.io/aslakhellesoy/sigs/QiIxtNJgabxTzT60tpDF7_R49Yjh3KWwPI36dgijwDw ]

Posts4
Comments61
View on HN

Browser-monkey is awesome, and for a real project I'd consider using it. I'd also use a virtual dom UI library like Vue, React, Hyperdom or similar.

For a teaching example I think it's essential to reduce the number of external libraries, or else it's too much to take in.

You and I have very different opinions on the purpose of TDD. You're presuming it's a design technique - many do. For me, TDD is all about validating a design in a way that gives me faster and better feedback than if I were just coding. I design the code before I write the first test. In fact, my test is derived from the design.

First I sketch a rough implementation design on a napkin or whiteboard. I don't worry about making it perfect, just good enough to create an initial mental model, and perhaps discuss it with someone.

Then, I write a test to express how I would like to interact with a small area of an implementation of this design, typically by calling a function or method and expressing a desired outcome.

I use the feedback from the test to drive out some simple code that resembles the design I sketched. If at any point this becomes hard, I take that as a clue that my napkin design can be improved, so I go back and tweak it.

Then I start over again. This is a quick cycle, typically 10 minutes or so. I get constant feedback on my design as well as my implementation.

I don't design code with TDD. I design code exactly the same way people who don't to TDD do it. Through intuition and experience. This is a skill, not a process. I only write tests to validate my design (not my implementation). Of course, because they are tests, they automatically validate my code as well, but that is not why I am doing it. If I only cared about testing, I might as well write them last.

More often than not my designs are imperfect, but by doing TDD I always improve them significantly, with relatively little time and effort.

It's taken me 15 years to get decent at it, and I'm still learning new techniques and abandoning others. There are many tricks to be learned. I usually only TDD when I care about the design. Quite often I don't, and then I just hack. I'm simply making a choice between going very fast now or going reasonably fast in a year. I haven't found a way to do both yet.

I gave a presentation called Testable Software Architecture [1] a week ago with very similar recommendations to this article.

Decoupling is essential in order to have fast, maintainable tests that give you confidence to deploy continuously.

My two favourite techniques for this is a ports&adapters architecture where we plug in fake adapters for the majority of the tests. We then use contract tests to be confident that the fakes behave the same as the real services.

[1] https://skillsmatter.com/skillscasts/8567-testable-software-...

Disclaimer: I'm the creator of Cucumber.

The biggest problem with Cucumber is that most people trying it out don't understand what it is.

Cucumber is not a tool for testing software. It is a tool for testing people's understanding of how software (yet to be written) should behave.

Most bugs and delays caused by rework arise from misunderstandings, and this is the problem Cucumber aims to solve.

Cucumber is a tool that facilitates collaboration and software design (especially domain-driven design).

Here is how it works: You pop a story off your backlog and run a 20 min. meeting (Discovery Workshop) with business folks (BAs, POs, domain experts) and IT folks (developers, UX, testers if you have them).

You have a conversation about the story and come up with some concrete examples to describe the various acceptance criteria for your stories. Not in Cucumber's Gherkin language - just in plain conversational language.

For example: "The one where I upload a picture that is too big". Or: "The one where there are five taxis in range". These conversations act as catalysts to uncover subtle details where business and IT might have a different understanding.

Two things can happen at the end of this short meeting. You ask people to do a thumbs-up or thumbs-down vote on whether they understand everything that needs to be done, and whether the story is small enough. If enough people give a thumbs down, you send the story back for further analysis, maybe breaking it up into something smaller. If it's mostly thumbs-up, you're good to go.

After the 20 min. meeting you have 2-5 concrete examples that a developer (and perhaps a tester) can flesh out in more detail using Gherkin (Given-When-Then) to make it even more concrete. For example:

  Scenario: Close taxis with higher rating win 
    Given taxi A with rating 0.8 is 1400m from the customer
    And taxi B with 0.9 is 1500m from the customer
    When the customer requests a taxi
    Then taxi B should be assigned
The dev shows the example to the business person, who confirms that this is right (or wrong).

Now, the developer follows the regular TDD workflow, using the Scenario to guide the development of the core domain logic. The Cucumber scenario doesn't go through a UI using Selenium WebDriver or similar. The domain logic is implemented in such a way that external services, message queues and databases are stubbed out.

Lower level unit tests are still written, and there are far more of those than Cucumber Scenarios.

Cucumber is there to make sure you write the right code.

Unit testing tools are there to make sure you write the code right.

Using UI testing tools together with Cucumber? Please don't - or at least do it very sparingly. UI tests are expensive to maintain (the UI is more volatile than your core domain). They are slow (2-3 orders of magnitude slower than test talking directly to the domain logic). And finally - when they fail they don't tell you where the bug is.

The purpose of Cucumber is to bridge the communication gap between business and IT by providing a small set of essential scenarios to illustrate core behaviour of unwritten software. These scenarios do become regression tests, but their real value is to prevent defects by uncovering bad assumptions up-front. You end up with executable, living documentation accessible to everyone on the team. -Documentation of how the software should behave - and how it actually behaves.

I use 't' all the time to look up files as well.

I guess this extension makes it easier to get an overview of the directory structure, but that's something I rarely need.

I'm sceptical of browser plugins in general. There are so many browser plugins that change under the hood and do malicious things. It would be easy for the author of this plugin to scrape all your source code and phone it home.

I completely agree with you that the most important value with BDD and Specification by Example happens during conversations at a whiteboard.

Cucumber/Fit/high level tests aren't fundamentally less refactorable. They have a looser coupling to code than unit tests, so when the production code is refactored they are less affected than xUnit tests.

The problem most people make is that they are trying to cover too much with Cucumber. And they use it solely as an automation tool without any collaboration whatsoever. That doesn't work, but it's difficult to get that message across to people.

In order for Cucumber and Specification by Example to be used well it is essential to provide tooling that appeals to the most critical piece of the collaboration puzzle: The business analysts (or the people with the requirements).

Nobody has solved this problem yet, but I think it is a solvable problem. We're trying to solve it with Cucumber Pro: https://cucumber.pro

Let's see how that goes.