BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage Interviews Matt Wynne on BDD, Cucumber, Hexagonal Architecture

Matt Wynne on BDD, Cucumber, Hexagonal Architecture

Bookmarks
   

1. First let’s get the basics out of the way, Behavior Driven Development for anyone who is not up to speed, what is it why do they care about it?

Test Driven Development it’s a practice that is been around for good long time now and many people are having great success with TDD, but there are also a lot of teams that struggle with it, or maybe actually don’t take the time to really learn to do it effectively at all, and I think the best way I can find to explain what BDD is, is it takes the ten years of experience of the best TDD practitioners and starts to give names to the other things that they are doing. For example discovering and using a ubiquitous language which Eric Evans, as a really experienced TDD practitioner has been talking about, using examples to clarify requirements with your stakeholders, and writing business-readable tests excepting tests for the system, so you can built the trust in stakeholders. Those are the kind of things that good TDD practitioners have been doing for years but a lot of us missed along the way, so I think what BDD does is that really explains Test Driven Development in a way that helps people to pick-up all of the good practices, that the good TDD practitioners that have been doing anyway.

   

2. You wrote the Cucumber Book, why did you choose to write a book about that particular project?

I got drawn into that project because it was tackling this problem that I had experienced so many times where as a developer I felt like the communication between the people who wanted this software and my side of the team just wasn’t effective enough. I got drawn into the community around RSpec and Cucumber, so actually when I first started working with Cucumber, I was barely a Ruby programmer, I just moved over from C# and I could hardly write any Ruby, but I got very involved in the mailing list because it was so passionate about a tool and just kind of gradually drawn into the community, so I ended up being one of the people that have been there from the very start and it was a natural choice to write about when the time came.

   

3. […] What’s your feeling and how do you think on any given project as to choose between using the Capybara versus Cucumber?

Peter’s full question: When people are writing tests these days especially in the Ruby Community, there is a real split, some people are like “All we need is RSpec, the unit testing framework, and then maybe we throw some others in there, so we have the ability to try stuff but we really want to keep it in simple Ruby code. Other people really feel like Cucumber is the way to go because it gives you end user readable, maybe writable tests. What’s your feeling and how do you think on any given project as to choose between using the Capybara versus Cucumber?

I would always use both myself, I'd use RSpec for microtesting the components, but I always think tests are like you are fitting a warning light to the system, you are leaving behind something which is going to signal to people later down the line, the ”Hey, you’ve broken something!” But there are two different kinds of signals, so in RSpec Test, a microtest, when it fails it’s really speaking to the developers to say: “This bit is broken”. What the business facing test do is they say to the whole team “This functionality isn’t working.” So there are two different things, this functionality isn’t working and this is why, so you need both of them.

I think it’s fine if it works for you in your context to write the high level acceptance tests using a tool like RSpec as well if that works for you, either if you’ve got technical stakeholders that are quite happy to read code and it’s possible to write those tests in Ruby and have them still be quite readable. Actually personally for me, it still helps me to put on my analyst hat, if I’m sitting writing a specification even if it’s just a project just for me or I am the only person working on the project, it helps me to think differently if I I’m working in a medium that is not encumbered by, do/end blocks and the mechanics of coding.

   

4. […]Do you have anything to say about refactoring of the tests?

Peter’s full question: One of the things that I see a lot of teams getting into trouble with, with their Acceptance Test however they encode them and often it’s in Cucumber, is they do I think a good thing which is they create lots of grains of sand, lots of user stories that they provide acceptance tests for, but then over time what they do, is they end up with hundreds or thousands of small Cucumber tests meant to be going over some sets of the same user stories. Do you have anything to say about refactoring of the tests?

Yes, I think it’s something that I’ve learned definitely over the years of using these tools, is that I think there is something you go through when you first get the hang of using a tool like Cucumber, is that it’s almost like it’s so fun and each of those tests it’s quite a big lever, so from writing one scenario you can maybe keep yourself busy driving out of the work for half a day maybe even longer before the whole scenario goes green, and you feel like as a brilliant, so I’ve got this one test, that has covered all of that effort, and I don’t need to write all of those little microtests as well. I think that is really dangerous because actually the reason that we want to write microtests is to help us to design objects that implement that solution really well, so they implement that behavior really well.

So I think there is a process sometimes of migrating down the warning lights, the tests into microtests, once we’ve got a design that we are happy with that’s stabilized. So maybe the scenario becomes the first place where you describe the behavior because in the early part of the project, you are still just writing down a few examples, but then once the set starts to become bigger, you want to sit and actually look at higher things from a higher level of abstraction, and those details it’s not important to surface those in business readable tests anymore and it’s actually more impropriate to have them tested at a low level.

   

