 So, a really short regression before I get to the rest of my talk. The very first time I stood up in front of a conference full of people and gave a talk was 1997 and that was at a vendor tool conference, a test automation tool conference. I was presenting a technique on some deep magic I had done with a little fascinating sort of undocumented aspect of the language. So I had 25 slides that were incredibly code dense and when I speak and I'm nervous, I speak faster. So I went through those slides really fast because I was really nervous. So 25 code packed slides and I went through the whole thing. And at the end, I had had no sense of time when I gave the talk and I look at my watch and I realize, wow, I used 25 minutes of a 45 minute speaking slot. I have time left. And then I looked out at the audience and they're all looking at me like this. And I said, oh, did I go too fast? And they're still all looking at me like this, except for one guy. The one guy was in the front row like sitting right where you guys are. And he looks at me and he says, no, that wasn't too fast. That was perfect. I got it. And I'm sure he did. He probably had invented it two years before I even thought of it. He was wicked smart. And the thing that I realized yesterday as I was sitting in this audience was that I'm in front of a room full of people like that. I think you're all smarter than I am by a lot. So I'm not worried about whether or not I'm going to run over time. I'm more worried about whether or not you're going to get anything useful out of this. We're going to find out. OK, now yesterday what I learned was that we've got a whole bunch of people who program Ruby and who do testing and better yet, who drive their development with tests. And I know that somebody asked for a show of hands on who uses cucumber, but I completely forgot who uses cucumber. So how many use cucumber? Wow, that's a lot. That's fabulous. This is actually not a talk about cucumber, although all of the examples are in cucumber, but this isn't about cucumber. The other thing I don't know about you guys is how many of you take the time to do proper care and feeding of your code. So you do refactoring. You take care to make sure that your method names and your class names are evocative and intention revealing your move duplication. Let's see a show of hands. Woohoo, that's fabulous. Now how many of you do the same thing for your acceptance tests? Any fewer. That makes me sad. But that's OK because I'm not here to talk about how to treat your tests like code and refactor them and so forth. This isn't a talk about that either. This is also not a talk about Ruby or about anything that's actually particularly technical, although technical details snuck in here. Instead, this is an entire talk about being nice to humans. Well, you're humans too. Boo. Ah! Misanthropes in the audience. All right. Well, obviously you're humans and while it's good to be nice to you, I mean being nice to the other humans, you know, the ones who don't do code. So this is a talk about being nice to people. And by being nice, I mean speaking in human language, whatever language your team speaks to each other in, well, OK, some teams speak to each other in Ruby. But that's besides the point. I mean, the human speaking part, that's probably English if you're working around here. And we're better to look for advice on how to communicate effectively in English than in the classic work on how to write English effectively. And incidentally, as Henrik surrounded us yesterday, tests are for communication. This is how we communicate, so our tests are going to follow some rules from here. All right. So let's take a look at one of the rules out of this book. As a rule, begin each paragraph with a topic sentence and end it in conformity with the beginning. Who knew that Strunk and White were talking about acceptance tests? It's amazing. Don't you see the connection immediately? Well, OK, let's change some words, like scenario, paragraph scenario, same thing. And an evocative name and, OK, this is looking a little bit messy. Keep the expectations and, oh, let's rephrase it. Make the statement and the expectations all align. The statement, the name, the expectations. So let's take an example. This is something I see a whole lot of. When I look at suites of cucumber-like tests, especially on Rails projects, they'll look kind of like this. Does this look sort of familiar? So we've got a system here. This is a trading system. The magical commodity exchange, known as Magix. And in Magix, we have players who have commodities in their inventory, and they want to trade them. So if I am logged in, it's the fairy godmother, and I am on the make offer page, and I go fill in this field with this and this field with this. Does this look kind of familiar? Your test might look a little like this. OK. Do you have any idea what this test is about? Yeah, me either, and I didn't write it, and I wrote it. So clearly, this is violating the strunken white rule. But let's take a look at some of the stuff that's in there, and maybe we can pull out some of the essence of the meaning. Given I am logged in as fairy godmother, and I'm on the make offer page, and blah, blah, blah, that whole thing that's surrounded in red, all of that is about making an offer. And all of the details that are in there are extraneous. In fact, I'll say they're almost gratuitous UI details. The only time the UI details belong in our tests is when we're testing the UI. If we're not testing the UI, and we're just testing the logic of the system from an externally facing perspective, and I know you got your unit test, because whoo, you test, that's great. But the customers want to express their intent about the system, and the intent here isn't to fill in fields. The intent here is to make an offer. And similarly down here, the intent is to see that when I make an offer, I can see it on the market. So let's do a little bit of refactoring. And now our test becomes this. Is that a little more clear? I hope. So we've now made this so much more clear, but wait, there's still another rule that we could apply here about omit needless words. Strunk and white rule number 13. And well, okay, words, details, eh, same thing. There's a principle here that's drunk and white so wonderfully captured that has to do with expressing the essence of the test and nothing extraneous. We're going to omit all of those irrelevant expectations. So when we look here, we've got four statements in this test, but one of them has nothing to do with making an offer and everything to do with the UI. There's one UI thing left over, and that's that line. So we can shorten it even further. This test in the steps may go through the exact same steps, but the important piece is that it is now conveying so clearly the intent behind it. So there's the principle of play here is that we're going to hide all of those incidental details. Cucumber gives us some fabulous place to hide details every framework does. So Cucumber, we can put stuff in the background. We can put stuff in the steps. We can put stuff in helper methods. We've got a lot of places where we can hide the extraneous but necessary details. Y'all do this? Okay, I heard like two yeses. By this time, hell yes. Okay, a hell yes. Excellent. All right, let's keep going. I only have half an hour, 20 minutes. All right, there's another rule that we could apply, and that doesn't come from drunk and white directly, although I'm pretty sure they would agree with it, and that is to use the most clear representation even if it's longer. So let's take a look at a test. This test is pretty straightforward. This is a simple trade. So Fairy Godmother is going to put some wands on the market, and Jack's going to bid on them, and Fairy Godmother's going to accept Jack's bid, and then we've got some expectations about what should be true in terms of the money and the magic wands, because if you do financial transactions, then you should know that it is an absolute requirement, and the government gets kind of cranky if you violate it. Thou shalt not create or destroy money. Right? That's kind of a good thing to follow, and similarly, although this is the magical exchange, we probably shouldn't be creating or destroying magic wands. So we want to make sure that everything is all balanced. Well, this test, I would say, is pretty readable. Do you agree with me? But now, see, these kinds of tests, oftentimes, the stuff that's being verified here is really being verified very well by the unit level test. So I'm not going to write a whole bunch of simplistic acceptance tests, although I am going to write some so that they express the expectations of the system, they provide documentation, that documentation is executable, all kinds of good things happen, but still, there aren't that many, it's just not that interesting. This is much more interesting. So now we've got a much more complex situation where fairy godmothers put up something and Alibaba has put up something else open for bids, and then we've got Jack and T-Bell, because I figured that Tinkerbell and Disney might get cranky at me if we use Tinkerbell to the name. So we've got T-Bell, she's going to bid on some stuff, and then we've got some expectations around what happens, who wins the bid, what happens to their accounts, right? This is way more complex. Can you rock that one at a glance? I'm embarrassed to tell you how long it took me to write that test, because I kept getting lost in who bid what, who won, what their account value should be. It took me a good 45 minutes to work through this. Then I refactored it. So Cucumbert allows you to do tables, so you can express what's going on in sections like this. So we can see that we've got some offers, we've got some bids, which bids were accepted, and then what final state of the accounts should be. Does that have a little bit better? Who knew that we were following Strunk and White's Rule 9? One topic per paragraph. Could be just amazing, they would be so great at acceptance testing on software projects. So paragraph section and whatever. And furthermore, following Rule 15, having to do with putting coordinate ideas in similar form, or if it's the same basic idea, then express it in the same basic way. Cucumbert lets you use scenario outlines for this, which is really, really great, and tables, which you just saw. Okay, so that's about organizing long tests, but let's go back to some simpler ways of being nice to the humans. Because remember, this is a whole talk about be nice to the people, be nice to humans. One of the ways that we can be nice to humans is to allow them to speak grammatically, giving Jack offers one magic bean bag, and T-Bell offers five magic bean bags. If we are too literal in our steps, then it won't allow for stuff like this, and that means we're gonna have to say things or tell our product owners or customers. Yes, we want you to express stuff like, given Jack offers one magic bean bag. And then they're kinda looking at us like, really, oh come on, really? But fortunately, this is relatively easy to do thanks to the fact that cucumber works with regular expressions. Woo-hoo, regular expressions. They bend my mind almost as much as closures, but they're incredibly useful. So we can pull out the salient fit just by expressing that regular expression better. Similarly, let's avoid enforcing unnecessary stuff. Like, does it really matter if we capitalize gold? Well, through the magic of regular expressions, we can make it so that it doesn't enforce that constraint. Unless it's important in which case we're gonna make it so that it does. But if it's not important, let's not enforce it, because then we've got these people who are running these tests and wondering why they can't manage to express their ideas without getting lots of bread all over the screen. It will accept it either way. Now, let's go back to why is this important? We've just walked through a handful of techniques for making your tests more readable, and you're on a short, you've got very little time on any given project, and you're thinking, maybe you're thinking, why should I bother being so particular about expressing expectations in acceptance tests? Y'all do write acceptance tests, right? Let's start there. Acceptance tests in any framework don't care which one? Ooh. Maybe we need to spend longer on this section than I thought. So let's talk about the universe from the perspective of the customer, and I've heard a lot of controversy over the last few weeks to months about frameworks like Cucumber and more about fitness. Anybody seen used fitness? Woo, okay, great. Wait, no, that's another language. So, people think this doesn't work because we can't get the customers to write the tests anyway, so let's just express the tests in code. I think that the people who, I don't have scientific data for this. I have not done a comprehensive study. I am speaking purely out of my hat and from my opinion, so this is my opinion. But I think that the organizations that have found it doesn't work are places where people are not willing to invest in the communication. These tests, the ones like that, they're not just tests. They're executable documentation. These allow us to not have to spend huge amounts of time writing lots of documents that are dead ends. They die. They go off into some repository somewhere and nobody looks at them again and we have to waste time making them because somebody in the project management office said that we did. These serve that same purpose, but they do so in a much more powerful way. And they do what Gwegoadzik calls bridging the communication gap. That's his book. Gwegoadzik, bridge the communication gap. Fabulous book. I highly recommend it. They're communication mechanisms. So when we say this doesn't work, we can't get them to write the test. Is it possible that we have tried to get them to write the test in another language? We have tried to get them to write in something that looks like code. We have tried to get them to write in terms that are unfamiliar to them. We're not working with them, pairing with them, helping them to bridge that communication gap and forge a language that we both can speak that represents the expectations of our application from a domain perspective. So it's critical to me to have acceptance tests that we can all share, read, understand and that my business stakeholders could, if they were so motivated, contribute to. There would be no technical impediments and no language impediments to them contributing to them. Because that's the point of how to forge that bond. How many of you have ever been on a software project where you did fabulous work and then the customer or a product owner, business stakeholder came back and said, that's fine but it's not what I asked for. How many of you have not? I mean, come on, if you've been in the software industry for more than six months you've had a discussion that was like that. This is what acceptance tests are for. They're not to see if the system is tested. They're to talk about what's acceptable. The emphasis goes on the first part, not the second part. I would argue that from a tester's perspective these actually aren't tests at all because they just check that stuff that we know should be true, should be true. Testers have a tendency to break stuff. I'm pretty darn good at breaking stuff actually. Wow. But I don't express those kinds of things in this kind of format. This is a communication tool and it happens to be executable, amazingly powerful. So, if you can accept, all right, well let me do this quick poll because I could just get down off the stage and be done if we don't have sufficient belief in this. It's kind of like Tinkerbell and Clap if you believe. Okay, acceptance tests are important. Oh, that's weak, come on. Acceptance tests are important. If we buy into that then why isn't it more readable, making them more friendly to the humans, making them in accordance with the guidelines by people like Strunk and White. Well, they're important because, as George Orwell pointed out, language can also corrupt thoughts. So to the extent that we are not careful in how we express our acceptance tests, we are allowing sloppy thinking about the thing that we are building, which is what's ultimately going to lead to those really uncomfortable conversations. Six days after you were supposed to ship and something hasn't shipped yet and the customer is ticked off and wondering why and trying to figure out where all of their money went that they spent on this thing that doesn't do anything that they wanted it to do and it's because we didn't have that shared alignment. So acceptance tests or alignment tools keeping very carefully and clearly in those acceptance tests helps to ensure that what we ultimately deliver is ultimately serving the business's need. And that's why we do this, right, to deliver value. I mean, lambdas and props and stuff, they're all cool and fun, but at the end of the day when we're on a software project that somebody else is paying for, we're there to deliver value and this is part of what helps us ensure that our efforts are in alignment with what our customer is expecting. Incidentally, major, major thanks to Steve Conover, you here, because he's the one who reminded me of this essay by George Orwell, so I went and looked it up and realized, that's the perfect quote to end my talk with. So, back at the end of the talk, there are some references that I want to point you to. One of them is Dale Emery's two essays on acceptance tests and expressing the essence and leaving out the incidental stuff. He's got some really great stuff around that and he has inspired me. Elements of style, of course, politics in the English language, thank you, Steve Conover. And then one more groveling apology and that is that my materials are not online yet. They will be later today. So I will tweet as soon as they are up on GitHub. I think I'm done. I've ever seen so enthusiastic with your question. You didn't see him leave. Those of you who were facing forward, looking at your laptops, that was amazingly agile. What I wanted to ask is about these acceptance as we write them in natural language and human language. But then again, if you express the same thing in various forms, which can be expressed in a single, regular expression, then we need to cover the same thing multiple times, right? And we don't want to do that. We have all this dry philosophy or anything. So when do you make, when do you put the line on this constraint that we should discipline ourselves to use the same terminology, use the same sentences over and over again and not try to be poetic and be very literate and be very human in our acceptance test? So if I understand correctly, where do I draw the line? Because if you do what I just described, you're not being completely dry. You're gonna have repeated regular expressions and stuff. Yeah, what I'm saying is that people, when they write, they avoid using the same thing over and over. That gets boring. The same sentence, the same word, right? So they tend to change it. So if you avoid writing the acceptance test, that would mean a lot of sporting ruby code to make it run. Okay, so let me go back to George Orwell because this is where I draw the line. If my product owner is being wishy-washy about terms like let's take user and account, for example. Those are two that sometimes people will, in conversation, use interchangeably. So, you know, the user, you know, the account and they're being a little bit too loosey-goosey about it. And it turns out that in our system and in our code, we have 17 different flavors of user and 17 different flavors of account and nobody has any idea what they're talking about. That is not acceptable. Now, I don't think that's what you were actually asking about, but it is important because when we talk about humans want to be poetic and want to make sure that when they speak, it's interesting they're not saying the same thing over and over again. That's how that kind of sloppiness creeps in to anything, whether it's like dead specifications or a lot of executable ones. The sloppiness creeps in when people get a little bit too creative in their expressions. So then, we pull out the George Orwell statement and we remind them that we have to be very precise in how we use domain-specific terms so that user always means user, account always means account and we don't ever confuse the two. However, that said, when we've got something where sometimes it makes more sense to say when fairy godmother accepts the offer and we know that in this task there's only been, sorry, when she accepts the bid, there's only been one bid made so there is no possible confusion over bid, then I don't want to make half to say when fairy godmother accepts T-bell's bid of 15 gold and I had just said T-bell bids 15 gold, that's where I accept a little bit more duplication in my acceptance test steps than I would have accepted in my code. So I do, my tests don't tend to be quite as dry as my code but that's how I draw the line. If it's about the domain-specific language then we have to be very, very precise. If it's about making it easier to express the concept related to the domain-specific language then I allow for a little bit more duplication in the code. Yeah, thank you. Great talk, I've got a question about the first couple slides you've been over about the very long acceptance test versus paring it down. Yep. It seems to me that when you talk about yes, that'll make it easier. Yeah, an example would be handy right about now. You could quote Brian Merrick. Okay, so this slide very clearly gives the customer's expectations on a very specific level about what they want to see in the page, what they want to fill in, et cetera, et cetera. Right. The second test seems to me to just sort of put a lot of trust in the developer that I want to do these two things. However this happens, I don't care, but I want it to happen. I just want these two things to happen. I just sort of balance the difference between some customers want very specific things to happen and they want to specify without the acceptance test getting to be like the first example, which is 15 or 29, which is kind of hard to read and understand, but at least is very precise about what they want to say. Well, what we're really talking about is two separate things. So I'm going to have two separate tests. And that's where we pull in Strunk and White's rule about the paragraph, all coordinate, whatever, I can't remember it off the top of my head. My English teacher would be mortified, but that I can't. But here, look at the scenario name, make an offer. It's not expectations about the offer page. And especially when we're talking about AJAXY, Web 2.3.5.0, whatever we're talking about, the expectations about the UI, they are going to have very specific expectations about the UI. But I'm going to express those in a UI test that talks about when I have not filled in this field, then this button is not available or grayed out or whatever. That's all about the UI elements. When we're talking about doing an end-to-end test about the logic of the system, then I'm just going to express it that way. This would be a long bloated test about the UI because it's going through an entire flow. And it's not really expressing the expectations about the UI well. If this was about the UI, I would change the scenario name and I would probably break it into multiple scenarios to express expectations about the make an offer page versus the market page versus other pages. And that would be a whole separate set of features. Okay, thank you very much. Talking about the issue of how much effort it's worth putting into acceptance tests to make them clear. And I guess what I'd like to say is that acceptance tests are a very high leverage document. A very short acceptance test can correspond to thousands of lines of code. And therefore that leverage makes it worth getting it right. And the other thing I guess I would say is that some of the same rules of writing good English in terms of short sentences and short paragraphs and putting in a few helper words here and there to help the reader along apply here as well because not everybody's a native English speaker and even some native English speakers don't have a good lot of English. Totally agree with you. So when you were talking about separating out this into the multiple tests, which makes a lot of sense, do you have any recommendations for cases where you wind up with a lot of setup? And so turning a test like this into re-reporting tests for UI elements, you know the math would wind up with a lot of duplication basically. Are you concerned about duplication or speed of writing? Duplication, I don't care as much about speed of writing. Well I think both are totally valid because I mean especially if you're going end to end through the GUI and every single test goes all the way back out to logged out and then all the way through to logged in to this page to that page to set this up, then you can have a test that should only take like two minutes to run, suddenly takes two hours to run. Absolutely, it's a valid concern, it just wasn't like our own. Okay, well if your current one is just duplication then I would say the power of Ruby is with you because you can stick a lot of that stuff in helper methods so that you're not actually duplicating large chunks of code, you're just calling a helper method or you're just calling another step. So you can chain steps the same way you would. So essentially you wind up with a rule of? Sure, there's the background. So you can stick some of the potential duplication up in the background so it will execute with every scenario. Or you can hide it in steps so that when it says something like as grandmother or as fairy godmother I offer then the step can check, is fairy godmother logged in, da-da-da-da-da-da. Instantly do that. Power, for the runtime problem, well I'm now prepared to be booed off the stage although some of what I'm about to say was implied by the code that I showed. I understand that sharing state between steps is somewhat controversial and it is entirely possible that there are technical reasons not to do it that I'm not aware of but when I researched and when I'm running my own stuff I haven't found issues yet. The answer is that I would have some shared state so that we get to a state that is farther along the path and then we're just sharing that state between steps and also potentially even maybe between scenarios. Be really careful with that. Don't boo me off the stage but if you've got serious performance concerns then you have to start taking shortcuts like that. I think that's it. Can we take this question? Given that I named him. Okay, okay, okay. Just for you. I have a brief follow up to the runtime question. One of the tenets of restful rap is that actions are stateless and it's often possible to log in in a stateless fashion like by an HTTP offer. What he said. So you can get rid of all of the intervening steps and make a stateless call to the staff. Right, so what he said is a better answer. Okay, that wraps it up for questions. Thank you very much.