 Russell Fair, who is presenting Developing and Deploying High Quality Code using Test Driven Development, Continuous Integrations, and Continuous Deployment. Let's give it up! All right. I'm not going to use the mic because I'm loud, so I don't need to do that. So my name is Russell Fair. Just to give you guys a little bit of background on me is I started playing with WordPress. I can't believe to say this. It's 12 years ago. It seems so long. A lot has changed in the WordPress landscape. A lot of evolution has happened, which is great. It's all really good. There's some parts of it that maybe people don't agree with that necessarily, but in general WordPress is moving. It's changing, and the way that we work with WordPress is also changing. If you think back to a very early version of WordPress before there were actually plugins, there was a file called MyHacks. Does anybody remember that? Okay. One guy. Thanks. It was just a PHP file where you could just stick whatever functions you want, right? And that actually, like, evolved into what's now a functions file in your theme. And so that was definitely an example of doing it wrong. And a lot of what I'm going to talk about today, I'm not trying to preach to you guys or tell you, like, you're doing anything bad. I'm just trying to show you some of the tools that I use to really try to build better quality products, right? When I'm talking about building products, I'm talking about primarily plugins, but it could be also themes that I'm delivering for a customer or for a project. But it's also about efficiency, right? In the software development world, we have this concept of dry versus wet, right? Dry meaning don't repeat yourself and wet meaning write everything twice. And I feel like I've written everything about 30 times. And only after I've written it so many times over and over again do I really think, wait a minute. I need a way to automate this. I need an efficiency here. So I don't have to keep doing the same thing over and over again. I feel like it's always good to start talks with a little bit of an anecdotal story. So I'll start this one out one time at Bandcamp. I was a drummer and I played bass drum, marching bass, and I had this drum line instructor, super cool guy. His name was John Robbins and he would always say to us, guys, what's the phrase that pays? And that was suck less, right? And so what really, you know, what I'm trying to get at here is how do we basically suck less when we're doing what we're doing, right? And so a lot of that for me comes down to basically how bad is my code today, right? And so I remember seeing this nice comic that basically like every time somebody reviews my code, there's usually like at least a couple like, dude, what were you thinking here? Like what is this, right? And so the objective is to reduce the WTFs per hour so that my code looks pretty good. So what are some of the things that produce those WTFs, right? What are things that make, when I look at a piece of code and I inherit a lot of code from a lot of developers, and I'm usually the guy who's sitting there trying to scratch my head to figure out like what am I actually looking at here. And so some of these problems that are illustrated here kind of shed some light on what I think makes for bad code. And I'm only able to tell you this because I have done everything on this screen, every single thing I've done it hundreds of times. You know, things like formatting and commenting and just readability, right? Not necessarily can the server read your code because that's a different problem, but can like I hand you a copy of a file or some code that I wrote and can you read it, right? It doesn't have a lot of complexity, is it confusing, right? This whole thing of like poetry as code, we've all heard that. When someone looks at one of your pieces of code, is that poem a haiku or is it, you know, a novel, right? And so complexity, all of this stuff, a lot of times you'll see in code very repetitive patterns, right? Where someone has copied and pasted something out of one place, they've duplicated it. Next thing you know, they've got basically like the same code in about 10 different places. And so all of this is just about simplifying this code, making it easier to read, making it more portable, a little bit more modular. It also definitely impacts you as a person, right? If you're doing this wrong and you're writing the sloppy crappy code, over time it gets really difficult to sustain, right? You start burning out, you start having a lot of problems. You're banging your head against it. I can't tell you how many late nights I've stayed up trying to figure something out. And you know, it's just one little thing that's getting me, but I can't quite find it. And so that's a symptom of not having what I would consider to be good, high quality code. And really what I want to talk to you guys about today, I'm going to talk a lot about tools and things that I use. But those are more of the like, how do you do this stuff? And I don't necessarily want to spend too much time on the how, because there's no way I'm going to get to all of the how in this talk. The how is going to be the part that you can go home, research, hopefully integrate with some of your work. And all of the slides that I'm about to present have links in them. So I'll make sure I send this link to this so that you can investigate, read those things on your own. I'm going to really try to blow through a lot of the tools as fast as I can. I'm going to focus on the why of this a little bit more than the how or the what. And then if we have some time, I'm going to try to do a couple demonstrations and maybe field a couple things kind of in real time, if you will. So a little bit more about the why. Why do I want to do this? I mentioned reusability. One of the things I was just talking to someone out in the hall was, you know, a lot of the things that I see my peers do, and I've done it a hundred times, is if we take on a new project, we have to get from point zero to point 100 to complete the project. And if every time you start a new project you have to start at zero, you've got to go through those hundred steps every single time. And so when you're creating things that are a lot more reusable, a lot more modular, instead of starting at zero, you can maybe start at 30 for the next client. And every time you take on a new project, you kind of just progress your starting point, so that at the end of the day, you know, when you really get these things tuned up, you're only having to do like steps 90 through 100, and that's really the wonderful part of any project, right, is that last little bit. This is also about giving you confidence, right? How many of you have deployed code to a website? Just show of hands. Okay, and how many of you have gone like, ooh, afterwards? Right? Because you don't know what's it going to break, right? Especially when you're talking about huge code bases. I inherited a code base that literally had millions of lines of PHP, JavaScript and other stuff in it. And there's no way for me to consume all of that and know what it's about. And so if I don't have some sort of way to test my application, to test that what I'm doing is working, I don't have a lot of confidence in those changes, right? If you look up a talk by Mark Jake that was at WordCamp US many years ago called Confident Commits Delightful Deployees. And he talked a lot about kind of the deployment process and a lot's changed since that talk, but a lot of it's still very true. And so what test-driven development and all of these tools that I'm about to show you is it will give you a lot better confidence that you just made a change that's not going to break something. The other thing about the kind of the why part of this is that really you're doing yourself or some future developer a great service by setting them up on a good solid foundation. Again, I mentioned I take over a lot of projects. I take over a lot of code bases that are not set up this way. And so I then have a problem, right? I just inherited a big mess. And so by setting up a project with good solid tests that are easy to reproduce, you're giving the future developer who might take this project over after you're done a really good foundation to move forward with. And sometimes that person is actually you, right? So if you have to come back to a code base that you wrote six months ago and you're looking at it and you're going WTF, WTF, like, this is what you want to try to prevent. So you're paying it forward not only for others but for yourself. And most importantly, if you do test-driven development, people will like you, and that's a good thing. At the end of the day, right, what we're all after and the reason we're all hopefully here at this word camp other than the food and all of that is, you know, we all want to be better at what we do. And so I really do believe that following some of these approaches will make you better at what you do. And I know personally, because I never did any of this stuff when I started, I learned it definitely the hard way. And so as I've started to implement these practices, I've seen my own quality go up. And I think that if you do, you'll be surprised at how beneficial it is. So in order to make all of this stuff work, there's some tools that you have to have. You have to be running probably all of these tools. And so I'm not going to get into these tools, but just suffice it to say that this is not something that you can just five-minute install, right? There's a lot of legwork to get some of these pieces running. I actually published a lot of the... I published all of the code in the demo that I'm going to show later. So there's some kind of boilerplate stuff there that if you want to try to implement some of these tools, a lot of it's in there. There's actually a couple pieces that I forgot to put in, so sorry about that. We're going to be talking a lot about PHP kind of concepts, obviously, so if you're here for WordPress, hopefully that's not foreign territory to you. And I do use Composer to manage all of these different packages, most of them. A couple things are node packages, so I do have those two dependency management there. So I'm basically going to break this up into two pieces. So we've got the quality code component and then the CI or continuous integration component. So I'm going to hold off on the CI, CD pieces till the end. We'll walk through some of the code quality stuff first. So I pulled this right off of the WordPress coding standards page and I thought this really spoke well to what I'm trying to accomplish. Basically that if you look at a piece of code, if you take a whole library of code and you're comparing file to file to file, you should not necessarily see like an individual tone or an individual style in that code that it should all be formatted and written in a similar enough style that it's believable that a single individual wrote that. So I work in a team of three people, so we're always contributing. You can actually sometimes tell which code is the code I've written because there might be guys that are actually much better at following these standards than I am. We implemented this into our practice several years ago. Basically adhering to the coding standards that WordPress has kind of agreed to in all of our code. How many folks are familiar with the WordPress coding standards and actually follow them? Okay, good. So basically this all starts from these WordPress coding standards. So they have the they being the WordPress core team members have created a set of rules, a set of style rules that they want people to follow. And so this is kind of step one for me is making sure that I'm adhering to those standards. It's simple things like indenting with tabs versus spaces and not surrounding strings and double quotes. There's all these little rules and there's rules for PHP, there's rules for JavaScript, CSS, HTML, and so there's different ways of making sure that your code is compliant with those. But the main key is that you're not just looking at it and mentally having to think through is this complying with those standards, right? It's too hard to remember. So there's automated tools for checking your code to find out if it complies with those WordPress standards. And the tool that we use to do that is called PHP Code Sniffer. So PHP Code Sniffer is a PHP application, go figure, that will actually analyze every line of your code. It will run your code line by line and it will check it against those sets of standards and tell you immediately if your code has a problem or is not necessarily a problem but maybe not following those best practices. Another really great tool that I use is called PHPMD. MD as in doctor. And PHPMD is a little bit beyond the WordPress coding standards but I think are really vital to making sure that your code is not overly complex, right? If you look at a PHP class and it has 50 methods in a class, right? Then that class is probably way too big. There's probably an opportunity to refactor parts of that code into another class. And PHPMD will help you kind of see those problems and comply with that so that you're not building things that are too difficult to read, too difficult to understand. They do some other things like it checks your code for over-complicated expressions, right? So like really deeply nested if this, you know, with inside of a loop, with a switch and all of this just complicated like decision points that your code has to make. And so the idea is to refactor those things into their own individual methods so that your code doesn't have this, you know, really deeply nested structure. The next two tools are linting tools. So these are not so much for PHP. There's a tool called ESLint, which is a linting tool for JavaScript. And there is a ESLint configuration within those WordPress coding standards that will actually help you parse, or not parse, but format all of your JavaScript according to those WordPress coding standards. And then StyleLint is basically the same thing except for CSS files. So it will actually go through and format everything for you really nicely. And I have all of these things wired up. Now these will integrate with your, with an IDE. So if you use an IDE like PHPStorm, or Adam, or what's the other, Julian, what do we talk about? Code, you know, Visual Studio, I believe has integrations with these. So you can tie all of these things into the thing that you're using to write the code, right? Hopefully you're not using Notepad++ anymore. And you can tie all of these tools in so that you can run them automatically. And it will just kind of help you do this. It will point out those problems to you in real time. One of the benefits of having these tools running locally and having them connected with your IDE and using these tools very quickly is that it reduces the amount of time between when you do something wrong and when you figure that out, right? I can't tell you how many times I've had to debug something that I wrote like two months ago, but it just got deployed and caused a problem. And so the time, the delta, if you will, between when I sat down and wrote that to when now I'm seeing the problem that it's producing is very large. And the longer amount of time that goes on between the time where I introduced the problem to the time that I'm having to solve it, the harder it is for me to solve it. So it allows you to get more instant feedback, more instant, just better feedback quickly about what you've written and what you're doing and what some of those potential problems are. So I'm going to get just a little bit briefly, a little bit deeper into test-driven development. So those first four things were really just about quality, making sure that your writing code that basically looks good. I'm so upset that I forgot to bring my hat. I have a great hat that my buddy gave it to me. He's a big ruby nerd. And it says, TDD, quality is built-in. And quality is spelled Q-U-A-L-T-Y, right? And so it's great because we've written all these tests to test that our code is right, but that doesn't mean that we're not still writing some optimal code, right? And so this by no means means that you're not going to make mistakes or that you're going to be 100% bug-free. Anybody who tells you that you're writing your code is selling something, trust me, I do these approaches and I still break things. It's just a lot easier for me to find it. So test-driven development, anybody here heard of test-driven development? Okay, pretty good amount of room in. So for me, test-driven development is basically this. Before you write your application code, let's say you're making a plug-in just for the context of this conversation. Let's say I was going to deliver a plug-in to someone and that that plug-in was going to do a thing, right? Before I write the code to do the thing in WordPress, I would first start by writing a test that tests whether or not my code is doing what it's expected to do, okay? So there's a lot of benefits to using test-driven development. First of all, it forces you to think through the business logic and solve the problem before you actually start writing the application code. And that's a very important separation, right? One of the things, I used to teach kids a lot, and one of the things that I always tried to explain to people is anytime you are learning a new programming language, right? Let's say you're learning PHP because you want to do a WordPress site. You're actually doing two pretty different critical thinking skills at the same time. So first of all, you're learning a new language, right? A syntax, PHP or JavaScript or whatever the case may be. You're also doing a very complex critical thinking problem-solving task to understand how to fix the thing that you're trying to fix, right? Does that concept make sense? And so when you can do test-driven development, you can actually separate those things a little bit so that when you're learning the PHP code that you need to know to do it, you can focus entirely on the syntax. You've taken the critical thinking steps out of the way, and it allows you to really think through what you're doing before you just start jamming code out on the page. And so that's really beneficial. The other thing that's nice about test-driven development if you do it right is that you generally produce more minimalist code. So if somebody said to me like, hey, we need you to write a function that does x, y, or z, and I just start typing it up, I might add a whole lot of extra stuff to that function that's not actually necessary to accomplish what I need. And so by following a test-driven development approach or TDD approach, you're only writing the minimal amount of code that you need in order to make your test pass. And so as you write new tests, you refactor your code so that those new tests pass, and what it produces is basically the, I would say like an MVP, if you will. It's the minimum amount of code that is necessary to accomplish the specific things that you need. And that's really the big, the big aha moment, right? Is you're not creating methods that are overly complicated with a lot of structure in them. When you're doing TDD, because you're testing individual functions, you're not testing the entire application. You're testing individual small snippets of that application. And so if you're going to write PHP that is testable, it forces you to write smaller methods, right? At the end of the day, that's really what it's about, right? If I can write a method that's one or two lines, I'm happy with that. When I have a method that's 15, 20, 30, 100 lines long, it's way complicated. Not really easy to test, so I need to refactor that into a smaller set of methods that are easier to test. So that's some of the benefits in my perspective of TDD. And this was me. All right? I will admit, I was like super hater on all of this stuff for a long time. In fact, I went to one of the PHP meetups back in Atlanta probably many years ago, and the guy did a talk on test-driven development. And I was listening to him, and I was like, man, nobody wants that. I don't know what he's talking about. And one of the things that he pointed out that's very true about unit testing is that because you have to write a fair amount more code in order to create the test, the amount of time that it takes you to produce the product goes up, right? So it takes you longer to complete your objective because you're writing unit tests to go along with it, right? So that's a difficult thing to sell from a business perspective. It's a little bit harder to say, hey, I need three months to do this thing where someone else may have told you they can do it in a month. However, I'm going to do X, Y, and Z that's going to assure you that this piece of code is going to work, it's going to continue to work, and it will be easier to support down the road. So there's a value add to test-driven development, but it is a little bit challenging to sell. One thing, so my dad, this may come as a surprise to you guys, but I come from a very technical family. My dad and my grandfather are both programmers, and so I started learning code when I was a little kid. And one of the things that my dad taught me that has just always rung very true to me is there's three types of work, right? You've all probably heard this. There's good work, fast work, and cheap work. You can have two of those three, but you can't have all three. So basically, for me, it boils down to you can have good work, fast, not cheap, good work, cheap, not fast, or cheap, fast work that's no good. And, you know, I kind of have come to the point in my life and like in my career where I'm not really willing to compromise on quality. I don't want to deliver bad stuff for anybody because that's not what anybody's paying me to do. So it really comes down to what do you want? Speed or are you willing to pay a little bit more for it? And so I feel like it's easier to kind of pitch that value, if you will, by saying, look, we're not going to be the fastest out there. It's going to be pricier than other people, but the reliability is there. And ultimately, I work a lot in the enterprise space. That's what people are after, right? It's something that's reliable. So unit testing is there. So there's a unit testing framework called PHP Unit. It's a lot like some of the other tools that I have. It's a PHP application that runs right next to your code. It pulls all of your code in and will then call functions inside of your code and will test those functions. And it does that with what's called assertions. So basically, I can say, here's a good example, is I can tell PHP Unit to assert or to believe that two things are equal. So if I say 10 is equal to 10, that's going to be a green light. That's going to pass because 10 is always equal to 10. Or if I say 10 is equal to the number of items in this query that I just ran, and it returns 10 items to me always, then I can actually start to test, like, is my code giving me the number of things that I want? And so with PHP Unit, we kind of separate it into two different types of tests. There's functional tests and there's integration tests. Integration tests to me basically mean, is my code hooking into WordPress where I expect it to be hooked into? Do my classes and methods exist? Do my methods return what I'm expecting them to return? And are they firing on the correct hooks or filters within WordPress? So if I expect for my hook to be added to the init hook, then I would test that init has a specific action and that function that I'm calling is registered to it. So it's testing whether or not I've written the code correctly to actually integrate with WordPress. At this point, though, I haven't actually done anything with my code. And so that's like the feature testing, right? Or the actual unit test of, no longer are we looking at, does it work with WordPress nicely? I forgot to mention too on this other slide. Does my code work when other stuff is installed? And that's a really key differentiator, right? If I deliver you a great shiny plugin with a whole bunch of unit tests, and then it doesn't work because you have Yoast SEO turned on, fail, right? And so in a lot of cases, what I will actually do is if I know which third-party plugins and themes I'm going to be using on a site, I'll actually make sure all of those things are activated and run my tests with those tools activated so that I know that my code is not going to be broken by some other piece of code so that when I deliver something, I can actually confidently say, yes, this works with these plugins. I know it because not only have I tested it myself, but I've written automated tests. Yeah, question? Yeah, so that's very good. So he said you might want to also disable those plugins as well. And that's true. One of the things that we do is actually turn them on one at a time and iterate over each plugin, test them with combinations, test them with everything, right? Does my code work with other themes, right? That's one of the big kind of problems in this space is that, oh, this thing works great when I have this theme active, but as soon as I turn on this other theme, something breaks. So we test with different themes. Obviously the theme that we're going to be using on the live site, we sure want to test with that. So anyway, so back to the unit testing piece. The best example that I can give, and I remember listening to a talk by a guy that was way smarter than me, I like to go to talks from people that are really super nerds because I just suck up their information. And so the best example that he gave, I think, was if you were making a calculator app, for example, just a simple four-function calculator app, you would have probably four functions, you know, add, subtract, multiply, divide, right? And if you wanted to test that your add function actually worked, you could say something like, you know, assume that eight is the answer, like eight is the given, and then three, five, and you pass that off to your add function. Your add function should always return eight. So you can kind of break it down on small levels and make sure that your function does what it's supposed to do. And then also whether or not your code has proper error handling in it, right? Does this method throw an exception when these conditions are met? And so you can actually test against all of that so you know you've got good error handling built in. I already kind of got to this a little bit, but PHP Unit is the testing framework that we'll be using. This is what the WordPress core utilizes, and you're starting to see a lot more plugin developers. We'll now deliver a set of tests with their plugins. So definitely want some PHP Unit. You can take that a little bit further and look at a package called WPMock. It's written by the guys at TenUp. WPMock is really useful. It allows you to create mock objects within your testing framework, right? So if I was, you know, writing a plugin that let's say my plugin changes the title of a post, right? It filters the title. That's all it does. Well, I need to test that on something, right? So I would actually use WPMock to create posts inside of a test WordPress site, and then I would query those posts and determine did my function do what it was supposed to do and filter the title for me. Does that make sense? WPMock? Okay, perfect. Okay, Behat is like my favorite thing in the world. Anybody here used Behat before? Oh, yeah, this is going to be good. All right. Behat is like the best thing since sliced bread. I'm not even kidding. It's super awesome. I actually want to like stop everything and just talk about Behat for the rest of this, but I won't. What's so great about Behat is that it actually allows for you to define in a very human-readable way business requirements, right? It's one of the biggest problems like in this industry and not just WordPress. It's everywhere where somebody tells you, hey, we need a function that does this thing, and then you go write it and you do exactly what you thought they were asking for, but at the end of the day, you completely misunderstood the intentions, and so Behat allows for you to write your requirements in English, right? A very specific set of requirements. It's actually, Behat came from a Ruby package called Cucumber, and Cucumber uses a markup language called Gherkin, and Gherkin is the language that we use in Behat to define all of those really specific business cases, and then what's also even more awesome about Behat is it will automatically write PHP code for you to test that those things happen, and I'll show you how that works in a minute. I'm telling you, if you're going to try anything out, check out Behat. I spent like a whole month just nerding out on it, and I got no work done. And then QUnit is something that I don't use as much of. I don't write as much JavaScript anymore as I used to. I have some really awesome front-end developers that do most of that, and they utilize a lot of QUnit tests. So these are basically essentially the same thing as PHP unit tests. They're just for JavaScript. So it allows for you to also test your JS. So I mentioned learning things the hard way. I'm a believer in doing things as close to the metal as you can. So learning how these tools work kind of in isolation, learning how to interface with these tools and how to run these tools like from the command line is where I would start. Yes, you can integrate all of this into your IDE and you can have an IDE that just does it all for you, and that's great if you get to that point. But if you don't understand how to do it the hard way, it may be a little bit more difficult for you to understand these concepts. So I would suggest you start on the command line and then configure your IDE, right? Then set it up with PHP unit or whatever you're using. All right, that's the first half. I'm gonna pause for just like any questions on that stuff before I move on. I don't think it's .com. I think it might be behat.com or .org, but if you just Google Behat, you'll find it for sure. Is it or? Thank you. Okay, so basically everything that I just talked about is doing stuff locally, right? You're writing code, you're checking all of your code. The next piece is about what's called continuous integration. And so the concept behind continuous integration is that if you have all these great testing tools and you've got good unit test coverage of all of your code, that anytime you commit and you push to your repository, assuming you're using a Git repository, pardon me, that you want all of those tests to run automatically. You want to know immediately if you've introduced a change that made one of your tests fail. Ideally all of your tests pass all the time, right? The lights are green. This is a good thing. But with continuous integration, basically what it allows you to do is as soon as you push something, it'll actually re-run all of your tests. So again, assuming that you're doing it locally, that's good. Continuous integration is actually doing it on basically like a server that's not your actual web server. Well, most continuous integration uses some sort of container service that will actually, as soon as you push your code, it will actually spin up a VM running on somebody's cloud and then it'll execute all of your tests for you. And what's great about continuous integration is you can actually specify different environmental variables. So one of the things that I just spent way too long fixing was I had a big huge site that was all custom plugins galore and all the developers on it were using PHP 7.1 because they were hosted in AWS. Well, they decided to move to a different host who shall remain unnamed that doesn't support higher than PHP 7.0. So guess what? Composer dependency hell, anyone? We had to go back and change a lot of syntax back to PHP 7.0 compatible code. And so we were able to make one change to our continuous integration provider settings to say, hey, rerun all of our tests using PHP 7.0 and then all of our tests failed. Our code wouldn't even load. And so then we played whack-a-mole for like a week and every time it was like, okay, this function's not working. Just rewrite it, commit it, push it, wait four minutes for the Travis to build start-up again and run those tests again. And then we eventually got to a point where we got all of our tests passing again, committed it, deployed it, and everything's happy. So it's very beneficial continuous integration tool. What I mentioned this earlier, but I think it's key to point out is that the benefit of continuous integration is that it gives you as close to real-time feedback about your changes as possible. Remember I was talking about that difference between when I introduced the bug versus when I had to find the bug? If that time is weeks or months, it's a lot harder to kind of remember, oh, I changed that thing. Maybe it's that thing that's breaking. So continuous integration reduces or almost eliminates that feedback cycle so that you're getting very quick feedback that you can look at. You can say, okay, that failed. Here's where it failed. This test didn't pass. So maybe I need to keep working on this change before I push it. You can keep working on it until all of your tests pass. This is an interesting one. It says continuous integration is cheap, not integrating continuously as expensive. And so I think that really goes to the core of this, which is that these tools are like, I'm talking about mostly free tools. Some of these tools you have to pay for. If you're like private, get reposed, you have to pay for it. These things are fairly easy to set up. The writing the test is not so easy to do. That's going to take effort. But getting these tools put in place is pretty easy. And you can actually take it a step further and use what's called continuous delivery or continuous deployment. And basically, I'll kind of just briefly talk about the differences between those. So continuous delivery is basically that any time a set of changes is committed to your code, your continuous integration provider will actually build your entire application. So Julian, you use Sage a lot, right? So one of the things that Sage has that's very nice is the yarn, like, dist function that minifies all your JavaScript, minifies all your CSS, does all that nice stuff for you that we used to kind of have to do manually almost. And so that's a good example of something that you would set your continuous integration provider to do. It would bundle all of that stuff up and then actually can package up all of your plugin code to a nice little zip file that you could then deploy anywhere you want. The deployment is still done manually. Okay? So somebody has to push a button for that to work. Or continuous delivery, which is where the deployment is automated. And that's really, for me, that's the secret sauce. Is that any time I commit, I push to my repository, I open a pull request, my continuous integration script runs. If all of my tests pass, then and only then can I merge it into generally, like, my develop branch. My develop branch, any time it gets emerged, will automatically deploy to my staging server. So I don't have to sit there and, like, open up FTP or R-Sync or any of the tools that I'm used to having to use. This sucker just does it all for me. And that's really nice because I can actually say to someone, hey, I just finished the branch. All the tests pass. I'm about to merge it. And within five minutes, it'll be live on your staging site. You can actually go check that feature out. And we basically do the same thing for production builds as well. So anytime we merge develop, we use the get flow workflow. So anytime we merge develop into master, it automatically publishes to our production server. So there's basically no DevOps or sysadmin required to do deployments. I used to do deployments Friday nights at 2 a.m. Eastern time because that's what time all my clients were like, yeah, it's fine because everybody will be in bed. Nobody's using our website at that time. And I hated it, you know? But at the same time, that was the only way I could do it. And with this, it's a lot easier because I can just make those deploys seamless once you have a working process. It's gonna be the same process all the time. And there's no, like, oh, did I forget to go back and change all the permissions that, oh, maybe that's why this is failing. No, it does all of it for you. It does take some time to get right, but it's very beneficial. There's different continuous integration providers depending on where you actually host your Git repository. So if you use GitHub, then you can get Travis CI for free. You can also use Circle CI. Bitbucket has a pipeline feature built into it. Which is essentially the same thing. And GitLab has a runner built into it as well. So depending on where you're hosting your repository, you may have some CI resources available to you. Deploybot and Codeship are, like, a little bit different animals. I won't get into a whole lot of them. There's different tools out there. You'll need to research and figure out which one is gonna work for you. Deploybot is, I think, especially handy. It costs money, but it's a great tool. I listed a couple of these. These are some resources that I actually used as I was putting together these slides. And so if you pull these links up later down the road, I definitely recommend that you read these. All right, here we go. This is the scary part. How are we doing on time? How long do I have? Awesome, I'm gonna torture you guys. Pray to the demo gods. This was a huge fail the last time I did it, so I don't expect for this to work. Let's see if I can make this bigger. Let's not do it that way. Okay, so I'm just gonna walk through a couple of these really quickly. Let me see if I can get out of this stuff that I don't want in here. All right. So down below is just a terminal window. And so I'm gonna actually step through all of these tests for you just to show you how they work. I made myself a nice little cheat sheet of all of my tools. So I'll start with the PHP code sniffer and the WordPress coding standards. So what's nice about this is I can run this and it'll give me output like this that will show me all of those things that are not lined up correctly. Yes, sir? Zoom in, yeah. You know what I'm gonna do? I'm gonna do it in terminal instead. See if this looks any better. All right. So what's nice about this is it's actually telling me every one of those standards that I've ignored, right, where I've got a problem. The really neat thing about it is the Xs inside of the brackets, those are things that can be automatically fixed for me, right? So instead of having to even open the file, I can simply change this command up just a little bit and it will auto-fix those for me. Oh, I didn't like that. Let's see. There we go. All right. So it told me five errors were fixed and I had to run my checker again. All of those ones with errors went away. Right, so the two, the ones that were able to be auto-fixed are now fixed. The only thing I have to do is I have to go back into my plug-in and I have to look at what's on line 21 and what's on line 18. So let's see if I can make this bigger or not. I don't think I can. Can you see that okay or not really? Okay, so it's wanting to do something with output here. What did it say? .comit for parameter output is missing. Don't actually know why that's... Hopefully that will fix it for me. I can run it again. And now I've got no errors coming back from that script. Right, so now everything is clean. That light is green for me right now. So I fixed my coding standard issues. Let's see if we can... This isn't working. No, it's just the WordPress PHP latest container. You can run this on Vagran or whatever else too. I mean, you don't have to use Docker. Let's see if I can get another test to run. So that was PHP Coding Standards. We'll go ahead and run the PHP MD. I don't think it's going to find anything because I don't have a whole lot of code in this. Right, so I just ran PHP MD. It's not complaining about anything. So it's like, okay, this is good. Basically this plugin doesn't do anything right now because I didn't add anything to it. So I know that from a quality perspective I'm looking good, so now we need to run some tests. I'm going to actually run the B-hat test first because they're so awesome. So this actually gives you a little bit of an example of what B-hat tests look like. So see where it says feature title. This is the actual test that I wrote. This is something that I could hand this off to like a business owner or a product owner and I could say write the specific requirements that you want me to develop. And I hand them the piece of paper and they have to write it down. The benefit of it is obviously this is not code stuff, right? This is just English. Things like this scenario. Viewing the website as a regular user. And the given, when, then and and, those little first word keywords all dictate to B-hat how to run specific functions. So in B-hat what's cool is it sets it up what's called a feature context. So let me just open this up really quick. So this is my title feature. I know you can't read that yet so I apologize. See if I can just go in here again. So that's my test. Nothing really frightening there. And believe it or not you can actually train non-developers to write this. I promise. That was supposed to be a joke actually. And so when I have this, if I just write this and I run my B-hat test it's not going to know how to do anything because there's no PHP. B-hat will actually generate the code for you, which is pretty amazing. Right? So let's just copy this scenario and I'll show you exactly what I'm talking about. So let's say instead of viewing the website as a regular user I'm going to be an administrator. And the title of the site doesn't change. I can actually change up. Let's actually not do it that way. Let's say I open Alright, so I've just added a new test and I'm going to come back here and actually re-run these. Let's run it first without this. Probably going to get some red lights here. Alright, so something a little bit different. It's telling me basically this second scenario we ran the test but it doesn't actually know how to do that. See at the bottom where it says suite has undefined steps please choose the context to generate to snip it. So I'm going to do one as a feature context and then it actually wrote this PHP for me. Remember we're talking about efficiency? When you can have tools that write the code for you you have to write less code and that's a wonderful thing. Now open my feature context file I can't even read this. Okay, so here's my feature context file and you should notice down here at the bottom I don't have my I don't have a function for that feature context. So I'm going to run it again with the append snippets and this is where it will actually put that code in my file. And so now when I look at this you see I've got a new function down here and this is a function that I would use to test the IOpenWP admin, right? And so now whatever I want to do I could say what's neat about Behat also is that it has a browser built in I mean anybody use phantom before? So phantom.js is like a headless browser, right? It's just like Chrome but no user interface and Behat has a similar browser so I can actually tell Behat to do things like visit a web page, right? So I can tell it like visit this web page so I'll grab this drop it in here right? And now I've got a function that actually tells the driver to open the WP admin and I can come back here and rerun my test and with any luck it'll pass. Nope didn't pass. That's okay. That's the whole point of this, right? Is this can be frustrating at first but the more you start to embrace it the more you realize like failing tests are great because that's an opportunity for me to now I've finally gotten to the point where I've got a good test now I can go write my code that is gonna make that thing happen right? So that's Behat I don't want to spend all my time on Behat I mean I want to but I shouldn't let's get into one more. So we talked about Behat and then finally we'll look at PHP unit so I can run my unit test suite here as well and right now all my tests are passing because I don't have a lot in this function this is just a basically a some demo plugin just for the purpose of this but again I'll show you how that works so if I'm following TDD and I get into one of my test files let's go here what I would do is I would say okay I want to I want to test something and I would create a new function and I would write whatever I'm trying to test about my plugin so in this situation I wrote a little filter that actually adds the word foo to the end of your site title right it's kind of a silly use case but that's what it does and so if I'm gonna enhance this to do something else then I would write a function or a series of functions to test that new thing and by default this test is gonna fail right when I run this now this test is gonna say nope I don't like it and it gives you what it expected and what it got right so the assertion here is that my result should be WP test site-bar but what I actually got was WP test site-foo right so it'll actually run that test and compare the expected answer to what it got and it gives you feedback so I can go okay now I know I can either change my test or I can change my plugin code right and so in this situation this would be the point where I would go and I would add that additional functionality I would create that function inside of my plugin does that make sense okay so anyway let me actually get rid of this test so that I can show you the CD component so let's say I have sorry I'm jumping around a little bit can't remember where I'm at say I have all this stuff done and I commit it and I push it to my develop environment you'll notice that I have my develop branch here I'm not gonna actually pull request that just yet I'm actually gonna get into Travis and inside of Travis it'll actually tell me this is my build right here I know you guys probably can't see that very well so let me try to screen so Travis is now thinking about starting my container right so it's finally started and these are kind of fun to watch for about the first day so what this is doing right now is literally starting a Linux container that has all my tests built into it and if everything goes according to plan it's gonna run all my tests everything's gonna be green everything's gonna pass. BeHat will probably fail because I think I committed that test that didn't do anything and again these are not super fun to watch but it hasn't actually got to running my tests yet it's still just basically building some of the things that I do inside of my continuous integration as I mentioned earlier is not just running my tests but also compiling building my application so I would do my you know my Sage build production command here if I have you know a linting tool any of those tools I would set it up to run here so that I'm deploying a nice lean application see if it finishes well this is going any questions I'm kind of running out of time yeah yeah for sure so when I set this up I actually installed WPCLI inside of this container so I have access to WPCLI I can install plugins I can activate things I can change options I can do anything that I would do normally with WPCLI but I would just put it into the container setup yeah good question okay the question was how do I work private composite repositories in first of all I try not to basically we have plugin repositories for different little groups of plugins that we create right so if we have a custom plugin we keep it as a Git repository there's actually a tool called SATIS server I have never actually used it one of my colleagues set it all up and that's what we use for managing like premium plugins and I would imagine that that's what he's doing for all of the composer plugins as well yeah mm-hmm when you say git push do you mean deploy to your server yeah right so I intentionally left out like how to do the deployment because that's going to vary for everybody obviously if you have SSH access then rsync or if you don't have SSH and you only have FTP or SFTP there's LFTP utility that's kind of nice it has a mirror option that allows you to synchronize those files it's maybe not the best out there but one of those tools should be able to be able to get it done yes yeah deploy bot is pretty much where it's at yep alright so this is good my build failed yeah this is like this is the screen that I don't like to look at right is when I have to look at build fail I'm not going to sit here and go through and retest this over and over again because I'm out of time but you know the idea being that once you get these tests passing then the process is going to move forward and it will use your deploy bot or whatever to push those changes maybe time for one more question I think I'm about out of time yep alright well thanks everybody