5. Talking about business readable tests, I believe you have been working on a project called Relish? Would you talk a little about that?

I’m trying my best to bootstrap this little web based product alongside my consulting work and really Relish is built for… there is a particular person who I used to work with when I was first getting to know Cucumber and she took a very active part in the team, she knew everything that the system could do, but she couldn’t code, she couldn’t read code, and she couldn’t use git, and she couldn’t use ext Mate or god forbid Vim or Emacs. So we would sit together with Brooke, and what Brooke used to do was she would first write the examples in a spreadsheet and then we would sit down together and pair and write them down as Cucumber scenarios and she loved Cucumber, she really liked the feedback of talking about the examples in that way.

Then we would check them into git and started automating them and driving out the code, and they kind of disappeared from her world because they'd gone off into this medium that it was quite inaccessible to her. My idea with Relish is to give the developers a place to publish them back so that they are visible to people like Brooke, and it’s all indexed by Lucene, so it’s very easy to find features and it just puts them back into the hands of the business people, so they become that sort of single source of truth for the whole team.

   

6. If somebody is looking to get started with Cucumber, obviously it’s very easy in the Ruby world, what about on the JVM, what are some of the options for?

For ages we had this rickety old thing called Cuke for Duke. Cuke for Nuke was the old C# one. And it using quite a lot of the original Ruby Cucumber but using JRuby as a bridge into it and it was a lot of bugs always flying out of it and it had just about gotten there but it was really and awkward piece of software. Actually Cucumber’s Ruby version suffers from the same problem that we were talking about earlier of having a preponderance of acceptance tests but not enough microtests. So actually the design of Cucumber’s Ruby is not as elegant as it could be, so there we’ve got all these layers of JRuby on top of something that is not as elegant as it could be in the first place.

So Aslak Hellesøy is the original creator of Cucumber and has been doing a big rewrite and about six- eight weeks ago we released 1.0 of Cucumber JVM and it’s a complete rewrite, I was going to say for the ground up, but actually the really interesting thing about Cucumber JVM and the other flavors of Cucumber (so there is also a flavor of Cucumber that runs on .NET runtime called SpecFlow and there is also a JavaScript port to Cucumber now as well) and all of those share in common is the Gherkin library. The parser for the feature files is actually written in Ragel and Ragel is a parser writing DSL if you like and that actually generates code. So from the Ragel parser definition we generate C code, Ruby code, JavaScript code, Java Code and then we take the Java code and turn it into C# as well. All of those different languages, the different flavors of Cucumber are all built on top of the same parser and actually we run the same set of tests on all this different builds of the parser.

   

7. So you find that gives you the test coverage across the whole range?

Yes, it’s sort of pushing down the common core bits of behavior of what a Cucumber needs to do and putting into a single piece of code so it makes it easier to write a new flavor of Cucumber.

   

8. […] You said when we spoke briefly earlier that Hexagonal Architecture was based on Steve Freeman's book Growing Object-Oriented Software (GOOS) with tests, so I’d love to hear more about that?

Peter’s full question: Great, so you're best known, I think, for the Cucumber book and the Relish project but the one thing that it’s interesting to me is well as being at QCon New York this week, you are also going to be presenting the Gotham Ruby Conference and you are going to be talking about Hexagonal Architecture. You said when we spoke briefly earlier that Hexagonal Architecture was based on Steve Freeman's book Growing Object-Oriented Software (GOOS) with tests, so I’d love to hear more about that?

The Hexagonal Architecture is this Alistair Cockburn idea, it’s quite a simple idea, so the hexagon is just a metaphor as I understand really, the more technical name is ports and adaptors. The idea is that you have this core bit of your system which is not encumbered by any details of how the application is going to talk to the real world. So the infrastructure details like appearing on the web or through a rich Windows GUI or talking to a message bus or a database- all of that stuff is on the outside and you core, your inner hexagon if you like exposes ports where you plug in adaptors that can do that. I think the original idea of this was actually to make acceptance testing easy, so you had domains where the application was maybe surfacing say in a Windows GUI where testing is quite difficult at that level, what you do is you test at the next level down, you test the port, you plug in a test adaptor instead of, the adaptor that can show the application on the Windows GUI.

