 England, blah, blah, and he's a very seasoned developer with over 30 years of experience building scalable, manageable and reliable systems. For the past 10 years, he's been doing that with PHP, is an advocate for BDD, and as a driver for building great applications. And his dedication to the PHP community is well known to be the founder of Vegas PHP. In the past few years, Adam has been building IoT apps, and he's been researching ways to make this accessible in PHP. And in this session, this is track three, and this is BDD with Behat for beginners. If you're not here for BDD, track two is on the right side, and track one is on my left side. So if you're in the wrong track, please go ahead and make your way to the right track. If not, this is BDD for Behat, and let's have a round of applause for Adam. And they're working. All right. I forgot my laptop. What's it doing? And perfect. So good morning. So if I say something you don't understand because I'm terrible and I use a lot of American slang, please let me know. Today's session is going to be broken down into four basic segments. This is the preface, so I'm getting an understanding of what you're trying to get out of this tutorial. We'll do an introduction to behavioral driven development. We'll do an introduction to Behat, and then we'll actually build some tasks. So the first thing that I really want to know is get an idea of what the audience is. So how many people here are primary lead developers? Okay. So that's one. How many are primarily QA? So I guess the thing I need to find out now is, so for reasons for attending the session, do you want to learn more about behavioral driven development, or do you want to learn about automated slang testing? Okay, so mostly behavioral driven development. Okay, so we'll go with that. Experience level with PHP. So how many people have been using PHP for more than five years? Okay, that's good. More than a year? More than a year? Oh, okay. How many people have used Behat before? Okay, so you can keep me in check. And how many people know what behavioral development is? Okay, so we're definitely going to do some time on behavioral development. I see a bunch of people with Windows. So how many people have used Composer in Windows for an app before? How many people have not used Composer in their PHP apps with a Windows machine? Okay, so what you're going to want to do is you're going to want to go to getcomposer.org, and there's an installer to install Composer. You're going to want to do that because as we get started, here's your pre-run checklist. So if you need that, if you don't have any of this stuff installed, you're going to need to install it. Let me get down to the actual examples if you want to follow along on your code. So for the latest version of Behat, or sorry, it's fresh, Behat. For the latest version of Behat, you need to have PHP 5.6. That's going to be pretty important, but you should be using anything older than PHP 5.6 now, right? PHP 5.6 of life. You'll need Composer, and you can go to getcomposer.org, and there's a Windows installer. If you're on a Mac, you can just use, if you're using any of the package managers, you can get it from there. Sorry, not Composer. You just go to the getcomposer.org, there's installation instructions. It's pretty easy. You don't necessarily have to have a browser with a Slonium driver to get this to work, but if you actually want to do some Slonium testing, you need a browser with a Slonium driver. Firefox works really well if you've already got that, and it's going to be the default for most of it. If you are installing newly the Slonium driver, you will absolutely have to get Slonium server standalone, because the new 3.0 version, which is the default version when you install it, does not allow for non-Slonium server standalone interfaces. You can't directly interface with the driver. So is there anyone that has any questions about that, or can I just move on? Okay, so when you're doing this and you're trying to get things set up, here's some of the gotchas that you're going to run into. Mostly for you Windows folks, is that you have to have the curl, mb-string, and open SSL extensions enabled. So that's usually pretty easy on Windows. If you're using a Mac or you're using Linux, it comes pre-installed with those enabled, unless you yourself have built it and it doesn't have it. And if you've done that, then you know how to enable it, and I'm not going to have to go through that. In Windows, in your phpi and i, you'll see there's an extension section, and you'll see that these things are commented out, open SSL, mb-string, and curl. And the majority of these are actually just being used by composer itself. So if you have composer working, you'll probably be okay, with the exception of the mb-string, the multi-byte string. And for everyone, your tests will fail if you do not have a time zone set. So inside your phb and a, if you've been using phb-5.6 and getting warnings about the fact that you're trying to use something in time, and you don't have a default date time zone set, these are going to throw warnings which are going to make errors and have your tests fail. So it's super easy if you just search for time zone date time zone in your phb and you can uncomment that and put in whatever you want. If you're not sure what to put in, just put it in all caps UTC. And then you'll have one set because it's going to default to that anyway. Any questions about that? If I move too quickly, please raise your hands and ask me to slow down because I talk really fast. And move through this thing really quickly. So we'll kind of be able to get back to that in the end, but if you've not set this up and you want to actually go through tutorials, it's not really required. I want to do a lot of typing and you'll be able to see it. But if you really want to follow along, you're going to need to have Composer, Behead installed, which you can install through Composer. And to do that, you're ready to curl and be storing open SSL at a default date time zone. All right. So the first section of the actual talk is an introduction to behavior government development. And there's a lot of text, but I'll do a lot of talking. It's here for you. I'll do a lot of text so if you come back to the slides later, you'll be able to really kind of see it. So behavior-driven development is user-focused and test-first. It's not developer-focused. It focuses on delivering business value as effectively and efficiently as possible while maintaining consistent quality throughout the entire application. VDD is a methodology built around the principles of lean development, extreme programming, test-driven development, and domain-driven design. So if you don't know what any of that means, basically, lean development is you only build what is necessary. Why build something for a customer when they haven't asked for it? Why build a feature for a product that may never succeed? So the development world is all about building minimal viable products and the minimal amount necessary to get it out there and see what the customer thinks, see how it works, see if anyone's going to use it before you build in these 100 features to find out that nobody wanted to use the product anyway. So that's lean development. That's kind of agile development where you do iterative development as you go along because your requirements change as you go, so you build it for the requirement today and you add pieces on and they may change as it goes. And the problem that you run into when you're doing agile development is that you have to not break all of your old things. You have to make sure that the requirements that you had before still work after you make these changes every week, two weeks, three weeks on your iterations. And by broken code, what I actually mean is that you've removed or limited or have an inadvertent reaction inside of a feature that the business require. BDD is all about business requirements because at the end of the day, applications are made, for the most part, for a customer. Whether that's to make money or to allow them to make money, at the end of the day, you're providing a product. And if your product doesn't have what the users want, they're going to move to a different product. So if you're an open source, in many units you manage an open source project, you've got to make sure that the users that are using your product every single day as an open source product, you don't shift to them something that's going to completely destroy their lives because now their users can't log in, they can't put things in forums, whatever the case may be, whatever your functionality has. So what behavior-driven developments do is want to really, really focus on providing business requirements. It's not about how pretty is your code, it's not about how much coverage do you have, it doesn't care if you have cyclobatic complexity, all these things that you're going to find from these other tools that are more unit and code-based, this is about, am I delivering the business feature? Does it meet the business's requirements and hasn't stopped meeting those requirements? Which is why I find it very exciting. Any questions? So one of the things that BDD actually provides, so you get a better understanding for the business requirement. When you're writing these tests for behavior-driven development, you're required to get the actual requirements from the business user. Anyone out here who's a professional developer, you know that you will get something that says I want something to do stuff, make it happen, right? And they don't give you a whole lot more information. And you're in the middle of coding and you realize, oh, well, we didn't talk about this thing. What do I do in this particular scenario? I'm not sure what to do. And then they tell you something that you didn't expect and you have to rewrite all of your code because it didn't take that into account early on. So one of the nice parts about behavior-driven development is you're going to get a better understanding of the business requirement because you're going to have to build out these scenarios and figure out, oh, when it happens this way, what's it supposed to do? When the user does this, what's supposed to happen? You can get a better understanding of existing features for the business. So if you have an application, and a lot of the times what I end up doing when I'm implementing BDD is I have a legacy application that is starting to go through problems. They're starting as your application that's a year, a couple years old. There's a bunch of features that people totally forgot about. Or people argue about what it's actually supposed to do. When I work now, I've been working there for about 18 months now at launch heat, and they didn't really want to do behavior-driven development, and I was pretty okay with that. There's this really nice tool, and if you want to use it, that's fine. If you don't, I'm not going to pressure you because when you pressure people using tools and they're hard to do, they're just going to agree. And about six months ago, they're like, all of our testing is terrible and you need to find a better way. And one of the things they're running into, I actually watched two of the founders argue about whether a feature was supposed to be the product or not. So the vice president of engineering said, no, we took that feature out, we deprecated it's gone, and the CTO was like, no, we never took that out. And they're arguing about it and also what things are supposed to do and how it's supposed to react because there's no documentation of what it actually was at the time. We could probably go looking through tickets forever and try and find it, the point where they put it in or put it out or changed it. But one of the things that it does is it's going to allow you to document what that feature is on the existing code or the older code and see what it's actually supposed to do because that's what's passing right now. And it's going to allow for better communication view what's a very large term called a ubiquitous language. One of the problems that you run into in organizations is that the same term means different things to different people. So when you talk about an application, one of the problems that I had at LaunchKey is they had 16 different different applications for an application. So an application can be the thing that the user interacts with, the main application. And then there's an application which is actually the integration point in our system as it's documented in our dashboard. And then we have an application which is what runs on your mobile device. And then you had an application which was actually the integration scenario. So we had the same word that was used in multiple places. It meant completely different things. So when you're talking to someone, they didn't, you had to spend a bunch of time making sure that you each understood what you were actually talking about, which makes it very difficult to work on. So one of the things that's really kind of pushing this is a ubiquitous language so that a word means the same thing to everyone, which makes it easier to be able to document things and to write things. So your code, it should mean the same thing. How many people have heard of domain-driven design before? Okay, a few. So that's a big tenet, domain-driven design. That's one of the big pieces that's taken out into BEHAB, is that if you, when you talk to someone about functionality, it should mean the same thing to everyone. So it shouldn't be called an application here and it's called an integration inside the code because then everyone gets confused on what you're talking about and it's the same thing in your tests. The other thing it provides is real insight into the business effect of a defect. So if you're running unit tests and your unit tests fail, you know that a piece of code doesn't work. What you don't know is how that affects your customer. You just know that a piece of code doesn't work. You don't know if it means that they can't do anything or if some esoteric feature somewhere that nobody really uses doesn't work. There are times when you're going to push code out and it has bugs and you're okay with that because you evaluate, you say okay, how bad is the defect? I'm pushing out code because I have a feature or a fix or something like that and you can make a very, and you and the business can make a very, very well qualified decision as to whether or not you're willing to push out this new stuff because it breaks something old and what you're going to be able to do through behavior development and through the feature testing is you will have a very, very good idea of what's actually broken. So you and the business can make a very informed decision and sometimes you have to say oh customer wants it, we're going to put it out there and if you don't know what you're breaking you just hope that it doesn't really upset everybody. One of the things you try to do with BDD is you try to have a really good idea of what's actually broken. What BDD does not provide is an answer to all of your problems. It is not a magic, it's not magic, it's not a silver bullet, it doesn't do all things for all people. It does not replace unit testing. Unit testing is to make sure that developers don't break other developers code. It doesn't replace manual testing. So there are certain things that you're not going to be able to automate. It's just the way it is. Some things are going to be visual. Just because I can interact with a web page doesn't mean that the user can understand the web page or that it's not often a place that they don't see or it may have something they can't figure out. And you're also going to have to verify your automated tests to make sure that they actually, that when it says it works it actually does work. So the first time you actually implement a new one you're going to have to verify manually that's actually good what you think it's doing. It is not super easy to implement everywhere right this second. Hopefully when you leave here you'll have an understanding of how to do this. It's going to take a while to get good at it. You can't go to a boot camp for code and then be an amazing programmer in a month. One of the things that I also talk about is what to do a year later after you've ruined your life with B2D and B2HAT because you're going to do terrible things. So for the developers out there if you like the code that you wrote a year ago you may want to consider a new career because you should constantly be getting better and you should be very upset with the terrible decisions you made a year ago because you're a much better developer now. And it's going to be the same with B2HAT. You're going to make some assumptions and based on fairly limited knowledge you're going to say oh this is the right way to do it and then you realize it's very difficult to work with later down the road. And it's not a measure of code quality. Behavioral development doesn't care if your code is very pretty, if it's very readable, if you repeat, if you have the same functionality repeated 100 places it doesn't care. Which is one of the beautiful things. You can write a very terrible application. I worked with Place where they had a terrible application. It started on PHP 4, made its way to PHP 5, it had a function that had 10,000 lines of code that did everything. Model View Controller, 10,000 lines of code, lots of switch statements, if statements. But it made that company $10 million a day in profit. So they didn't care if the code was quality don't mess it up. Whatever you do don't mess up a $10 million string. And so we had to use behavioral testing because you can't unit test something that's got 10,000 lines. Which is one of the reasons that I started getting into behavior development is how do I actually test the application? Because I can't unit test the actual code because there's too much. We ripped stuff out over the years and made it down to maybe like I think it's 3,000 lines of code now and the rest of it's pulled out. But there's still just a ton of stuff there. So the other thing, this is my favorite, my favorite conversation to have with people. So how many people have done selenium testing using unit tests? Okay. So you have seen this a lot. Failed to assert false is true. Because when you run selenium tests through unit tests, you're basically saying, oh, this should be there. And you say a certain true and it's false. And that is your answer. You have no idea how you got there. You have no idea what's actually not working. You just know that false is not true. And I worked in a place when I, the place I started learning VDB, we had this and you got a screenshot, right? You had a test that had a name. Failed to assert false is true screenshot. You had no idea how to recreate that unless you went into the code, right? So QA couldn't go evaluate it and say, yes, it's actually broken or it's a false positive. You had to go into the unit test, follow the cryptic steps that you're doing inside of selenium and then try and recreate it yourself and see if you can make that picture that you got back. That is terrible. So the solution for me is story VDB. Now behavior government development is a very large swath and we're going to talk about story VDB, which is story basis. Does anybody here do scrum or agile development? So you've heard of user stories, right? You'll find amazing, amazing similarities between story VDB and user stories in scrum. Something that I used to do at the end, but this is for like 30 minutes shorter than normal, is kind of showing you how you take scrum and turning it into story VDB so that you have a flow straight from scrum into behavior of development that we had. But if you've done it and you've done it long enough, you'll see the similarities instantly and it'll, you'll have this little aha moment in your head and just say, this is, this is amazing. How to write effective features? It's very important to write effective features because they are the basis of all of your testing and the absolute basis of VDB. And you have to stay focused. It's really critical that you focus on what feature, what a feature provides the business. Nobody cares where a button is. They may care what the text is. They may not. It depends on your business. What's important to the business is that they have a need, so based on our example today, user registration. If a user can't register, then they can't do the things that I need to do to make money from them. So that's a very important feature to the user or it's a very important feature to the business. And you need to make sure that the actual requirements are actually documented so that you know when you break something that the business really needs. And that is where you have an idea as a developer before it goes out, before it even goes to QA, you can run these tests yourself and find out, am I breaking a feature? As you know. You need to always understand the role of the user and the relationship to the feature. So many applications have different users and different roles for the user. So sometimes you'll have a user who is a visitor, right? Visitors you may or may not care about depends on how you're actually doing conversion, right? If someone is a visitor and something for a visitor doesn't work, you may not care. But if something for a registered user breaks, you may really care and if something for an administrator doesn't work, you may have some serious problems. So it's important to understand the role. Do not get distracted by the technical aspects of the implementation. If your tests are very technical in nature and talk about the technical way of which something works, what value is set in the database? No one cares. Your business people don't care that it set a value in the database. They care that that value affects something over here in the application and does the application work. How that technically happens, no one cares, right? It's not testing your code, it's not making sure that things are working for your code, it's making sure that features work for your users. So don't get hung up on making sure that this technical part of your application is working. Make sure that features work. And so here's the hierarchy of StoryVDD. You have a feature. And so based on what we're doing today, a feature could be that user registration. Features have a background. So oftentimes they have a background. So let's say for logging in, right, if you need to test log in. But before you're logging in, you need to be a registered user. So the background of your feature is that you have a registered user and then they can log in. You have scenarios. So for user login, it would be what happens when the user provides an invalid username? What happens when the user provides an invalid password? What happens when they failed three times, right? These are all these different scenarios that you need to take into account and how you want to react to them. Do you want to let them know that they couldn't find the username or do you always want to just say invalid credentials? Do you want to let them know that they failed three times or do you just want to say invalid credentials? These are things that business people probably care about. On the code side, you just need to know what you have to do. And then there's steps to accomplish this scenario, right? So to log in, once you've got your background, which is that you're a registered user, you're going to have to navigate to the login page. That's a step. You're going to have to fill in the login form. That's another step. You're going to have to hit the submit button for login. That's another step. You're going to have to verify that you've successfully logged in with the correct error messages shown. That's another step. And so that's kind of the hierarchy. So in writing features, I probably shouldn't have to tell you this, but applications are comprised of features. BDDs want to discreetly separate each feature. They should be atomic, right? So when you're writing your features, the testing of your feature should not be reliant on any other feature. That's what your background is relying on. So if there's some other feature that you're going to need to make sure it works, so in login that I have a registered user, you should not be testing registering a user in that feature. You should assume that it works and put that in your background. So all the steps that pertain to that are going to show up in your background. So that when your test fails, you know that, oh, it failed the background. This is not where my problem is, right? So if you have a bunch of steps going to register the user and then log in as part of your feature, you're not, you're going to have to actually do a lot of work to see where is it actually failing and what's the actual problem. So if you move the things that are not part of that feature into the background, they can be able to easily identify that it failed in the background. I'm looking at the wrong place because that should be under test somewhere else. Each feature contains a narrative in a scenario. So it's important to be descriptive about the feature. One line of descriptive, one line of cryptic text, right? So if you have like feature registration, right? Registration of what? By who? So it's important to say something descriptive and if you've done scrum before, that's your user story, right? You start off with a very simple thing. As of what, in order to do this, I must be able to do that. So I tend to do it that way. It doesn't really matter as long as it's a narrative that is descriptive so that any user coming up or developer or anyone else, a business owner coming up two years from now can go look at your feature test and say, I understand what this does because at the end of the day, this is going to become the documentation of your application. One of the things that it does provide is it provides documentation of your application that is always up to date. If you've managed an application and you've had to document it, it's never up to date. It's a lot of work to keep the documentation current and it always falls behind because as a business is moving quickly and building applications and putting things out there, internal things fall to the wayside as opposed to customer things that are always moving forward quickly. So if you have an administrative portion of this, the documentation is probably old and out of date and people are going to ask, how does this work? And you're like, I don't know, ask this person because they're the only one that knows. So one of the things you can do with this is you can get really good insight into how things work. And it may also contain the background, which we just talked about. So in the narrative, the description of the feature, things that are super important is what is the business benefit? You're writing applications to benefit your business. And business could be, it doesn't necessarily have to be money. You have customers and you're providing a service for them. So for an open source project, you're providing something that's going to be used by lots of people that have understandings that's going to work and that these things are going to have that are high impact, low impact, things like that. Who's the beneficiary and what's the action performed? So a background should contain steps that are common to all. Right. So all of your, you may have scenarios and they're going to do all different things, but things that are common, you're going to want to put up in the main background. It's kind of like if you do unit testing, you have set up and tear down. It's basically set up, right? So that you don't have to recreate all of this stuff in all of your steps, the side of your scenarios, you can just have them in the background. They should also be tested elsewhere. Very important. You should always make sure if you're going to put something in your background, so let's say for the login feature, having the fact that you can register, if that's not tested somewhere else, you're not going to be able to find out how to fix it when it's broken. So make sure that they're tested elsewhere. And like I said before, step spending in the background will identify the feature that the failure is not related to the feature. So you can not worry. So this feature, I don't know if this feature is working or not, but I know it's not the problem. So scenarios, again, a scenario should contain an error. Explaining what the actual scenario is. One of the things that I use BDD for a lot is getting clarity with the business owner. So they say, hey, I want you to build this thing, to do this thing. And they're usually very broad and they're very busy and they don't spend a whole lot of time explaining it to you because you just understand it, right? And so they think you understand it. They think they've explained it. You go back and you're missing pieces, or you've basically taken what they've given you and what you understood that they gave you and you're writing out your scenarios. You're featuring your scenarios. You provide that back to the business owner and they said, that's not what I meant. And you can fix that, right? If you have the narrative with the scenario, it'll either prompt them that they, there was something they hadn't thought about or that you had misunderstood their instructions, which happens a lot in development world. They tell you one thing. They have a complete idea of what it's doing and you think about it in a completely different way and you didn't come to a middle ground to figure out what it means to both of you and you build the wrong thing. I've spent way too much time building the wrong thing. And scenarios should not test multiple features. So again, inside your scenario, if there's something that's related to another feature, it should be in a background. And do not perform actions after assertions. So if you've done unit testing, and you've done any kind of research on unit testing, right? Your each unit test should test one piece of functionality. And it should not test two pieces of functionalities. There shouldn't be, you shouldn't do like, verify that something worked and then go do something else, right? So they have got the whole range, act and assert, same thing inside of PDVs. If you don't want to have code that's verified that things have happened before you do something else, because that should have been tested somewhere else. Is that clear? I always have a difficult time explaining. Scenario outlines. Scenario outlines are awesome, helping you reduce the amount of code that you have. So they use a common set of steps with placeholders for data and a data table. So if you need to test that when you say you log in, is this where you register with, let's say this type of, if you register in this particular country, that you're going to have specific things shown to them based on the country of origin or whatever the case may be that they're doing. And so you're going to have to test different pieces of data. So if I'm coming from Australia, United States, or Singapore, you're going to have a different reaction. But the same step, you're actually doing the same steps. So instead of rewriting all of that step code and all those things that you're testing, you can just say, oh, when I have this piece of data, I should get this result. When I have that piece of data, I should get that result. And a lot of you do scenarios which will really cut down on your time when you're building this stuff out. So steps. Steps are the things that actually do the work. They're the heavy lifters inside of PDVs. And they should do one of the following. Arrange the environment, perform an action, assert the result of previous actions. So unit testing, you've got your setup, you've got your action, and then you do your assertions, the three A's of testing. So one important thing that you don't think about a lot of unit tests is that steps should be reasonably reusable. If it's something that you're going to do on a regular basis, genericize it. Because you're going to be able to write a lot less code. So if you're, let's say, for filling out forms, fortunately, most of the stuff in PHP is already built for filling out forms. But if you're going to, say, fill out a form, it doesn't, you don't want to make, fill out, have a step that says, and I give this value to this form field, you want to say that I give a value to a form field that's identified this way. You want to make them very generic because you write less code. The less codes you write, and the more generic you make it, the more usable you make it, the faster you're going to be able to iterate through your development cycle with BDD. It's very important. The other thing is that they should be aggregated for simplification. So if you require that the user is registered, you should have a step that says, given the user has registered. You may not care about the username, you may not care what their email address is, it doesn't matter to you, they just need to be registered, and then you need to be able to log in as that user. Oftentimes it's important, given the user is logged in. Given I'm logged into the site, you don't care what the username is, you don't care any of that, you may care what type of user they are, so you may specify a role, given I'm logged in as an administrator. All the stuff behind that is just distracting when you actually put it in your step. And to have to rewrite all those steps that actually make that happen is really annoying. And it also makes your testing very brittle. So when that functionality changes, you have to go change all of your features and all the things that you did that utilize being logged in to now use the new flow. So what you want to do is you want to capsulate that into one step. It's going to reuse the code from the other steps so that you can just say, given that I've logged in as an administrator. And so you can go back and when you change how that happens, you just change it in one place or two places. You change it in the step or in the feature that allows you to log in as administrator or create the administrative user. And then you've also got the aggregated step that actually performs that for you. So there's only two places you have to change it. Instead of you have a large application that has thousands of features, you don't have to go change to a thousand places. Super important, right? Code reuse. I would kind of liken this to you don't want to build your code based on... Let me know what that is. You want to be able to pile together a bunch of reusable pieces instead of rewriting them all the time, right? You don't want to repeat yourself in your code, you don't want to repeat yourself in your steps. So any questions about story BDD that went really fast. Okay. If you have any questions, there's all kinds of books out there. There's all kinds of resources on story BDD and how to get better at it. And what I can tell you is that you're probably going to be terrible at it at first. Don't feel bad, right? If you... Anytime you start doing something, if you start doing something and you're amazing at it, you should just focus on doing that one thing forever because that's probably what you do at your plant station in life. But for me, I did behavior development really terribly for years and had philosophical arguments about why I was correct if someone else was incorrect and we're both wrong. And as I've been doing BDD now for five or six years and now I have a lot of kind of hindsight as to why things didn't work and why things could have been better. But I wasn't able to see those immediately. Well, the advantage is that you'll have is that five years ago, there was no PHP BDD. So I was having to listen to QCumber and didn't understand it. I didn't understand Ruby. And everything was talking about how to do this from Ruby. And if you've ever done Ruby, Ruby does things very differently than everything else. And I'd like to argue about the flow of the code more than how effective this is a lot. This is just my experience. So now with the hack, we have a lot of things that are super, super helpful. So let's talk about the hats. It is French and fantastic. So it is pronounced the hat. And it uses things like geese. There's a lot of French front stations. That's awesome. So the hat is an open source behavior development framework for PHP. It's an official PHP implementation of QCumber. So QCumber was the third tool really in the evolution of BDD. So there was this thing called behave, JBehave, written by Dan North, the god of behavior development. And it was a lot of really ugly Java code that spit out really nice human readable results. But the code was just really ugly Java, really ugly Java. And then the next iteration was RSpec. If anyone's ever used PHP spec or RSpec, that was kind of the second iteration. And the third iteration was QCumber. So QCumber is a Ruby project. And now there is a QCumber for every language out there. So QCumber is QCumber. There's QCumberJS for JavaScript. There's QCumber for Java. There's Behats for PHP. There's Behaving and Lettuce for Python. And the list just goes on and on and on. And they have some things that are very common. We'll get to that. What I can tell you is it is one of the easiest implementations of QCumber to get up and running. You are a very fortunate PHP developer. If you're a Java developer, you're going to try and steal everything you can from Behave. Okay. It has a lot of really nice extensions that take away a lot of the work from what you're going to have to do. And it works really, really well. So you're going to be able to get up in 15 minutes. You can have everything necessary to test web application very crudely without having to write any code, which is awesome. And all these other languages, they have extensions that aren't so great. They don't work so well. And only work usually with Slenium. Where the hat using Mink, which is the web driver, it can connect to Slenium. It can connect to five or six different things that provide the same functionality for doing testing of applications and websites. The negative of that is that it's a little bit slower because you have a level of abstraction. It's not written directly for that driver. It's written to use for any driver, which can make it a little bit slower having to send more commands over to Slenium because most people do Slenium. So to install the hat, there's two ways to do it. You can do a FAR installation. If you know what a FAR is, it's basically a PHP executable, it's a PHP archive. It's going to be a single global install. You can always stick it inside your project, but that's just kind of weird. And you have one version for all feature contexts, which may not be a good thing because you may have certain projects that write they're newer, some products that are older, and they may need to utilize functionality, and it may mess you up having one global one. It's kind of like back in the day when you had a single PHP unit for everything, and you hated your life. You can also do a project installation to be a composer, which is the way I always suggest that you do it. Because your testing, the versions of your testing tools should go along with your code because you're using particular things as a part of that version of the testing tool. And your version of dependencies are tied to the project. So the components of the hat are a command line executable, a configuration file, feature context or contexts, which is where you put your steps, and feature files. Feature files contain the definitions of the features and the tests within them. So you need the command line executable to make it run. You need the YAML file to be able to tell you things that are very specific to an environment oftentimes, and as well as where you may look for things, and which context it needs to load to be able to provide the steps. And your feature files have all the information for the steps. So the command line executable allows for the initialization of the environment. So if you type the hat dash dash init, it will set up all the things it needs to be able to run, at least the directory structure and create a, actually it doesn't need the YAML file, but it creates a features directory. It goes and creates you a skeleton for your feature context. Before you run that, it's going to complain that you can't find anything after you run an it, and you run the hat and it'll say, I don't have any steps, I don't have any features, but I ran and I'm okay. It also allows you to run your features. So you can run a feature, one feature file at a time. You can filter it by tags. So sometimes you'll only want to run something that's currently in progress. If you're doing it locally, you may want it to run just for particular bug ID. If you make a tag for a bug ID, things like that. It's also going to choose your environment, because you can have a configuration for multiple environments. And so you're going to tell it which environment configuration file to use. It's also one of the super handy features is the fact that allows you to list your step definitions. So when you're sitting here writing these things, and you're writing all of your feature files and putting all the steps in there, you'll get an error saying that, oh, hey, this step isn't defined yet. But you know that no, this step is already defined, which means you had a typo somewhere. And you need to figure out what it's actually going to be. And instead of having to go sifting through all the code, you can just do the hat dash dl and it'll give you an actual listing of the step definitions. And so you can go through there, or if you're like, I need to do this, and there might be a step, I don't know. Because by default, it comes with hundreds of them. So you need to go see, is what I need already done so I don't have to recreate the wheel. So that is super nice. That's actually all part of the cucumber specification, which is actually kind of nice. So the configuration file, which is the behatt yaml file, by default, you can call it whatever you want, as long as you tell the command line, the command line executable, which one to open. It's split up into profiles. And so you'll have multiple profiles. So let's say you want to test. I guess it's like depends on how you want to do your profile. So we'll do profiles of different environments. So your a lot of times it's just going to be the base URL of the application that's going to be different, but everything else is going to be the same. Or you may have alternate credentials for things that you might need to do. But they're all going to inherit from the default profile. So you start off with a default profile, and then everything is going to inherit, inherit and override those other settings. So if you have a setting that's common to all of your environments, you just put the default and it will always be there. It allows you to configure custom auto loader paths. Not as super necessary today, but when behatt first came out, we did not have PSR0, and we did not have common auto loaders. So that was actually super important. By now, by default, it's going to look inside of your features bootstrap directory and load every class inside of there. And then it's going to use your standard composer auto loader. It defines a global tag, sorry, global tag filters. So if you're, you can create an environment where I'm only going to run work in progress or you can create, I'm sorry, a profile. You can create a profile that's only going to run work in progress features, or you may want to have it skip features that are work in progress, or skip ones that you just say, this doesn't work, I don't care. You can just tag it to say stop running this test, I know it's failed, stop failing. It defines output formatters so it can just like run a unit test, it can output to the standard X unit format or whatever format you need it to actually work for. It defines feature suites, much like unit tests, you can set test suites, you can do the same thing with feature suites, and it configures extensions. So most of the work that you're going to do with behatt in testing, real world testing, is going to be with extensions. And most of the things that you need are already provided out there, which is super awesome. So feature context, okay. So a feature context is where you define your actual backing code for steps. This is where PHP code goes in feature context. It may extend other contexts. I don't really suggest doing that, but it's the super easy way to get going. It can also access other contexts, which is the way that you really want to do it. So you want to do for feature context, I would really, really suggest composition over inheritance, we're going to be accessing the other context as opposed to just extending, let's say the main context, which is what accesses all of your web pages. It can add hooks for pre and post hooks for a tag executing when you're executing scenarios under a tag, when you're executing steps, scenarios, features and suites. So a lot of times you may need to have a particular thing set up or make a particular thing cleaned up when you're done. So one of the things that I do for my job at BDD is that we use test users. These are randomly generated test users so that you don't collide with other tasks because we actually run them in parallel. And when you get done, you need to basically unregister that user so that it doesn't just clog up the database. It's a test user, it doesn't need to belong there. And so at the end of the feature scenario, I have a list of all of my users that I created and I have a hook in there that goes and just tells the API, delete this user, delete this user, delete this user, delete this user and cleans up after itself if I don't need a bunch of garbage in the database. Sometimes you may need to create a session, a login session, things like that for particular steps where you may have to get like an OAuth token or something crazy like that for it to work. So those are the types of things that you can do. You may also want to do stuff for kind of doing browser manipulation, but that just gets a little weird sometimes, but sometimes it's needed. So we are talking about Ruby and Ruby loves to talk with cool cute names. So if you don't know what a gherkin is, gherkin is a type of pickle and a pickle is a pickle cucumber. So for a cucumber, you have the language called gherkin. Thank you, Ruby. So gherkin is a domain specific language, DSL. And if you don't know what DSLs are, don't worry about it. But it's basically, it's a language that has specific formation and specific ways that it's used so that it can be interpreted properly. And so from the three A's of testing, arrange, act, and assert, you have given, when, and then. Right? So given I can access the website, when I go to this page, then I will see that, right? So that's kind of a test for that. So if you want to see what gherkin looks like, let's say you have a feature called home page, which actually shouldn't be home page, it should be feature called login. And basically saying, oh, hey, Sarah's login link. So you need to make sure that your login link is always visible to the user because that's important to some people. So given I'm on the home page, when I click login, which means it's there, then I will get to the login page. And that could be a very specific feature all into itself. And so you may have scenarios that say, well, I've already logged in, but I'm not going to go to the login page. It may go somewhere else or it may not show. There are a bunch of different things you can do. But this is more just an example of how gherkin works. So this is natural language test. And this is your test, right? There's backing code that we'll get into in a minute. But that is your test. So a very non technical person can write these tests as long as the steps, the backing code for the steps already exist. They can find out what those steps are by just using the be hat band line tool and getting a list of them. And so it's super awesome. And it's the business person can read this. If you if you if you love domain urban design like I do, and you've read the book, and you're really going through the thing they tell you to do is show your unit tests to your business owner and let them approve it. I don't want to show my unit tests to my business owner. I don't want to have to explain to them how this works and why it works, even though it should kind of make sense. Some of the business owners just would just lose their minds if they lost a code. But they can read this, they can tell me if it's right or not. And then you have backing code, right inside your feature context. You have you have a method on a feature context object class. And it's going to contain a dock block. So if you it's when it first came out, it was all the hotness doctrine had just announced and started introducing annotations. But now I guess it's everywhere to code. We have a dock block that's going to use a matcher for the step. There are different types of matchers that they have. Thank goodness for PHP or for the hat three. It uses turnip. It used to use regular expressions. And so I had to learn how to write really good regular expressions. But now I don't, which is awesome, because most people it's a it's definitely a learning curve, learning how to write random expressions. Turnip super super easy. It can contain examples of the dock block now. So it used to be that you had to write this step, this, this matcher, and you would see the step and you had, oh, this is just a name. I have no idea what it's actually going to do. So you can actually put in more information now with the new version of the hat, which is pretty awesome. So you get a description and you get examples of how to use it. So that's pretty sweet. So here's what a step looks like. So opens homepage is the description. So you're actually see that when you do the list. And you have examples, given I'm on slash, when I go to slash, because this one actually has two different, which is now supported, multiple, multiple matchers. So the same function, you're going to use as a step in doing your action. And you may also use it as a background. So those are two different measures given and when. And you may have different wording for it. So so we have you'll see here when you when you run the listing for the mid context, it has going to the homepage, right? So you can say, given I am I'm on homepage, I'm on the homepage. There's a lot of different variants that you can use. And you can actually document that stuff right there in your doc blocks that you're when you're writing a step, and you're listing it out, you can actually see what it's supposed to be. So it's super nice. Any questions about that? So we've rolled right through the introductions to be had to behave. This is the this is the time to ask questions about any of that because the next thing is the demo and we're going to do it after there's going to be a break here in about eight minutes question. So I understand that this PDD is target for something that you have some business effect on it. Can we build PDD for developer, target for developer, like even something developers be able to end new page easily? So at that point, so if even if you're your business owner can be internal, right? So if you have an application that developers use, right, it has it's an application of features, and those features have business use, and they have users. So if you like, internally, we have a dashboard application that's only accessible to developers. So for configuring accounts and setting up user accounts and credentials and things like that, we have those. So you can actually do it internally. And you can use cucumber as well for testing code if you wanted to, I wouldn't do it. It's a lot of work and coders, you should like writing code. It makes more sense to write code instead of writing text, because nobody really needs to see it so much. But there is no requirement of what you have to actually interact with. It's again, it's just a testing tool. It's going to use natural language to write the test and it's going to do natural language when it gives you the responses. So you can have it test whatever you want. But for doing behavior driven development, you need to test behaviors. And you need to test behaviors atomically by the interaction with this should not affect something else. So you want to test that feature together. So if it's that a developer can't do, you know, in order to do this as a developer, I have to be able to do that. And that's, that's story B to D right there. So that's your question. How about refactoring? So refactoring, this is amazing for refactoring because your feature doesn't change just the code underneath changes. So your test doesn't ever change. Until you change your interface, your test never changes. So I mean, if there is a task like, okay, we have to refactor this code because it's already messed, can we build BDD for it? So one of the things, when I first started using BDD, as I inherited an application, that in their defense, these were people who were PHP for developers, this is a while ago, that moved to PHP five. So objects, they didn't really understand object theory very well. They don't understand objects. So they had two different frameworks that they built themselves. Because until recently, all the frameworks from PHP were terrible. If you're if you're a Zen fan, I'm sorry, I was never a Zen framework fan myself. I tried it. I didn't like it. So it had two different frameworks, and one of them had nothing but static methods. So you couldn't actually unit test it because it's just pulling in using singletons. Everything was a singleton. And so you can't do mocks, and you can't really do much unit testing. And then the other application used actual objects, but it actually, it actually displayed HTML to the screen by instantiating the objects of the constructor. The constructor had all the view logic in it. So completely untestable. And it's a very important application. And it would break all the time. And it's literally just we they'd ask for a feature, we change something and have some really unexpected side effect, and just wreak havoc. And so what we ended up having to do is we said, well, we can't actually write tests around the application, because then you have to refactor it. But then while we're refactoring, we're breaking things. So we decided is we can test the application. And it was before it had existed. So we did it in cucumber. And so we wrote functionality tests around the application. So before we refactored it, is that we made sure that we we documented how we thought it was, we gave it to the business owner and said, this is what has to work, right? Because we're going to change this. And if this is what still works, and it doesn't, and it doesn't meet your needs, then then it's going to be your fault. So make sure that this is what actually is supposed to happen. And so we had this negotiation process of going back and forth on properly documenting what the features were that they needed, getting those tests running, and then we could refactor and not worry about breaking things. So that's how I actually started using the hat because we were using cucumber and then the hat came out and we switched to that. And so I've been using the hat for since version like zero dot three. Because it's better to have an if you love Ruby code, I apologize. But I'm not a very good Ruby developer, so I didn't want to have Ruby code. So I was writing really, really terrible Ruby code. And I would rather write decent PHP code so that it's manageable for me. That's your question? Any other questions? Yes. So DDD is going to test your, you have unit tests, right? You're already going to have, it's going to be a lot easier for you if you're already doing domain-driven design. Because you're going to have ubiquitous language. So you don't have, because that's a big, if you've ever translated or if you've ever moved from not using DDD, domain-driven design, using domain-driven design, that's a big conversation. Oh, TDD, okay. So test-driven development, BDD is test-driven development. You write the test first, but it's not about the code. So when you do TDD development for writing code, using PHP unit or using PHP spec or whatever tool you're using, that's making sure that your code, your object works. And that's the difference. That's still necessary. Your code still has to work. You still have to know when you're breaking your code so that other code isn't going to, the other code in your code base isn't going to work properly with your object. BDD is making sure that your application works as the users expect. It doesn't care what your code looks like. It doesn't care if your objects are broken. It just cares that the user has the experience they're expecting. And so it's a much higher level. Right? So in test-driven development for code, it's at a very low level, making sure that your objects are formed properly, that the methods are doing what you expect, that they're not having adverse side effects on data that they pass to each other and they react in a particular way so that while developers are writing code, it works the way they expect. Behavior-driven development is making sure that I have a business. In order for my business to make money, I must be able to do this. Users must be able to plus take Amazon, right? If you can't make, if you can't check out and pay for your cart in Amazon, they make no money. With the exception of AWS, I guess it's a little different. But if you can't deploy, if you can't deploy your EC2 instance, they don't make any money because they can't charge you because you didn't deploy. So that's a very important feature to them. How the code does it, from the business side, they don't care how the code does it. They don't care if the code is pretty. They don't care if the code is tested. They just care that don't ever stop someone from deploying an EC2 instance because then I can't charge them. And so that's when BDD is going to actually go out there and make sure. And like I said, the other thing it's going to do is it's going to tell you, if you have a failing test, you're going to be able to make a very intelligent decision on whether or not you should still release or if you should roll back. Because you're going to know that this feature, this scenario of this feature is failing. And you can determine that, oh, we may not care about these users, right? This may be some esoteric feature in somebody who's that these are not paying customers, right? This only affects free tier, right? Free tier doesn't have this thing that they had yesterday. But everybody pays, their stuff still works. And we've just had this new feature where we can start charging more money because they're going to love it more, right? There's this new thing like elastic bean stock that's amazing that everybody can get away and use it because it's easier. As a business owner, I want to put up that thing that my paying customers are going to pay more money for. And I'll make a really heartfelt apology to the free tier people who don't have this function anymore. And it helps you make a really good business decision on what's working, what's not working, as opposed to this object here has a failing test. And I don't really know what it affects. I can maybe try and find out everything is accessing that method, but I don't necessarily know how that's affecting the user. I just know that these sections of code are not working, but I can't go to a business owner and say, I got a failing test, and it's going to affect this much revenue until we can get it fixed. PDD can allow you to go, you work with a business owner to determine, okay, how much money is this going to cost me, opposed to how much money is the new feature that we're pushing out for the broken, according to Jenner. So you can make very good business decisions as opposed to just saying, I have a broken test, I can't release because I don't know what's wrong. I don't know what the effect is on the users, I just know that the test is broken. That is your question? Okay. All right, it's time for break. How long? 15 minutes. Yeah, if you guys can come back about 15 minutes, 15 minutes, just a break. So that's, that's actually more food from this morning's breakfast. So if you're still hungry, you can have coffee, tea, whatever it is, it's still over there. The toilet site of this AWS, so yeah, go ahead, right, and be back here in about 10, 15 times. Thank you very much. You need to make sure you can access this URL. So I've got a reverse proxy serving from my laptop. It hits that page. So if you can access that, you'll see, you should see, you should see that. And if you've never used Ngrok, it's pretty awesome and it's free. I have a paid version, so I don't have just kind of random names for the subdomain. So I don't know how well Wi-Fi is going to work here. I've pre-installed this stuff in case we start getting, sometimes you'll start getting some pretty wicked things from GitHub saying that we've exceeded our limit because we're all probably going on the same IP address. So you may run into problems doing the composer install where you get rate limited. If you have a GitHub account, all you have to do is just go ask you for credentials to make sure that we're not just basically trying to get them a general service. If you're not, then you should be fine. But is anyone having a problem accessing that URL? No? So we're all good there, right? Okay. So this is the, if you can, can everybody read that in the back? Okay. So in order to install, install the hat and the pieces that we're going to need, we, Sliny Driver, if you don't have it, if you're not ready to do that, don't worry about it. It's actually fairly simple to do. But you can do this whole thing without it. It's not a problem. Because that's what the Goot Driver is going to do. It's a headless PHP-based browser, basically. It just does curl, pulls down the web page, and then does some transversal inside of there using XPath to try and pull out part of it. That's a really nice translation from CSS to, CSS to XPath. The be hat, the hat, sorry, I keep calling it wrong. The be hat make extension is what's going to provide all of the steps, which are really, really nice. So who's not done the composure require yet? Who hasn't finished that? Okay. So if you can do it a little really quick, that'd be super awesome. So we can kind of move on. Is anybody getting rate limited by GitHub? Nobody yet? Okay, that's good. Last time I did this, super rate loaded. Maybe it's because it's coming from AWS, who knows. I know there's a lot of typing. I apologize. Yes. No, it won't be problem. It's going to complain that it's slow. You're going to get this warning from Composer, but Composer just started doing that like I think a few months ago. So it's kind of annoying that it complains, but I don't know what you're talking about. Yeah. So while everybody's getting this up, does anybody have any questions about the requirements here? Those, of course, have, you know, 100 other requirements. You'll see that when you do the install, but other require. You want to make sure if you've gotten to this point, you want to be inside of a project, and you had to have already run Composer in it. So it needs to be a Composer project. So that's all the best stuff. So if you've never done it before, right, if you've done a Composer in it, if you make a project directory, whatever it is, project, it's a little typer. It's going to worry about that right now. When you do a Composer in it, it's going to have this kind of step-by-step walk you through. None of this actually matters when you do the Composer in it to set up your Composer project. It's going to give you, based on your username and your directory, it's going to give you a default. We're not going to be publishing this to anyone, so it doesn't really matter what the name is. Just kind of accept the defaults and move through. So it's going to ask you for a description, which you don't care about. It's going to ask you the author. You can just end the skip, or if you like the author, that's fine. Minimum stability, don't worry about that. It's got a default to prod, which means it's not going to use a beta or alpha version. Package type doesn't matter. Just accept these on through, and when it asks if you want to do interactive dependencies, just tell it no and no. That's really all you need for a Composer project. It just has to have a name. Actually, it just says to have a file, but you generate it, and then you can start running Composer things. But if you try and run this Composer install, before you do that, it's going to argue, it's going to complain that you don't have it set up as a Composer project yet. I forgot that set by apologize. How do I get back down there? So how many people have the Composer stuff installed already? Nobody? One, two, three. How many people are stuck? Okay, so what kind of problem are you having? Command Do you not have Composer installed? Okay. If you solve the homework, it should be everywhere. So just you just like Composer and nothing happens? Oh, so you're in the end, right? So I would try this, go to the Composer. Make sure you do like a brew. So yeah, let's see. Okay, so you So if you can close it in, don't worry about the interactive. Just read the one from the end. Controls. Yeah, I'm just going to close it in here. I didn't hear it, just do it here. Yeah. Okay, I'm going to close it in here. So just do this one. Come close it in here. I'm going to ask if you want to do the... Center. Center. Oh, of course not. Center. Center. Center. And then you pick up. Let's see now. Center. Okay. Now you're nice and uniting that because you're required. That's nice to have. Then you got stuck on a Wicked Loot. Okay, anybody else stuck? I know this absolutely works in Windows because the last time I did this, there were a lot of people with Windows questions, and I haven't used Windows in a long time. So I went through and did it all in Windows, and I know how it works. And we have a lot of Macs here. If it was primarily Windows, I would actually do this in Windows on Parallels. But that's really slow and annoying sometimes. And I mistype everything like slashes and backslashes all the time so it takes a little longer. Yes. Just to dinner. Just accept all the defaults. I'm going to ask you if you want to do the interactive setup. Tell it no. This doesn't really matter. The defaults will be just fine. The default stability level is production. So it won't allow alphas, betas, or using the sources. It will offer sources. Which is fine because you won't need to find the stuff for each. It's a browser. Yes. It's amendment. What's that? It's a voice page. It's a page. It's a Facebook web browser. Why is it called Blue? Then this was a... No, why'd you put the Facebook web browser? In Chinese. It's the same browser. It's the Slenium 2 driver. Oh. Yes, the Slenium 1 driver would give you a problem. So yes, it's the Slenium 2 driver. The Slenium 1 is absolutely deprecated. And it was for Facebook. Got it. Actually, Slenium 2 is going away as well. Slenium 3. So if you actually try to install it, it will be really confusing because if you try to install the Firefox driver, it will say this one is only if you're using 3, but 3 is only in beta. But I did install it that way and it works just fine. But now you can't just do direct access to the browser like you couldn't slid to. I just want to understand it makes it a lot faster. So if you've ever used Slenium, especially in a grid, you'd be very happy that it's going to be faster. Yes. Could not pass version constraint. Could not pass version constraint. Okay. What version of PHP do you have? PHP 7. PHP 7. That actually should be fine because I'm on PHP 7. Not pass version constraint. Yeah, I'm pretty sure I'm using PHP 7. Yeah, I'm pretty sure I'm using PHP 7. Oh, yes, I'm on PHP 7. Yeah, so PHP 7 should be a problem. Yeah, so PHP 7 should be a problem. Let me get back with you on that one. So if you actually type this in, mine will go really fast because I've already downloaded everything. And so when you run it, it's going to do all this kind of crazy stuff, which I imagine most people are seeing. You get the nice warning about XTbug, enable onComposer, don't worry about it. And it's going to try and figure out, which is going to be a slow part. I want versions of everything it should be reinstalling. So let me see what I get when that happens. What project on my head? Yeah, so mine works. So you may have a typo. So he had the same problem. We record the Selenium driver instead of the Selenium 2 driver. So because it should work. If you have any version 5, 6 or better, you're not going to have a version conflict. If you've got PHP 5.5, you may run into problems. But PHP 5.6, PHP 7, and I haven't tested against 7.1 yet, but it shouldn't be any different. I guess it may have to do with the depending libraries, but for the most part, these are all, this is all the same team, so it shouldn't matter. So if you're still having problems, we'll come back. All right, so now that you've done that, you should have in here, you should have a vendor directory, that has a bin directory, that has a be hat. Sorry, the hat. I don't know what causes me to get upset because I'm proud to be proud. So when you run it, you should get an error. If you run correctly, when you run vendor, bin, be hat, enter, you should get this feature content class on account. This is the command. Oh, that's not really high. I apologize. You probably can't see that. So let me make this pretty still. Can everybody see the whole thing now? Yeah, so if you type vendor slash bin slash be hat, you should get this error because it's not initialized. But it does mean that everything is installed correctly. It's not saying you need to install the requirements or any of this kind of nonsense. That means you're set up correctly. That's how we're going to go right now. So the next thing you want to do is you want to run that same command and type dash, dash, and that is going to initialize your project to use be hat. So it tells you some nice stuff. And so basically what it's done is it has created a features directory, which is where you put your feature files. It has created a bootstrap directory underneath that, which is where your feature context go to get auto loaded. So you don't have to register them with your auto loader and all that kind of nonsense. And it also created a feature context for you. So it give you a class called featurecontext.php which looks like this. So you've got features, bootstrap and a feature context which I'll make bigger. It's just like that. That's what your feature context looks like right now. It's just an empty class so it can actually be instantiated. That's where all your steps are going to go. So right now you don't have any steps. So if you go in here and you execute your be hat I think again you do a dash DL which is dashes D for step definitions and L is list. There's a couple different things that you can do. It'll actually I think tell you in there. So it comes back with nothing because there are no steps. And if you run a hat again they will say no scenarios no steps zero seconds. But all that use up seven and a half minutes to do nothing, which is awesome. That's not a very lightweight program but it's a very awesome program. So the next thing you need to do let me see if I can go back. This thing is going to work. So we've done that. So now we need to add our context to our config. The context are what are going to give us these. These are the libraries we're going to use inside of the hat. They're going to give us all this wonderful magic that people have spent years building so that we don't have to do it. And let me show the notes. Where's the notes? All right. Why can't it show notes? All right. I'm going to go back to this real quick. That's it. Right. So we've done that. We set this up up. So we've done that. You can see the help text if you type dash age. We've initialized right. The dash dash and it we've verified it. So the next thing we need to do is we need to add context to our configuration. So we're going to create our inside of our default profile. We're going to add some configuration. So we'll go back to here. I was just switching back and forth all the time. So inside of our project, we need to create a behat.yaml file. So create a new file and it's just behat spelling behat.yaml. You can call it whatever you want but it's able by default load the behat.yaml file and all that you need to do. And what you want to put in there is this is the the construction that's going to tell it. I apologize. So we're taking our default profile and we're going to set up an extension section and the extension is what provides all of our browser functionality. It's going to provide all these wonderful steps to interact with the browser. And it needs to be configured to know what drivers it should use and also the base URL of the application. You could just tell it to always go to a particular URL, but that's not going to work very well when you go from development to release candidate to beta to wherever it's going to go before it goes to production. You should be able to run these tests against production to make sure that when you do a release that things still work. So using the base URL is going to be this is the part that's going to be different from environment to environment. And then you can just tell it to go access a particular you want to be at the root level when you can tell it to go access this URL or this sorry this path. And so it'll work fine with the access in the path. If you've ever used one of the HTTP clients like Guzzle will oftentimes ask for the base URL and then you just tell it to go to a post to this, to a get to that and that's what's actually going to end up happening here. And the way that you can tell if you're let's just start doing this in here how about that. Do you want to make this bigger too? Yeah. So so the way that you can actually test to make sure this stuff is working properly is if you run number one if you just run the hat which is vendor the hat. If you run the hat again and it's correct it's not going to give any errors that's the number one thing you want to do and if you run dash dl again it should have had a bunch of steps. Oh I haven't had the feature I'm sorry. You're just going to run the vendor bit by hat to make sure it's not broken we're going to add in, we're going to have to add the feature context later this is just setting up the extensions I've got to step ahead of myself. So if you type this in and it's a the hat.yaml and you run vendor bit by hat and you don't get any errors then it's correct. Right? Then we can move on from there. Who's not ready to move on? Okay. And so yeah the other thing it's doing is saying that oh we want to use the GUIT driver and we're not going to pass any configuration to it you could pass configuration if you wanted to if you want to do configuration of GUIT although the documentation for that is pretty sparse actually the documentation for all these are pretty sparse you almost have to read the code but they're getting better. You normally don't have to do much. The only thing that you want to do with Selenium 2 is configure some of the things like which browser am I going to use and all that and that's just using the standard Selenium configuration for the browser arguments. If you're you know what Selenium 2, if you use Selenium 2 before you don't want to be in browser arguments. Those are configurable in here as well. Okay. Anyone not ready to move on? So the next thing we want to do is we actually want to set up the slide. So we want to actually get the mink context to get access to the steps. Right? So, the next thing we're going to do is we're going to do that. I've got to find a better way to do this. So we're going to set up test suites and we're going to say what context are available with test suites. The HAT3 made this a little more complicated but there's very specific reasons they did it and I've heard the arguments and they make sense and it's more complicated. So the next piece we're going to add in here is we're going to add suites. So these are test suites. If you've done unit testing, you're familiar with test suites you probably never use them. You just know they have to be set up. I never do test suites. So one of the things that suites allow you to do with different contexts and the reason that it's set up this way is that you can run the same test as different users to make sure that the results different types of users, different roles to make sure they're the same. They're the same steps for the way it works for different roles so that's the way they set up this way. I never use that functionality so I don't really care but it's apparently very important to someone. I don't know who that is but it's very important because they did a lot of work to add this in. So default suite is all we're going to use and again everything extends to default if you need to have common configurations. So if you add that in and you add it incorrectly you'll now get a bunch of steps when you run that which I'll show you a second after I don't have to take that down. So for these things if you're going to be if you're going to have multiple environments so you have this set up here and let's say you wanted to have something for beta which is going to have a different URL you would just make a beta and then set up with a different base URL and do it that way. Another way that you can do it is also do it with command line arguments to set up pieces that you need to set up. You can do that as well setting up environments but it's usually much easier just to have a default and then override the base URL with another profile beta, RC production, whatever it needs to be so all that stuff that exists in there. The other thing I would also suggest is keep your test with your code. I've done it both ways because I've actually worked at where the QA team was responsible for the BAHAT test and development team was separate and the code was separate and they get out of sync. So you don't know which test version am I supposed to run with which version of code so it works out a lot better if they're all in the same code base so I know that these tests run again so my tests for beta are in my branch that's going to beta or my tag that's going to beta so I know which test I'm supposed to run against it but I think it's failing because they haven't been released yet to that particular environment so I'm sorry this is going to be everybody ready? So now if you run vendor bin BAHAT vendor bin BAHAT-DL you get that which doesn't translate very well on a large screen but here are a bunch of steps you didn't have to write you should be very happy about this very very good steps the ones that are super super important are going to be and I press that button there's some very complex expath in here to identify that button right well it's going to be the text inside the button, well it's going to be the idea of the button it's going to be a class of the button it's going to be a link that has that particular text there's a bunch of different things you can do as far as pressing buttons, following links and filling in form fields the steps provided for filling in form fields I copy this expath for every other language I use because it works so well they have really really really done a really good job making sure that when you try to fill in a field there's some very complex expath that says find me a label field that has this value and the actual input that that label is for so it gives you amazing stuff so if you're getting all of these things when you do a vendor bin behat-dl then your feature context will be installed properly if you're not then we've done something wrong anybody have any problems with the feature context yes just wondering what this is what does P oh ok so these this is what you used to have to do so this right here is the placeholder so this is regex, regular expressions and it's saying placeholder page so there is a variable sorry there is a parameter in the method called dollar sign page and so it knows that this value goes into dollar sign page in the method when it calls the backing code so I can actually probably just show you that too so if I just search for let me find real quick the project and find that in products libraries so I can actually show you what it looks like there it is comments so this is actually the code for that so here's your step definition and so this is a regular expression so this right here this question mark P says this is a placeholder so it's going to take whatever value you stick in there so this is anything that doesn't have a double quote all the text between the quotes it's not a double quote we'll get put into this variable you don't want to use that you don't have to use that anymore that is awesome this is what you used to have to do to write them so this is the oh yeah there may be something here there may not be because to make it flow properly and make it feel natural speaking you don't want to do say like when they go to the home page when I go to home page and I go to this you can also just say when I go to the home page and to click a button instead of when I go to the home page and I click a button it doesn't it's a preference thing that doesn't really matter to most people but some people really really care that they don't have to put I in front of everything so this is what an actual real life step code looks like it doesn't really do a whole lot right it's just something to identify that it uses for a given and a when and then it gets this value that you put in there so you say when I go to slash login and it's going to visit the path slash login there's a bunch of code for me I'm not but that's really all I can answer your question yeah and so we're all very fortunate that we don't have to do this anymore because doing all this nonsense really really no fun at all I don't know if they have any of this stuff in here wish they don't but here's a lot of a lot of things you just got for free and a lot of things you're going to reuse a lot okay so the first thing you want to do normally is you want to make sure that you can access your home page because if you can't access your home page your website's not working therefore everything's broken and why do any more tasks right so the first thing that we're going to do is we'll make a new feature file so inside your project under features we'll make home page.feature home page.feature so one of the things if you're a JetBrains fan like me and you like PHP store it comes with a plugin for doing feature files so it does all this nice highlighting and stuff which is why I'm using this instead of VIM or one it does auto-complete I'm a turbo-speller and if I type myself it will be wrong so you just need to put in a feature and so this is home page is accessible I don't care what you write in there it doesn't really matter as you can see I just dispel something right so in order to access the site the site as a visitor I can go to the home page and see stuff now your home page you may have very specific requirements that if they come from a certain place and this is accessible this is not what we're doing here today we're doing something very simple right so on this particular one there's no background because there's nothing to set up so we're just going to write a scenario and all we're going to write for this particular scenario is we're going to write a happy path home page displays so I don't know any way to break the displaying of the home page be perfectly honest so we're just going to do that okay and so now we write steps so normally the first thing I do is oh I need to go to the home page so the first thing I'll do is I will go here and I'll look at my steps I just printed it out and I should see if there's some way that I can go to the home page oh okay so here's a step when I go to the home page super awesome so I will say when I go to the home page so that's my action I didn't have any arranging but I have an action so I need to make an assertion so on my home page it says my applications landing page that should work so I should when I go to the home page I should see my applications landing page your home page you probably won't see that it identifies that page that you care about you might say I see today's deals or whatever the case may be so then so I go look and see what I've got here I'll take a look at my steps and there's one that says then I should see there we go then I should see text we don't want it in elements then I should see text so we have a step that says then I should see text so I'm just going to verify that I can see text so then I should see your applications landing page so if it's a very simple example all we're going to verify is that if I go to the home page I see that text anybody have any questions about that ok so now since I now have steps if I run vendor bin behat it should execute steps it should pass because I wrote it right if you have a typo you will get this which is awesome by the way so this lets me know that it says hey this step doesn't exist and so this is the new this is the new way of doing the matcher this is a turn up matcher where you just do a colon in the argument and it figures out what the argument name is and it automatically says I don't have quotation marks turn it matching is awesome so you don't have to use regular expressions but I can tell right here the reason this didn't work is because I had a typo so if you're doing it from memory and typing things in and it's wrong you look here and it says oh I couldn't find this step just go back to your list go back to your list find out how it's actually in there because I always do them wrong anyway once I know they're there go back and find it it says oh it should be spelled correctly so I'll fix it the other part is and this is the great part and this is what I do where I work is that you may not have all of them written yet so you can write scenarios and features for things that are not complete and document them and then fill in the steps later and then eventually the test will run because they have all the steps that they need so you can go through and document these things if you're a QA person find all of the tasks or all of the features and steps that won't run because the backing code hasn't been written and they'll run those manually and as we move along farther and farther and make more complicated functionality for the backing steps then it becomes automated so you can still do your documentation you can still write your features and your scenarios and do all this kind of legwork to make sure that you're ready to do it and be able to utilize that as both documentation and manual testing because the steps are human readable so when it spits out oh hold on let me run so when you actually run it the big thing is this is human readable and that's very important so one of the things that I really really push is this term that people are getting tired of me at work saying is you need visual verifiability of your steps if anyone who has never seen your application or has never seen your code cannot follow those steps and execute the test manually it's wrong because no one should have to have any knowledge about your site your application or your code to be able to follow those instructions this is why it's documentation right so when I go to the home page everyone knows how to go to a home page and then I should see application's landing page so most people know that the home page is slash if you don't you can find that out really quickly your application's landing page is on there it's very easy for me to visually verify and visually follow those instructions to validate the test and when something goes wrong and it fails if I go and change this sorry so when I go and change this to fail it's going to look like that so what I'm going to be able to do as a developer a QA tester actually a lot of our test validation happens with our office manager she helps out on testing so she can just follow this failure and visually see that either the page is throwing an error or that section is missing it's not there so she has no real knowledge of how the application works she has no knowledge of any of the code but she can still verify our test so it's because your application's two ends isn't there so you should be able to follow the green and then see why this failed you should be able to absolutely see why the failure happened just by going to the web page which is super awesome if you've ever done slonium testing this will make you happy if you didn't get that with standard slonium testing you get failed to start false it's true screenshot no idea how to recreate the screenshot no one except for a developer can go look at the code and figure it out this way anyone can go figure it out any questions about that so you should be able to see the facts what I'm saying I should be able to follow these instructions and then be able to just look at the page so one of the things I didn't do is I didn't say and the path slash home slash slash body or slash html slash body slash I didn't put a bunch of css in there I didn't put a bunch of xpath in there to actually locate the text I just said that you can't see this on the page so that's visually verifiable the text is part of class name then that's not visually verifiable and that's bad so we cannot check it so one of the things you shouldn't do is you shouldn't use xpath and we'll get to the I'll show you that a little bit but things that are going to be very specific that don't follow kind of an html standard so when you're filling in forms you should use the label of the form field you shouldn't use the name because number one name is change IDs change classes change because those have nothing to do with the name of the how the user identifies a field on a form so that's either going to be a label or it's going to be I always forget what they actually call that but the example text inside of the field or it could be on a field set with a legend like there are specific ways that a user identifies those and actually in behalf for the most part they give you a way to use those to identify those pieces but if you have something custom like we'll see here in a minute with the errors for Laravel it has its own custom way of showing an error you should make your step like so how the step works underneath it doesn't matter to the person who's going through the verification is that the text makes sense and I say that and I see . if I find the input and I find a sibling that has a CSS class that has that some people may know that you can just go inspect it and look at the class to make sure that's right but that's a very specialized skill set so you don't want to do that if all of your errors for your form fields are going to look that way then you can just say and form field X has an error you can read it and visually verify it without having to go look at HTML plus the HTML could change that make sense so in general you need to prepare it for someone who has zero technical skills you should prepare for your user how is your user actually going to use it the user is not going to go look for a form field that has a particular class or ID or a name and then go enter text into it and also let's say scenario like registration you have two steps register and then there's a function so those two are two separate scenarios that you take it depends on whether it's one page, two page or six pages shouldn't matter is what is the feature if those two steps are part of that feature and they have multiple scenarios where you fill out but you don't confirm those are different scenarios for the same feature of registration so you don't really care, like I said, you don't care about the technical implementation the business is going to change the technical implementation over time totally what you care about is that the business has a feature which is registration and it has requirements in that you fill in these data fields and you complete the verification of your email address for whatever case may be that is their requirement to become a registered user and that's what you have to document and then you have to go through the scenarios of well, okay, if I don't have you may say, oh, if I don't have if I haven't registered, if I don't confirm and I try and re-register it as a pick it back up or if I try and log in does it say you need to complete registration or just say I don't know anything about you and then you can't use the username again because all these different scenarios that you can go through all that particular feature which may or may not be actually considered separate features but the big thing is that it has to be simple that a business person can understand it because a business person is not going to go verify your feature test to go take a look at XPath or CSS because one of the really powerful things I've used this for is I take that when it's working I will take this file and I will ship it in an email to the CTO, the COO whoever it is that I'm building this for and say if this passes and my feature complete is this acceptance or is it for acceptance testing if all of these tests pass will you accept it as complete and if they say yes then I know what I have to do to be feature complete so they can't come and say oh you didn't do this you're right because I was not told to do this and you verify that this is what it had to do everything else is a new request so you're able to work with them actually coming through and getting the requirements in a matter that's already for a test so three that's a really powerful tool I've been able to use in the last couple of years when I learned how to get more when I started doing these things it was just to not break existing code or legacy application so they were more technology I was more testing the technical aspects as opposed to what the business needed and over the last couple of years I've really kind of morphed into what this is really powerful for is you and the you as a developer the QA person and the business both know what they're supposed to what the actual application is supposed to do so a manual QA tester can so a manual QA tester can actually manually QA test with those steps they can just go look at your feature file and then do the test themselves a business owner can say yes this is what it's supposed to do and this is how it's supposed to react to these scenarios and a developer can write code and say it does exactly what the business asked for and then when you're building other code you can know that oh so when you go to the home page it doesn't say that and maybe you care and maybe you don't as a business owner you can say well the fact that it doesn't say that but everything else works I'm okay with that we can release with this busted piece right now we have a bug we'll release it with the bug and we'll fix the bug very quickly but I don't want to delay the fact that in my home page to not release this feature that my customers have been complaining about not having so that's kind of like the full loop of what the power of the stuff can really give you as well as reusability because we were able to granted it's a very very simple test but we didn't have to write a single one of code to test this we have not written any PHP if you want to do this inside of and with unit testing you've written like 70 or 80 lines of PHP by now yes are you able to define what landing page is so you can so landing page is slash right so when I go to the home page means I'm going to slash on my website how you can say oh then I have this form there's built you can do whatever you want with the test there's built in things for so if I do a dash DL you have built in things to say I should be on this page which doesn't work on every driver the URL should match a particular pattern so you may have like you go to the home page and it redirects you to an ad page or whatever the case may be this does not work the URL map pattern but it does work on some of the actual browser controllers the status code you can check so it should be a 200 especially if you're doing API stuff you might want a 201 you might want a 204 depending on what you're doing we just did this response should contain you can have response should not contain alright there's the other side of that I should see the following I should see a text in a particular element so you can say basically that's like you can check the title you can check that the H1 tag because everybody knows H1 HTML should only have one H1 tag right so you can say that the page header contains that value so you can check the header tag to make sure it's correct or whatever you need to do so there's a lot of things that you can check to see the elements are there not there or I should see 10 of these or 5 of these and those are all in there by default yes can you do what multiple 10 multiple 10 multiple 10 yes I should see right so yes you can do so if you want to do that so let's see and I should see what else is on that we can test and I can see welcome right so one of the things that it's going to do is you can actually use and and so and is going to instead of writing then I see this then I see that so you can see if you did when I go to the homepage and I do this and I do that it actually makes it flow a little better verbally and I should see welcome right wrong one so you do that and it's going to check I saw an application on any page and I saw welcome one thing that you don't want to do is you don't want to do a when move to a then and then go back to a when what you don't want to do is you don't want to do arranging do assertions do an action do an assertion because then you're actually testing multiple things right so just like a unit test a scenario or should only test one thing you can have multiple scenarios to test the other pieces and if it's it's a different piece of functionality it might be a different feature so you would put that into a background and it's going to be used that way or give it so the other thing you can do is hmm we've got some givens that come up but you're going to do some things you're going to be doing some arrangement one of the things that you normally backgrounds normally just have givens but you may actually do some assertion so given I'm on the homepage or given I have a registered user so if you want to test login you have to already have a registered user so you're going to have a given set that says given I have a registered user and that's going to do all the things that needs to do to be a registered user or if you're going to start working on your shopping cart adding things to the shopping cart you can say given I'm a logged in user so you have created the user you've logged in the user and you're going to work from there one of the very important things that you have to remember though is that all of these tests no test should depend on another test no scenario should depend on another scenario having been run because there are some modes where you run this and it runs in parallel and you will break things and it goes very very badly so if you're going to do things that are based on a user and a shopping cart you'll want to make sure that each one is building its own user with its own shopping cart every time and you may need to just randomly generate a user name and then build that user and that can be done in hooks or in backgrounds and you can get very complicated with what it can do with holding state and all these types of things inside of your feature context but this is an intro but all those things are very possible and I do all of them so one of the things that I do for my particular for my company is that we are an authorization as a service platform where you authorize with your mobile device and there's a whole pair it's a very secure process of creating a user and linking devices and doing all that type of stuff so our actual setup for a user takes about two and a half minutes to actually set up to actually run a test so we actually store that user for being used in that particular thread in that particular running of the tests so we'll just store it over there so that we can basically just reuse the same user there's a lot of things you can do with that based on your feature context where you can store instances of things for reuse if you have something that's very expensive to sell and the other thing that you want to do also is you want to clean up after yourself so the other thing that we do at the end of the feature test we're on is it's going to go remove those users from our database at the end so you don't have just a bunch of test users out there that people might be able to figure out how to guess the user into passwords and kind of do terrible things any more questions about that so, sorry yes can you get double-byte correctness? I'm sorry? double-byte correctness yes, yes, you can use multi-byte character sets it's written by a man from the Netherlands so it does French, it'll also do it does multiple languages so you can do Chinese, Japanese Arabic that's why one of the things that you have to actually install for this to work is MB string so it provides multi-byte character sets it also does translation so you can actually have the step you can actually have translations for the step definitions they come back in multiple languages so you can have, depending on what language you're using if you have the step definition of this right here if you have that translated for French it'll actually translate it back into French or Chinese, Japanese whatever you want to do so the default one is actually when I did the search down here you see it found a bunch of excellent files so it actually has translations for that's English, so the written by default in English in the code and it actually translates the steps into German if you're doing it in German Japanese so it has a lot of internationalization support as well as multi-language because it is the team that works on this actually they all speak three languages so it is very important to them any other questions about that that's a fairly significant feature that doesn't really do anything that's the very basis if you can't access the homepage nothing works so it's an important feature it doesn't really do much so the next thing we want to do is we want to actually we want to test user registration right so what we want to say is we'll create a new feature and this feature will be feature file let's call this user registration let's probably spell it correctly so we're going to create a user registration feature so our feature is user registration I'm sorry yep absolutely thank you thank you for reminding me so we're going to create a user registration feature so and here's an important thing as a visitor so we're defining what type of user it is it's very important to do this in all of your and all of her descriptions so it's easier to understand for anyone like what state do I need to start in right so as a visitor in order to become a registered user I must be able to register as a user and it may seem kind of silly this is just a very simple example and a lot of features that you're going to get for your business they're going to be a lot more complicated but you need to be at least have this very basic definition of who's the actor what do they need to be able to do and why are they doing it right you need to have context so that as a developer I have an idea of the context because if I have to make my own context I do it wrong about 80% of the time unless I have a very good understanding of the business I do a lot of pre-sales and post-sales work so I probably have a better idea of what the customer is asking for but a lot of the developers where I work they don't have that context so they have to do it based on their requirements so it's really quite nice if you can actually define the context for the developers as well as for testers because the testers may go this doesn't make any sense because this is not how it's supposed to work for this type of user and stereo so we'll do a happy path successful registration right so first thing I have to do is we'll do a background on this one which is user is registration page so given I am register so we're going to navigate to the registration page so if I go to slash register so what I didn't do is I didn't say given I click on register because that's a homepage feature so that's a menu feature that I can navigate to the registration page via that what you may do is you may create a custom step that says given that I'm on registration and then you can actually just write the code that says to go into the slash register yourself but we're doing a very simple demo here so that takes me here correctly right and so we have form fields here's some of the magic given to you by behalf then I fill in the following so these are tables and you can do this is what's called a hash table you can do row tables but this is just going to be a hash table so sometimes you would say let's say you have multiple values or we verify multiple values you could just put basically like a CSV file with a pipe separated CSV file that has your headings on your column and then you have rows for all those columns but what we're going to do is we're going to do formfilling which is a hash table so this is going to be name I don't know if that's email address I believe it's email address the dash mail address test user password by the way never use this as your password it is like the third most common password and it sees to figure out and confirm password and I press register and I press register there's the errors that should take me back to the home page so but I want to make sure that I have I can see my name so then I should see I don't I don't want to be headed so when you complete registration hopefully you would just give yourself like you successfully registered and then it would redirect or maybe something else but this thing just actually just takes you back to the home page and logged in so the only way that I can test this when it does when you do it if you actually manually do it so if I do I do it and register when it works successfully it takes me back to the home page but it also has my name so that's so this is the only thing here that lets me know that I'm now a registered user and it has my name on the page it's not super visible this large but when you do that it's a lot more visible so with this particular very simple Laravel built this for me in like 5 minutes website that's how it's going to be my verification that if I successfully register then my name will be on the page how about we should also change and I don't see registration because I guess my name could be there with an error sometimes this stuff if you have very simple pages so for register and I should not see register so the first thing I want to make sure is that when I submit I don't see register I see register I probably got an error and we're not going to write that scenario at this point because that's going to be some custom code and that's coming in a minute so one thing I should not see is and I press register then actually I should see welcome because I'm back on the welcome page about that so it'll say welcome so I should see why I should be back on the home page which means I see welcome and my name is on the page when it was registered so now that it's now that it's written everybody let me give her this everybody can see it okay so as the background and the given so every time I'm going to every scenario I would test it's going to require me to be on the registration page so I put that as a background the background gets executed before every scenario so every step of the background gets executed before every scenario I'm going to fill in the following fields which by the way is a super awesome thing she can get from the hat and all I need to know is the labels right I don't have to know the field names I don't have to know the IDs, I don't have to know classes I don't have to know anything except the labels I'll press register which is the button that has the little register thing in there and it should work so let's see if my test passes which I'm hoping it will so I'm filling in the following and I'm submitting and I got an error walk was not found and I know why so the username has to be unique so this is a problem we're going to solve here in a minute so I'm going to delete all my users and run again somebody actually run this test already didn't they what if you did it um so I should pass so there's a requirement that we haven't documented here but the requirement is that your username must be unique I'm sorry your email address must be unique so that a user can't register with the same email address twice so this is a problem right and this is a problem you will run into a lot when you're doing automated testing is that user names have to be unique, emails have to be unique so how do I build this so that it works so there's a couple of different ways that you can do this one is that you can generate a random username and then basically have it fill in you know the email address is going to be the random username so when I create a user with the following it'll know that oh I'm supposed to automatically generate a username that's normally what I end up doing and there's some more some more stuff that you can do as far as that comes but the other thing that you can do too is I can always make sure that I delete the user I don't reuse a username as far as deleting it so one of the things that I want to get over is everybody understand what I did here and feel okay and comfortable with that right so this is an actual feature who's written selenium tests how much fun would it have been to actually write something so that it would actually use the labels that would have been terrible right if you've ever used something to fill in forms and figuring out where they are without using a name, id, that is just horrible and it just comes with it it is awesome and also has options for sometimes on your form field you already have you have multiple fields with the same name so you may have business address home address right and they'll both have street, city, right things that are common to the both things there if you use proper html and you use what are called field sets and a field set has a legend there's a fairly simple way I believe somebody actually wrote one that you can actually add as a context now where you can say when I entered this value in for this field in a field set there's a lot of really nice xpath out there to just do this stuff for you automatically and it is super awesome you can also test you can also verify what the value of the field is without writing any code without anything except knowing what the label is that is pretty sweet so the hard part is it new? is it new now? yeah how long more do you have to that depends so the other piece I was going to do is I was going to write my own custom step it was going to be fairly complicated so I may not do that question are you able to do set up and tag out so those are hooks okay so some of the hooks that you have that we talked about before context after context before step after step so one of the things that I was going to do that I can write that really quickly is I was going to go actually I can just open it I was going to go take a look at my feature context I was going to add a hook we'll just call this the before scenario and it's going to have a before scenario scope that gets passed to it it will allow us to the per class that's smart, okay so before scenario hook I also have to document it for scenario so this is a hook and this is a scenario and so it supplies a scope and the scope is going to have your environment in it for a scenario so one of the things that I'm going to do to solve that problem for rerunning that test is I'm going to go delete all my test users I created this terrible hacky thing so I don't have to do it manually in unit testing and integration testing I like to set up the environment beforehand so if it breaks I don't do it after the test runs because then it's clear all away all of my evidence if it doesn't work so I usually if I have to do some cleanup or things like this I'll do it before the test runs so it will work effectively so after the test runs if something's not correct I can just go take a look at the actual standard database or things like that to see what's wrong so one thing I need is I need access to the mink context to be able to go to that URL that's on that site so inside of my scope I can do get context oh get environment nope I don't get the context oh it's going to lie to me I hate it when it does that it's sweet oh that's right they changed it around so if I get the sweet now I do it so I get context get environment I actually document this stuff so let me go find it real quick okay I didn't bring anybody right so a lot of stuff it's all documented fairly well but another cleanup okay so get environment get context so it's not actually documented in that but so when you get the environment you get a context from it so what I'm going to get is I'm going to get the mink context so if you want to write things that are using functionality written in the mink context you don't have to when you're going to write steps they're going to use the mink stuff you don't have to do that yourself you don't have to figure it out you just have to get it from the environment so you're going to depend on the other mink context so the thing I want to do with the mink context is I will set up set up mink right because I might want to use this to access other mink stuff before I go through and let's actually set it up here so proper coders sorry mink which is going to be private and so and it's going to be a mink context which I just do this mostly for mink context I just do this mostly for how to complete because like I said on turtle's car so now we have a mink context if we wrote steps inside of this context then we could access the mink context and go to visit pages and verify things and do all that kind of stuff so let's make I want to visit a path which I believe is delete how to hear somewhere so you can access a mail if you wanted to but right so what this is going to do is before every time it runs the scenario it's going to delete all the test users which isn't going to work for don't ever do this in the real world because if you have multiple running tests you're going to interfere with each other's tests and delete their users that they just created that they're still working with or if you run tests in parallel it will be a problem as well but now I should be able to run this and before it runs a scenario it goes and deletes all the test users so when it goes through here it's got the same username which it didn't work a forced scenario a forced scenario forced scenario delete test users yep it did interesting it went back to the homepage so we should probably figure out why it doesn't work so if I go back to my site I'm going to delete test users which runs before the scenario ah it's busted so one of the difficulties with that is you could actually do what does my server say is it down hmm I can't access this one do I have too many people accessing this is that what the problem is delete test users I'm going to give it back to you sorry that works I should be able to register test user so it's not deleting them so I'm not sure why it's not working unless you guys are running at the same time and it's not working so here's how you access other contexts so you're going to create a hook and hooks are going to so they're going to get past some sort of object based on the event so there's before feature, before scenario before step and before suite and those are going to allow you to give you access to the entire environment so if you have settings, environment settings setup as far as things that are set up for your profile you can access those as well so if you need to configure something and it needs to be configurable from the behat yaml you have access to those inside of your feature context and it's where you're going to write you're going to write steps so really quickly before we have to go we go to launch, I want to show you something very awesome about this and awesome is blue right so whatever this case may be here's something that's custom that I'm having to write of course I'm a lot of time to write a custom stuff but it's going to basically you write this in and what it's going to do is it's going to actually tell you that it doesn't exist but it's actually going to give you the stub to write the code so you don't have to figure it out so we have and awesome is blue which isn't defined anywhere and I'm going to run my tests and it's going to tell me that awesome is blue isn't created yet and it's going to give me, it has missing steps here's the snippet to build it so what I have to do is copy this in and I put it into my feature context and now my step is defined so now when I run it it's going to throw a pending exception but it will be happy so now I have a step that hasn't been written error but it's not going to tell me it's not defined it's going to tell me that I had an error on of the text isn't found so there you go, you have a pending exception on the homepage display so I've got code but it's through the exception whatever exception you throw it's going to throw that error and so you can write your scenario you can write your steps and anything that's not there don't worry about it because it's going to tell you it's actually going to give you the code that you need to throw it in there to build what you need to build so now I can just say that for this one we'll just say if I'm going to write this awesome actually because it was supposed to be awesome I'm going to change this to awesome so we're going to say this is awesome always has to be blue so if not awesome throw new exception awesome my definition awesome my definition so that is actually how you fail a test you can also use any type of assertion that you want as long as it's going to throw an exception when it fails when you write a test and an assertion fails it throws an assertion exception so you can use those if you want you can use hamcrest matchers if you're really crazy and love hammies so basically now we've got the test written now so now to run the test and it's going to pass that because awesome is blue so that one we knew was failing but awesome is blue so if I change it to awesome is red if awesome has to be red and run my test again I'm just going to run the one featured because the other one is not working page feature so I run it and it's going to fail because awesome is blue so that's how you write a custom set that's the simplest possible custom set you can write but the important thing I want to show you is that it's awesome but the important thing I want to show you is that it's super easy to just write your step in natural text based on the requirement it's going to spit you out a snippet that you just copy and paste into your feature context clean it up however you need to clean it up as far as doing optional pieces using turnip and then just write the backing code to do it and most often what you're going to end up doing is you're going to end up using the mink context to go take a look at something on your web page most of us are building web applications so via the mink context there's a lot of documentation about mink if you've ever used symphony the number one contributor docs there I always forget his name when I have to think of it Ryan Weaver, he also does the docs for the Hat so the docs are pretty good so you would actually be doing things like using the mink context to go look at something via CSS selector or whatever the case may be and you can absolutely do that you can just pass a CSS selector and check the value or whatever you need to do as far as identifying those piece by piece and you can do it with children and go find this field and then go check the CSS selector so one of the things I actually wrote that I did for this particular class that we didn't get to yet so here is what it would actually look like to check to see if the fields had an error so in this particular one there's no kind of easy way to do it so this is what you're normally going to do in a step let me make this bigger so you can see when you're filling out these forms determine if the field had an error what you shouldn't do because when you go fill out the form this is an error so what you should never ever ever ever do is you should never look at the X path and you should never say that oh we're at a step that says and.classBlock exists right or .helpLock because as a user I don't know what that means okay but what I do know is if a field has an error I can I have a high level of confidence that if I look at email address okay so what we want to do is we want to be very user friendly and say that in my step the field should have an error and I'm giving it a field name so what this actually does in here is you pass the field name which is the identifier for the field on the field name so we use mink to get a session which isn't always 100% bottom necessary we get the page which is that actual page that we just submitted because it has the response back that we identified and then we go get its parent because in here we're going so the error which is a nice as it has error on the form group so I could actually see the format there so it has help block which is actually a sibling of the actual field that we're looking for so I've got to roll up one level to the field so I get its parent and then I go find via CSS a span with a help block class so this is me writing custom code to go traverse the DOM so that the user gets something that is really easy for them to understand it's actually defining what the user interaction is as opposed to what's happening in the code there's a couple things here as one if I said and this xpath is there or is not there the user is not able to figure out what that means so that's not documenting my code if I change, if I add another div or if I change my styles or whatever the case may be it's not going to work anymore because every place I go and access something for a field error I've got to go doing it individually and manually so I'm not using something generic that I can reuse so now my testing is brittle and at the end of the day it's documentation for my site and it's the business owner is going to say I don't know what that means and that's not what I asked you to do what I asked you to do is when they don't fill in this form that's going to show the user an error I don't know what that means that slash slash body slash star slash whatever you're going to do for your xpath or CSS that doesn't mean anything to the business owner so you have to use something that's going to be a natural language the business owner is going to understand that you're going to have to translate and so writing really good BDD and using the xpath properly you're going to do this for things that aren't standard for things that aren't just part of normal HTML and so you're going to have to identify these and using your ubiquitous language to find them so that everyone understands what it means and so that's one of the things that took me a while to learn and the other pieces that I'll tell you so we're going to run through this really quick which I haven't done yet best practices so we should probably talk about best practices we talked about some of these already feature files contain one feature just one feature so if you're working on a feature you can just run that task but don't worry about doing stuff all over the place and taking too long or testing things you don't care about so for documentation you'll know how does this feature work and you'll know where it is because it's in a file it makes sense they should be more business than technical focus don't have a step that has a bunch of xpath don't have a step that means something to someone who is technically savvy but a business person or a QA person can understand what it means at all use the 3As arrange, then act, then assert don't mix them up, don't change the order it's a really good reason to do this and if your tests are not doing that that means you're testing more than one feature that means that you're making it overly complex you should be testing one thing per scenario and if you have to do and you can have multiple assertions use a unit test like that one assertion but you can have multiple assertions here if it makes sense make steps visually verifiable you should be able to visually go through read the step follow the instructions and be able to look and see exactly what the problem is based on the failure and then feature file because of that feature file service documentation clean up after yourself don't leave your old users in there you can do these after you can put in your hooks for your after test suite hook to go clean it all up at the end scenario should be idepotent it's a really complicated word to say understand what that means is that they can't affect each other they should not require another feature to have already run or another scenario to have run they should all be able to run by themselves completely and work and not be affected by anything else running on the system at the same time because at the end of the day your application should work the way right spend the time to do it the right way in the beginning you have to really think about what you're doing because if you do it wrong you're going to hate it in a year and you're going to be worse off than you were just doing Selenium testing because you can do that faster than having to fix the message that you created in the beginning that's my personal experience you can make them very brittle and very wrong if you don't if you test more than one thing in a feature if you're just doing step by step everything you have to do in the background instead of creating an aggregate step it's going to do that for you that you can change it one place for everything it's going to make it messy and you're going to be angry that you ever picked up BDD you never picked up B-Hide if you do it wrong because it can go very very very wrong that's it any questions really quick before we go to launch and have this food so we ran out of time it is so Selenium is what we're using is Butte so if you start up your Selenium server and okay if you go to a step let's see if that's Selenium server running that's Selenium server running no so Selenium server okay that's Selenium server running so one of the nice things about Goode we have in our oh I'm sorry yep let me go back over to there and turn power point power point there we go all right there we go okay so that's Selenium server running and because we have inside of our the HatYaml we have Goode and Selenium it's a special thing that they do just specifically for Selenium if I want if something requires JavaScript to run I can go to any of my steps and I can put a special tag on my step it says JavaScript just to run it in Selenium is very slow so if you don't care about how it works with JavaScript you can just use the headless browser and so now when I run this feature when I run this feature it will hit Selenium I just started Firefox and now it's running a test in Firefox it's always too you're done because by default so in our configuration by default it's pointing at localhost4444 as the port for Selenium I have by default it's going to use Firefox so I have the Firefox Selenium web driver installed that's all I had to do it's all done so if I were to take Goode off of here in my Bahat YAML it would run everything through Selenium so if you just did that then we take off the JavaScript everything is going to run through Selenium because it doesn't have a choice but if you have multiple drivers and one of them is not Selenium unless you tell it to use Selenium it's not going to try and go faster so now when I run it it's going to automatically start up Firefox it's going to fill out my forms and go so really that is all there is to do with Selenium that's all it takes and for the grid there's some instructions if you have to use the Selenium grid how do you have multiple browsers and multiple things you can do that very quickly there's decent documentation on the main thing for how to actually set up the Selenium driver but for the most part it will document it but it really is just that easy to go from headless browser to Selenium just by putting it into annotation or just not using the good driver it goes straight to Selenium so I didn't have to teach you anything about Selenium because there's nothing to learn you just have to make sure that you have the browser thing, the browser plugin you have to have the the driver and then start up the Selenium server stand alone and it's just going to work I installed the Selenium server stand alone via Holmberg because I like to do things easy but you can just download the jar file java-jar or the Selenium server or something like that any other questions? awesome, so I'll be here all week so if you have any questions I love talking about this stuff please feel free if you want to, where did my contact information go? I believe my contact information at least my Twitter handle is on it's on the website so please just hit me up over Twitter and just ask any questions I love talking about this stuff I talk about it all the time, probably too much my developer friends get angry when we talk about it so I love to talk about it so please let me know if you have any suggestions I know that it's still running 3 hours so if you have any suggestions about how to change the talk it didn't really give us a good idea so just hit me up over Twitter and say hey, would it be cool if we could have done this or this was a little more difficult than you made it seem awesome yeah, I'm going to put them up I'm going to find out where I have to put them up so we're going to associate them with the conference and stuff like that so they're going to associate it with part of the other stuff but yeah, definitely alright, round of applause to Adam thank you very much just a little bit of housekeeping