It gives you this nice separation between what stuff that is actually interesting about my application and what is this necessary evil that I have to have in order to let people experience it in the real world, have it remember things, have it send messages to all the systems in the enterprise – that kind of thing. So that is the sort of basic premises behind the way that Steven likes to design things and talked about design in that book. And I hit this point with the development of Relish, which is a Ruby on Rails app and it felt so familiar to me, I mean I’ve been building Rails applications for several years now and so many times I’ve hit this point where, because Rails application development is phenomenal at first, it’s so easy it’s almost like the cost curve, it’s like you are paid to do it, it’s so much fun.

You start to hit this point where it gets harder and harder, slower and slower, and I realized that it is about dependencies and there is a sort of idiomatic way of developing Rails applications where you don’t really have this in a hexagon, you just have the web controllers talking straight to the database abstraction layer, and things get quite tangled up and slow. So I was fishing around for: “How can I make the experience of working on Relish not be like that, how can I make it continue to be a pleasure?” and it seems like trying to get Steve and Nat’s ideas into a Rails codebase would be the way to do that. So that is what this talk's about, my experience of trying to do that.

   

9. It seems like that is a number of different people that are going in that direction, we’ve got Corey Haines who’s got this superfast running test, one of the side effects, presumably, of this approach would be that you get faster doing that?

That is the idea, because the stuff in a hexagon is isolated from the real world so it’s mostly plain old Ruby, Java, whatever objects. It should be really easy to pick those objects to test them fast and the more I move behavior from being in objects there are sort of coupled to the bits of the framework that talk to the database or the bits of the framework that talk to the web application move them into this pure bit in the middle, the more of my tests are running against plain old Ruby objects, so the faster my test suite runs generally, because the slower bits of test which are working against the framework, they’ve got less and less behavior, less and less complexity in them so there is less testing to do of them.

   

10. Have you played with any of the other approaches to speeding up unit tests in the Ruby world, in the Rails world specifically? Have you seen similarities or differences?

I think basically, what Corey and Gary Bernhardt, Gary’s screencast was a big inspiration for this as well, they are talking about the same thing, so the stuff that Gary would put in lib/, for me that is in hexagon, that is where your actually interesting rich domain behavior is.

   

11. Are you finding any other things, you have been writing Rails code for a number of years, are you finding any other patterns or approaches that you didn’t use to do?

I think the other big part of what I learned from the GOOS Book, it’s almost embarrassing to talk about really, is the idea that objects in an object oriented program should communicate to one or other by sending messages that are tells rather than asks. Andy Hunt and Dave Thomas wrote about this a long time ago in the pragmatic programmer the idea of: “Tell, don’t ask”. And if you look at an idiomatic Ruby on Rails controller, it’s very, very procedural code, that’s not all of telling going on, that’s a lot of asking and then deciding what to do based on that. What I found is, if you start trying to tell rather than ask, you are pushing responsibility off somewhere else, because the object that you are telling might then need something else to tell when it’s finish doing his work, so you are breaking up your behavior into smaller objects, so you are following all those good principles, the single responsibility principle.

And you are making your program start to decompose into smaller objects that you can reassemble to give you behavior in different ways rather than maybe just sort of moving things around in functions and calling different methods. I think the ”Tell don’t ask” thing has been a big thing for me, I think I sort of got rusty about that and I think that Rails had not helped me to remember how important that is in designing object oriented programs. I think it leads you down a path of having a more sort of data driven domain model rather than one that’s based on the behavior.

   

12. [...] Do you find patterns like that coming out of your code?

Peter’s full question: Then the other question would be something that I’ve noticed myself doing recently in Rails apps: I don’t know whether if this is good approach or if is just kind of one of those habits you get yourself into, I find myself writing in a more and more functional style, I find myself passing more parameters rather than using instance variables within some of the domain objects and I find the benefit of it is it substantially simplifies the amount of setup you need to do when you are writing the tests. And it also makes it much easier that you know that method probably doesn’t belong in that object, but you don’t want to create another object yet, but it’s much easier to move it because it’s not depending of one shared state. Do you find patterns like that coming out of your code?

I think what I’m finding at the moment is that I’m writing quite a lot of objects, that are just like a little commands so they’ve just got one method on them, and an interesting pointer in this same, you are talking about Grimm's book, is objectify which is a library which I think is a guy in Vancouver, I forget his name now, has extracted from their Rails codebase and that is actually a DI Framework, so you kind of declaratively describe but it’s nice Ruby hashes, a sort of systems of combining together a lot of command objects. It’s another interesting thing to look at in this same arena. I think that there are a lot of people and fishing around with different ideas of this and I think it’s a really interesting time in the Ruby Community at the moment, there is enough of a momentum now behind this and people recognize that: “We could be doing this a lot better than we are” and a lot of people looking for ideas that are really interesting.

Oct 08, 2012

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT