Byddwn i'r bwysig yw'n gweithio i arddangos fel y cyfaint yn cynhyrchu, gan ychydig i ddim ymhleithio ar ôl gyffinio yma i gael cyfaint ar gyfer opportunities. Rydych chi'n gweithio i fynd i erioed o'u gymhau 30 ymylgen yma, ac ac hanes yna ddim o'r thirio o'r ffordgyntafol i'r ffordd. I'm really very excited by the possibility of a whole lot of new work and in fact new people who will be doing this work hopefully for many years to come. So anyway, I just wanted to start by saying a few words about the background to this. In the past, I think archaeological research into the late racial paleolithic has been very much dominated by studies of caves and rock-shelter sites. Let's get this working. New technology for me. Is it arrows down? Sorry. So, just to say that this is a tradition, of course, that is very much as a result of wonderful work done by people like Dorothy Garrett, the first female professor of archaeology at Cambridge University. And she undertook a major study of the apocaleolithic in 1926, but it was published in 1926, but it was completely dominated, of course, by cavesites. And this work was continued by John Campbell, seen down at bottom right, who published a very useful review in 1977 covering the early and the later apocaleolithic of Britain and published by OUP. And I claim to have some small contribution to this. In 1986, Simon Colcutt and I undertook a major survey of cave sites for English heritage and cadw at that time. And we were able to show that out of 120 sites or so that we visited that were targeted of interest that 80 of them contained evidence of paleolithic activity. And this, of course, was followed by subsequent survey and excavation work. I've only mentioned some examples here that many others, but ones in the Tornewton Valley, in the Wye Valley, in South Wales, Stephen Green, Creswell Craggs, and also particular studies of lake glacial sites, lake glacial cave sites like Ross Cave, Caverland and so on. So as a result of this, we know quite a lot about the caves and rock shelters of Britain. And, of course, we also owe a great debt of gratitude to Roger Jaffregl, who produced some absolutely fantastic work and was a great colleague and a friend. And he was able to show that through a magnificent dating programme that he carried out by Tom Ion and others at Oxford, he was able to produce a large number of radio carbon dates on modified bones from caves and rock shelters. And I think he's generated one of the best chronologies or chronological records of the lake glacial period, probably anywhere in Europe. And this is some of the examples here, King Arthur's cave on the left-hand side. There's more work being undertaken here that we might hear about today in the Mgol's cave. But this conference, this day meeting, is primarily about open-air sites. And I think as a result of the focus, our focus on caves and rock shelters, we tended to play down or give less attention to open-air sites, unfortunately. And this is rather surprising in a way because as a result of a survey that Simon Polkot 9 carried out, in fact, we only identified 63 lake glacial caves in England and Wales. And as we know now and we probably knew then, there were many, many more open-air sites of the lake glacial period dating to between about 15 and 11,700 calibrated years ago. So it's always been known that we've got huge numbers of open-air sites, but they've really been a sort of poor relation of the cave sites. And so this meeting really is to try and redress the balance and just to remind ourselves that in areas where we don't have caves and even in areas where we do have caves, we also have large numbers of open-air, finer spots. And of course we shouldn't really be surprised about this because the majority of sites from this sort of period in Europe are open-air sites. They come from major river valleys of the Rhine and the Somme and the Seine. And if you just look at the distribution of those sites, you will see that it really ought to come as no surprise because we've got a good land bridge connection at that time with Europe where there ought to be sites many more open-air sites to be discovered or shall we say to be properly reported in the east of Britain. So one of the objectives today is to sort of, as it were, highlight or to showcase some of the sites that have recently been discovered, these equivalents of these three buses that you waited very long time for them to roll up and these are three of the sites that will be mentioned today. But really what I'm hoping for, apart from a good discussion and understanding of these particular sites, is to think about context. For example, we can suggest a number of themes for today's meeting and I hope everyone will get involved and feel free to contribute in the discussion if there's a lot of time aside for discussions. And one of the things I hope that we can look at is how the landscape influenced human behaviour in the last place you'll be. We can look too at this question of the functional relationship between caves and open-air sites, something that hasn't really been looked at in enough detail yet. And we're lucky enough to have some people here who are working on very big projects, both in Britain and Europe. So the map taken from Vince Gaffney's group, work on the submerged landscapes of the North Sea and we have very big terrestrial surveys that have been undertaken by Philip Crombey. And we hope to hear more about those today and lessons that can be learnt in Britain from these bigger projects. And finally, I suppose to think about future management and conservation issues affecting the last glacial archaeology. How do we serve the interests of the major stakeholders involved in long-term research and also in preservation of these very landscapes? So these are some of the things that I hope that we can develop and discuss in this meeting to think about the future but also to think about landscape in a much more general sense than perhaps I've done in the past by looking at individual sites. So, although we're ahead of time, I think it would be good at this point to hand, if I could hand over to Matt Hope, who will be chairing the next session which will involve two papers. So thank you very much.


Hi folks, my name is Alex Durgachev and this is my colleague Dave Vasilevsky. We work at Evolving Web, Drupal Shop in Montreal. And today we're here to talk to you about test-driven Drupal upgrades, so hopefully you're in the right place. Before we go further, I want to say thank you very much for coming into a five to six o'clock session, the last session of the day. We thought because it's the last one, it's probably because it's our first Drupal Con presentation, so they knew that, so they put us at the end, but we're made up for it by preparing a lot more than usual, so hopefully you'll enjoy the talk. Yeah, and just in case we have some mountain dew, if you need it, just feel free to grab a bit. Okay, so the outline of our talk today, we'll spend a minute talking about us, an intro to the subject at hand, and then we'll cover the basics of Drupal minor updates, major upgrades, and how does testing fit into all of this. The tools we'll want to particularly showcase today are B-Hat for integration testing, Circle CI for continuous integration, Docker for spinning up consistent development environments, and then after that we'll do a demo called Drupal Docker Marriage that combines the two and really shows a really nice workflow that we've evolved ourselves for ourselves. And then we're going to go into a little bit of a case study of a project we did a year ago upgrading a website from McGill University that was quite hairy and really pushed our teams' capabilities and forced us to come up with some better practices than just naively doing it. And that was a Drupal 6-7 upgrade. And then after that we'll demo a tool that we produced as a result of this and similar projects called SiteDiff, which I actually hope will really be something you guys are interested in trying. It may save you a lot of time and effort. All right, so about evolving, so our company, like I mentioned, is based in Montreal, Quebec. We've been doing Drupal since 2007. We're super involved in the Drupal community. I mean, I've been to like half a dozen or a dozen of these conferences we've sponsored usually. And yeah, so, and our devs have committed code to Drupal core and control modules. The kind of projects we take on, you know, we're not shy about DevOps kind of stuff, with lots of users, lots of content, multi-lingual, it's a big deal in Montreal. The kind of organizations we work with, they really seem to take an interest in search, so we've done a couple of interesting search UI projects. And also, if you have lots of data, you have to import that data. So we're not shy about doing migrations and content, import, and sync. Of course, custom team development and design and responsive design is right up our alley. And we've built apps on top of Drupal, like an admissions app for McGill University. So that's really like treating Drupal as a development platform. And beyond all this, we also do quite a bit of training. Hi folks, we're just coming in. So we do quite a bit of training as well. And the kind of clients that we see, so both across Canada and the United States, so the top left is All Scene Alliance for the Linux Foundation, we've done a couple of projects and we're doing a few more bigger ones just coming up. Parks Canada is a Canadian federal government agency, and as well as buy and sell, achat, vent, JC.ca, it's for Public Works Canada, it's their RFP portal that was a few years ago. That was another Drupal 6 to 7 upgrade, actually. All Hotels was a big portal for Travelocity that was competing with Hotels.com. My lifetime, I think every Drupal shop in New York has worked with this project at one point or another. It's one of the earliest big Drupal deployments for any entertainment. And other local things like McGill University and others. So beyond that, we've done public training in Montreal, Ottawa, and Toronto very regularly, as well as DrupalCon Munich, New Jersey, New York, Boston, and we've done a bunch of private training as well. That's my partner, Suzanne, who leads our training program. We've done it for Health Canada, Parks Canada, Tourism Quebec, Trent, and other teams. And we actually do for both Drupal development teams, both for a dev shop or an organization that has an internal team, and we've even done some remote. So if you guys are interested in good quality Drupal training, please don't hesitate to contact us. Aside from being involved in involving WebSense since I founded it, or I co-founded it seven years ago, I have other programming interests like I've written a Chrome extension recently for translating and learning French, and I've written some red mine and vagrant plugins that people use. Dave was actually one of our first devs when we started the company seven years ago on a part-time basis, and yeah, he was around to show us how to use version control and Linux and the like, and beyond that. Yeah, I basically delve into any open source program that I find, so I've contributed batches to a wide range of programs, from KDE to Firefox to the JSP to Fire. All right, yeah, so there's a good, there's a chance that in the future you might, you see credit somewhere. Great, so that brings us to the talk at hand, Drupal upgrades. So rhetorically I felt obliged to include this, why are upgrades and updates important for security? Well, is everyone familiar with what's being called Drupal Geddin? Yeah, has anyone here not patched to Drupal 732 or above for one of your sites or one of your client sites? If so, we will pause the presentation and we will wait for you to update your Drupal core, because, or just tell us and then we'll play a prank on you if you don't want to do that. Yeah, so it's a huge security vulnerability that affected every Drupal site and within days of its announcement, like, script KDE's or whatever had an automated break-in, or like, hey, had an automated break-in that allowed them to take full control of your server or an execute arbitrary code, which means any server that was running on patched Drupal sites for more than a day is considered compromised and should be wiped. So that's a pretty important lesson to be able to quickly and regularly perform core and contribute module updates. But also, they can bring in new features. The Drupal 7, for example, has many performance improvement features, so if you operate from D6 to D7, you can run varnish without maintaining the press low fork, and obviously the admin UI. If you operate a control module like Webform from 3 to 4, you're going to get token integration, so your little Webform emails can leverage everything that token can do, the core token module. And of course, after Drupal 8 is released, as of now I think it's three months after, they will no longer be, well, they're not promising anymore to backport security releases to Drupal 6. So whenever Drupal 8 is released, whenever it's ready, if you have any Drupal 6 sites you're sitting on, you're going to have to upgrade them to 7 or preferably 8. Great. So many Drupal devs, ourselves included, don't like updating and upgrading. We do it when we have to. We do it when we see an important security announcement. But what's so hard about it? Why isn't it done all the time and regularly? Well, first, it's not entirely clear in every situation what to do. I mean, you have to sit down and figure it out, and there goes a couple of hours that you weren't planning to spend that day on that. It takes time. And we're afraid of regressions, and we hate doing the manual testing, right, because it's not actually fundamentally hard to update the code. What's hardest to be sure that the updated code works and works well, like your site doesn't get broken. It's very possible, I wouldn't say likely, but possible that even during a minor update, you'll introduce a bug that wasn't there before. So you think you're getting an important security release, but no one was really going to go after your site, or maybe it wasn't a factor. But now you've just introduced your bug, and your site is broken. And so people are afraid to just try it without dedicated a large amount of time and having a good reason to do it. So that's what this talk is about. It's to try to talk a little bit about steps so it's at the top of your head after you leave this room. You probably know many of them anyway, but we're going to introduce a few extra tools and processes that make it easier and faster. And a lot of that is going to be focused on the testing side of things, how to verify that your upgrade is actually successful. Because, you know, that's the manual painful part, I suspect, for most of the people in this room and ourselves. Just a quick point of terminology, minor updates and major upgrades. I guess everybody in this room should know, minor is 735, 736. Typically you're only for security updates and important bug fixes, both core and contrib, major upgrades were a major version bump. Both for core and contrib means backwards incompatible API changes. Means if you have custom code that extends it, it might not work. If you have other modules that are supposed to play together, they might not work. So hence the minor updates versus major upgrade. So then we have a couple of slides now about minor update basics, just. So first, when to run a minor update? I guess at the very least, if there's a security announcement that you see, you're also subscribed to this mailing list, Drupal.org slash security. I hope they will send you an email saying these contrib modules have a known vulnerability or Drupal core has just come out with an important thing. So if you see that, that's at the very least do it then. Where to, or more often, I mean, try to stay on top even more regularly than that, where to upgrade? Well, don't ever do it, I'm proud. I know for smaller projects, that maybe you're still kind of maintaining from back when you just started Drupal development as a favor to the organization or person, there is no Dev site. You don't have a Dev site anymore. You don't have a staging environment. But hopefully after today, you'll be able to set your Dev environment in such a way that even in the future, you'll be able to come back and spin one up really fast. So don't do it, I'm proud. And the other thing to keep in mind for both minor and major upgrades is if you cheated and you used a version of a module that you needed to patch or hack whatever terminology you want to use, that's going to complicate your maintenance and your updates, because you'll have to maintain the patch. If you were your colleague or somebody else was taken over after you doesn't know that that contrib module or core module was patched or hack, then they will overwrite your patch and lose whatever benefits it provided. Okay, so how to actually do the update in place? Well, there's two Drush commands that are helpful, Drush UPS or Drush PM update status, and it lists all the available updates, and then Drush up or Drush PM update that actually performs in place all the updates. So this is really great, one Drush command and you're done, right? Almost, in a real word situation, you're going to run this Drush command on Dev manually. It's going to do what it needs, and then you're going to test, and then you're going to see if anything broke, however you test, whether manually or using the automated testing tools that we'll discuss or something else.  And then the next thing you should do is you should realize that maybe there was a mistake in how you committed things. So don't apply the update on prod directly. If possible, apply it on a staging or test environment, and then make sure that works. And only after that process has been applied, staging successfully and tested successfully, then you can be, with confidence, apply and prod. I mean, and this is why in Drupal's update.php, you've seen the language saying, make a backup of your site now. It might be that something goes wrong and you'll have a corrupt database and you'll need to hire Dries and WebChick to fix it for you because it's going to be in an unknown state. Yeah, so basically better safe than sorry in this regard. The beyond the code changes that Drush will download, another thing it runs is it runs a specific Drush command called DrushUpDB, or alternatively you can trigger the same code by running update.php. And what that does, I'm sure most of you know, is it brings the database structure of your MySQL tables and, like, up to the same format as expected by the new code. As code changes over time, you might have a new column in the database where somebody might rename a variable from one name to another. And so if your database didn't get updated to the assumptions of the new code, the new code will actually be buggy and not work well. It might give you a white screen of death. So the first thing you need to do is after you update your code is you need to run DrushUpDB or visit update.php. Great. So that was minor update basics. I ran through that pretty fast because we'll show all of this as an example. So now this brings us to major update basics, major upgrade basics. Well, the first thing to say about major upgrades is that there's no such thing as a basic major upgrade. I guess you probably can guess what the second thing, the second rule of major upgrades. Yeah, so major upgrades can be harder than a site rebuild. Very often, if you do a major Drupal upgrade, you'll have incompatible API changes, and your custom code won't work anymore. Or contrived modules, which assumed that API won't work anymore. Or the contrived modules in Drupal from 6 to 7 or from 7 to 8 might not exist in Drupal 6 to 7. So then you'll have to find another one or upgrade it yourself, or build a custom module that does something similar. So you should be aware of this, that this is a major thing.  Everyone's by now upgraded every one of these modules. No, we found out multiple times in the last couple of years, three, four years after Drupal 7 has been around, that it's been far from trivial at every step. And there's always something different that breaks. Great, so then we're also talking about updates D6 to D7. We put that in the description for this talk, so hopefully you're not disappointed. But I actually don't know how to upgrade to Drupal 8. Does anyone in this room know how to upgrade from Drupal 6 to 8 or Drupal 7 to 8? All right, somebody, you should stick around for questions. People will have questions for you. I'll have questions for you. But from what I understand, the core developers are right now assuming you're doing a site rebuild in Drupal 8. And for now, you're going to just use the migrate module to go and import your content into the new site. Maybe that's not correct. And I know that they're planning to do better than that in the future. There's supposed to be a way. In the future. Yeah, so it doesn't exist yet, as far as I've heard.  So there probably a way will emerge. But if you're following that way in the next year, you can be sure you'll have to get your hands dirty. All right, so major upgrade basics some more. To convince you that this is not trivial, here's what you have to do before you even start going to D7, still in D6. First, from D6 to D7 that is. First, you're going to have to upgrade every single core, both core version, every single core module, and every single contrib module to their latest D6 version. For contrib modules, that means dev versions. Because the upgrade path from D6 to D7 is actually going to assume that you've run all the updates to get to the latest point in D6. So you've got to do that first. And that may take you a day or longer if you have complications. Then you'll have to de-feature as I'll talk about that in a bit.  No, features are PHP code. And there is no update path for features. You'll have to figure out a way to de-feature as your site and put everything back into the DB to have an upgrade path. Then you're going to have to clean up and fix bugs because upgrading to D7 will create lots of bugs. And you want to know, is this a bug that I just introduced, or is this a bug that was there to begin with? Then you're going to have to disable all contribute optional modules because, safer that way. I had a good reason to skip it now. And then you're going to try to redo the upgrade. But you should know that some things will fail in the upgrade path. And then you're going to have to go and uninstall those modules.  Hopefully they don't have much. If they do have tables or things in your database that you need that you don't want to delete, you're going to need to write a migration, like a ddd migration later to capture that back again. And then you're going to disable your theme because you can't disable your core theme, your main theme, but you have to switch it to a core theme like garland. OK, so you've done this. Then you can perform the actual upgrade, which involves upgrading the code of core and the remaining modules to the highest D7 version. Then you're going to run this Drush of DB, just like we did for the minor thing, but for the major. That may take a while. That may have bugs, like I mentioned. Then you're going to run content migrate, because what you're going to figure out is this core upgrade path and contrib module upgrade path that just ran that doesn't pick up CCK to fields upgrades that the developers have left that as a contrib module called content migrate, and it has its own separate Drush command that you're going to need to run. And that works fairly well. OK, so then you're going to enable one at a time, or two at a time, or three at a time, all your contrib modules that you've disabled and upgraded, and then hope for the best. And you're just going to iterate on seeing if they work, and then maybe patching them if they need to be patched, replacing them if they need to be replaced. Like in Drupal 6, we use pop-ups API for a couple projects for a better admin UI experience. And in Drupal 7, nobody bothered porting that, because it was so hacky and tied to Drupal 6. But in Drupal 7, there's references dialog, which tries to do something similar, and lots of people use it. Great. So then you have to re-enable and test your custom modules. So that's going to be a lot harder, because you're actually going to have to rewrite a good chunk of the code that you initially wrote, retest all that code. Hopefully you've got good tests. I'll talk about that later. And you should know that there's a code or upgrade module that does a code analysis of your custom modules and tells you how to upgrade them sort of mechanically, but it gives you lots of comments to guide you along the way. So you don't have to know all the API changes. It knows all the common changes you need to make. Then once you wrap up your custom modules, you're going to restore and refactor your project specific theme. And then you're going to iterate, iterate, iterate on this, testing the site, finding omissions, finding bugs, and generally getting it to a better state than when it started. Great. So that's major updates in a nutshell. So I'll hand it over to my colleague Dave to see how testing fits all of this. Hi. So we're going to start with some testing basics. And there's a bunch of different kinds of testing that we talk about when we talk about testing in Drupal. The most common one is unit testing, where a lot of modules in Drupal will just have a test. The test uses a fixture for input, uses some basic data structure as input, and some basic data structure as known output. And just test that, test one function or one class. And that's basic unit testing. Then there's integration testing, which tests how different modules fit together, or how the site as a whole fits together. Finally, there's UI testing, which tests how a user or a real browser would experience your site. And one of the good tools that we found for using that is called BeHat, and we'll talk more about it later. And finally, we'll talk about continuous integration, which runs your tests on an automated manner all the time to make sure that your tests are always being run. So first, let's talk about unit testing. Unit tests are great because they're fast. They don't have to touch the Drupal database. They don't have to load every single module in the site. They can just test one single function or one method. And as I mentioned, they use fixtures. You can't use most other Drupal methods in a unit test. So you have to put together a structure as your input and a structure as your output. So let's say you'd have a function that added two numbers. You'd have the two numbers as input and the sum as the output, and that would be all your function would test. It wouldn't be able to test how it integrates with anything else. In Drupal 7, you usually use simple tests for this by making your test classes inherit from the Drupal unit test case. And in Drupal 8, they're using PHP unit, which is a more standardized PHP way of doing unit testing. So unit tests are great, but they don't help you that much for updates. At least the contrib modules unit tests. Because each contrib module has already written tests for itself, and they run the tests every time they do a release, and the test bot runs those tests. And so you can be pretty satisfied that when you update views, views has already been tested in isolation. What you're worried about when you do an update is how will it integrate with the rest of your site? If they've added a method in views or changed the parameters to a method in views, is that going to work with your site or is something going to break? However, they are really good for custom modules when it comes to updates. When you're doing a major update of Drupal, for example, you're going to have to change a lot of code in your own custom modules. And when you do that, you're going to have to make sure they still have the same behavior as they did before. Unit tests are a great way to do that. Integration testing is more important for updates. We still have simple tests in Drupal for integration tests using the Drupal web test case as a base class. And simple test is great, because it is a lot of Drupal integration. You can do things like enable modules and create content and add users. And indeed, you have to do that in order to use simple tests correctly. The problem with it is that by default, simple tests will test your module in isolation. It only tests your module and the modules that your module depends on. It won't test how it integrates with other seemingly unrelated modules. But if you add, let's say, a new field type, it won't necessarily test how that works with views, for example. The other option is you could have your simple tests pull in all kinds of other modules and really do a whole site test, even with simple tests. But that creates kind of tight coupling. Because your site and your tests now depend on the structure of your entire site, and it's hard to maintain. Simple tests are also integration tests with simple tests are also really slow. Because every time you run a test, Drupal basically does a site install. It copies the entire database and installs all the modules that are necessary. Finally, integration tests are troublesome, because you can test things that PHP doesn't see, things like JavaScript, CSS, certain forms. UI testing is what we found to be the most useful for this. It basically tests your site by running a real browser and controlling that browser to visit your site and perform operations. It's very powerful and thorough, because it can run all kinds of JavaScript and other complicated web technologies. There's a lot of examples of them, like Selenium, Casper, JS, but Behat's the one that we've chosen because it has great Drupal integration. We find that UI testing is especially useful when you've got a legacy site where all you were doing before is manual testing. If you tried to add unit tests to that site, it would take a long time before you're able to test every bit of custom code. But by using UI testing, you can test at least a little bit of each bit of custom code in a short amount of time. So let's talk about Behat. Behat is a technology for behavior-driven development that has a Drupal extension that has a lot of Drupal integration. Behavior-driven development is basically the idea that you should write your tests first using a human, readable language. And then afterwards, when you write them at first, they'll all fail, because you haven't implemented the functionality yet. But after you write them, then you can implement the functionality and make sure they pass. It's a great way of handing off work to other people, because if the tests pass, then they've done an OK job. And if you use behavior-driven development, if you write your tests in advance, then you know that your site will be ready for upgrades because you have your tests in place. Moving on. So here's how you write tests in Behat. Here's an example where we have a scenario. And what we're doing here is just we have a site, and the site has articles on it. It has nodes. And when you hover over a certain part of a page on that site, you should see the author pop up in a hover. So we express this using an English-like language. We describe the scenario. We say, when you hover, it should show the author. Then we have a given line that sets up your example. It says, given that I have certain content, and here I'm going to describe the content that I'm given. It has a certain title, a certain author, and a certain body. Then it describes what you do. It says, when I hover over the author region, and the browser will be controlled to do that. And then finally, it has an assertion that says, I should see something. And if I don't, there's a problem. In this case, I should see the text bob. So in this case, the given line, this bit, comes from the Drupal integration of Behat, specifically the Drupal API extension, driver rather. The third part, that then I should see the text bob, is a built-in part of Behat. It just knows how to do that. And the second part is part that we built ourselves. And just to show you how easy it is to add functionality to Behat using PHP. In this case, we just created a method in what Behat calls a context. And the method has a line at the top that tells it what kind of text should trigger this method. In this case, when you say, when I hover over a name of a region, and then it provides a function that just says, what do I do when I see this text? In this case, it looks for a region and then tells the browser to mouse over that region. Behat has a pretty complicated stack, and it can be useful to understand how it all works. There's the Gherkin language, which is this interesting human-readable text that we saw before that's implemented in Behat. And then Behat relies on two separate parts. It has one part that integrates with Drupal, the Drupal extension drivers. This lets you do things through a side channel without controlling the web interface. So you can tell Drupal, create a node, or create a user, or log in without having to click all over the user interface to tell it to do all these things. And then the second part, which I listed first here, is the part that controls the browser. It uses a thing called Mink, which knows how to control many different types of browsers and browser emulators. And through Mink, it talks to Selenium, which knows how to control real browsers, like Chrome, or Safari, or Firefox. And then finally, it talks to the real browser and tells it what to do. Next, we're going to talk about continuous integration. Tests are great, and lots of people write them. But tests can be really slow, and developers get really tired of that and just stop running tests. Also, you just don't always remember.  There might be breakage there. So we like to use continuous integration. That's basically a system that every time you commit, every time you push to GitHub, let's say, or whatever Git service you use, it will automatically run your tests. Often use a build server for this. That way, even if a developer forgets to run continuous integration on their machine, the build server will run your tests, and it will report on the results to the entire team, and nobody can have their individual mistake just mess everything up. We find that for upgrades, this works really well if you have test-driven development, if you have your tests written ahead of time, then this will find basically any important bug. So for our continuous integration work, we use something called CircleCI. We really like it because it integrates with GitHub, which we use for a lot of projects. It's a hosted service. It integrates with GitHub, and so every time we're creating a branch or a pull request, it just picks it up and runs all our tests. It notifies us when something breaks, and it catches a lot of really unusual bugs that we didn't expect at all. We use it to run our entire, not just the tests on our set itself, but the entire deployment scripts as well. So if something weird happens, like a server disappeared that's not really important, but that the deployment scripts are relying on, we find out. If we hadn't run continuous integration for that project, we would have had some time when the site went down in the future, and we would not have been able to redeploy it, and we wouldn't know why. And finally, we like CircleCI because it lets us use Docker, which we use for a lot of our projects. And that lets us be sure that when we run a test in CircleCI, it's exactly the same environment as when we run it in development or when we run it in prod, that we never have CI find problems that don't really exist in our site, and we never have problems that really exist in our site that CI just doesn't find. So let's talk about Docker a little. Docker is a tool that basically lets you run lightweight virtual machines, which we call containers. There, it makes it really, really easy to just run a copy of your site, an exact copy that works exactly the same. You never have to worry about having a different version of something installed, or somebody having a slightly different file system layout. Everything's exactly the same. That means that if something breaks, you can just spin up the site again. If you run an update and things don't look good, you can just go back to where you were before. It also really helps because you have a consistent environment along, amongst all your sites, because it's exactly the same. If one developer finds a bug, they know that every other developer is going to be able to find that too, going to be able to reproduce it. You never have situations where somebody says, hey, this isn't working. And somebody else says, it's working for me. Everybody can find it. So here's how we integrate CircleCI and Docker. CircleCI is configured with a file that they call Circle.yaml, just written in YAML, which is a very simple human readable JSON alternative. So we specify the top that we want Docker to be running on CircleCI's virtual environment. And then we specify what commands we want it to run to set up our site. In this case, we just build our project with Docker. We'll talk more about that later. And we run the project, and we tell it to map certain ports so we can shush into the site. Then finally, we have the test stage, which tells it what to run on our site. We shush into the site, and then we run, in this case, a simple test, a Drush test run. And once we have this set up, then every time we make a change to the site, all these tests will be run. Now I'm going to show you a little demo of using BeHat, CircleCI, and Docker together. So if you were asleep, wake up for this part. So we have the site that we put together, and we're just going to run it. We have a little command that runs it automatically. And all it does is it runs the container that we've already built and has a certain name with Docker. So then we can go to our site. So now you can see this is the site that we have. It's from a barrage of some friends of ours from a long time back. You can see the happy couple here. As you can see, the site has a navigation bar, and clicking on the bar will move between different sections of the page. And every time you do that, the little active section of this bar changes. There's also a form at the bottom where you can register for the wedding. It's been over for a while, but I can still register. And we can see that when you register, you get a little thank you box. So now we can look at the BeHat.yaml that we put together, which defines how BeHat will work and some informational metadata about our tests. So here's how the BeHat.yaml looks. We have a bunch of lines at the top, which define how, which tell BeHat basically to pull in the Drupal extensions. We have to give it a couple of URLs. One tells BeHat how to talk to Selenium, because we're going to use Selenium to drive Chrome when we run our tests. Another one tells BeHat and Selenium how to get to our site in the first place. We have some magic in our Docker files and in our make files that set up these IPs with reasonable values. We tell BeHat to use a certain API driver, which tells it how to talk to Drupal. There's a bunch of different drivers. There's one that uses Drush. There's one that basically doesn't use anything. And there's one, this one, called the Drupal API driver, which we prefer, because it lets you do lots of interesting things like run Chrome, which you couldn't do otherwise. We tell BeHat where our Drupal site's root is. And we define a certain CSS selector and give it a name. In this case, we call it menu active, and it defines the active version of this menu. So right now it points to the R story one. It's important to define that because we're going to use it in our tests. So now I'm going to go into the container that I just ran, the Docker container. Now I'm inside, and you can see that this looks like a Drupal site. I can run BeHat, which is a little wrapper that I set up, and it'll run our BeHat tests. You can see that they're successful. They're all green. And you can see that they're being run in Chrome. It's automatically filling things out and doing operations. So let's show you what the tests look like. OK, so here's our test. We have one that submits the form. It says I should be an anonymous user. I can visit the home page. I can put some data in the form, press Submit, and I should see that little text thank you that we saw before. And we have another test that tests the header navigation. When I go to the home page, then the active section of the menu should be the little home button, this thing. And lodging should not be active. And then if I click lodgings, then lodging should be active afterwards. So now let's start doing some upgrades. You can run Drush Ups, and it'll show us that some upgrades aren't available. Actually, a lot of upgrades. So one of them that we want to look at is Webform. Because Webform is a security update, and we don't want to be at a date. So let's update it. I'll do Drush Ups dash y. So you can see that it updated the code, and it performed some up DB steps that's here, and now the update's finished. And so we can test if it still works by running our command. And everything looks OK. Then let's try another upgrade. One of the other ones that we saw was Bootstrap, which is our theme. And we'd really like our theme to be up to date. So we can do that. Update Bootstrap. Now when we run our tests again, you can see that the first test, using the Webform, is successful. But the second one fails. And that'll make us think what's going on. And we can visit the site and see. Now if we reload, you can see that this isn't clearly not working right. It's not in the right place. And the slow scrolling isn't working, and there's no active indicator. So VHAT has detected a broken update on our site. On a larger site, you wouldn't just test this live. Actually, let me show you something first. One nice thing about Docker is we can just reboot the site immediately from the stored image. And it's working again. Everything's fine. It's just really nice when you're doing tests, because you never have to worry that you're just going to miss everything up, and you'll never be able to recover. So on a larger site, you would probably not do these manually, right at the terminal. But instead, you would turn them into pull requests, which is basically, if you're not familiar with pull requests, it's just basically an issue or a bug that has some commits attached to them and says, I think these are ready to go for our site.  One of them does Bootstrap, and one of them does Webform. And CircleCI, which we've set up for the site, has annotated them with little icons indicating whether our tests were successful or failing. In this case, we can see that the Bootstrap one failed. And if we click on it, there's a little Details button. You can see first that this was actually the Bootstrap update that we expected it to be. So you can get how it cooperates. So all that was updated was Bootstrap. It's really a Bootstrap upgrade. And then we can see what CircleCI has to say about this. Why did it say it didn't work? And it has all the different steps of the site, the same way we did make run just a moment ago. It did make run. And then it runs the test at the end. And you can see that the exact same test failed. Because we were using Docker, and on CircleCI, we had absolute confidence that the test that succeeded locally should fail remotely, and it should succeed remotely, rather. And the test that failed locally should fail remotely. They were exactly the same. Yeah, any questions about the demo? Talk to us about a question. Sorry. Yeah, so I noticed in your test cases, you had a wait for Ajax. And more in Cucumber when I worked in Rails, there was never really, there's a lot of talk about how to actually wait for Ajax. I was curious if you guys had any magic or if it was just a sleep or wait. No, I mean, what VHAT does for Drupal by default now is kind of sad and not likely to work in all cases. I think it's the kind of thing where maybe you just have to customize it for your tasks. All right, is that anything else? OK. All right. So that was a fairly simple website that we did as a favor to a friend a couple of years back. And we thought it was a nice combination of Drupal and Docker and VHAT to show you guys. And I actually want to add that in the slides, there's a link to the GitHub repo for that. It's all open source, so you guys can poke around at the VHAT YAML file, the CircleCI YAML file. So it's all there. And even for the Docker site. Now let's talk about something a little bit more involved. So we have an upgrade case study for McGill University. The site is their course calendar, which is the Canadian parlance for an academic catalog, basically. It lists all the programs, all the courses, and all the regulations that used to be printed up every year in a book about this thick. And now it's online. These are legal documents that students follow as part of their academic program. They can sue if they are not graduating, but they should be according to that year's version of the program. There's a bunch of metadata, lots of cross references in Drupal 6.0 and old references. Because there's so much data in there, it's a search driven UI, and there's lots and lots and lots of data. So the search driven UI was back when we built the site originally five, six years ago. It was one of our first Drupal projects. And Drupal was a very new thing. And we actually kind of pushed the envelope a little bit with having search tabs. And within, there's different facets for each search tab and different content types and different templates. And we also had embedded search list sections. You navigate to Arts Undergraduate through the menu, and then now you have a search just that section link. Which was actually not available in the Drupal Solar Integration Module, Apache Solar in Drupal 6. It is in Drupal 7.0. I think partially because of some of the work we contributed back, we did the project. So we were happy that Drupal 7.0 search API did all of our custom stuff.  Another interesting part of the site was there's a huge hierarchical organization of every single page on the site. And so from a user's perspective, there's like 10,000 items in a menu driven hierarchy. And this consistency for the menus, the breadcrumbs, the URLs, probably other things that I'm forgetting now. But actually, there's only a few hundred menu items in the primary links, which is the Drupal 7.0 main menu. And the rest are actually in separate book menus because all these regulations are being written by different academic units and teams with a different import workflow. But each one of those top level books sits in the primary links. And then we had a lot of custom code that sort of glues each book menu to its right spot in its primary links menu. And that code used menu tree page data, menu tree all data, menu block, API, and so on. What else is interesting is the site has about 70,000 node revisions per year. There's five years. And each one is a separate Drupal database. Most of the content from the site is being imported from McGill's academic ERP called Banner and Sun Guard Banner. And for the regulations, that's being imported from Documentim, which is an EMC document management system, content management system. There's 15 content types, 170 field instances of fields per content type, and lots of node references. And we also have lots of custom input filters, for example. If anywhere, there's a course code mentioned that's going to get linked to the right page. What else made this project challenging is that we wrote it four years ago as one of our first big Drupal projects. And since then, there's been four years of cruft, like Debs who are doing their best to understand what's going on, who didn't write the original code, who copied and pasted a block of code somewhere because they had a related use case and modified a little bit. And I don't think anyone's guilty. I mean, we maybe didn't document it well enough. And maybe they didn't figure out exactly what the hell we were trying to do well enough. But after four or five years, there's a lot of code that nobody in this world could understand exactly why it was written that way. All the news, it kind of worked. So when we're going to upgrade to Drupal 7, and when we're going to break everything, we said, OK, well, we can't try to fix all this code that we don't really understand why it works. Let's refactor it in Drupal 6 first. We also had a legal requirement that everything must be correct. And another major challenge is we didn't deliver an updated code base and a database dump. We delivered an upgrade process that would work on their production database that's on as we were developing. And that would work on the other four years, two or at least, with adaptation. So what made the project easier than other Drupal projects actually is it had very few contrib modules, 20 to 30 standard stuff well supported. McGill's very disciplined in that way. Almost all of it is anonymously accessible. The content is imported, but doesn't change beyond that. And we knew the original code, at least, in some form or some years ago. And the client was a fairly disciplined client. They had a solid development team. They knew this was a hard project. Anyway, they weren't trying to fix everything that they didn't like about the site, come up with a new organization, and so on. This is just an upgrade project. But there were still surprises that we didn't necessarily expect. I already mentioned that the de-featurization that we had to do at the start, I guess we didn't figure that out until we started, we were surprised that we couldn't even get a deployment of a dev site that's exactly the same, because there were some custom modules on McGill that wouldn't run outside of McGill's servers, or they didn't have the legal ability to share with us. So we had to work around all that. And so our deployment site was an approximation to begin with of their deployment. And we also figured out along the way that when you run that DrushFDB and then run the content migrate, that takes two days because there's just so many fields and so many records for each field.  So we worked around that. And then we discovered MISC upgrade path bugs, modules that had a broken update path, despite the fact that Drupal Cell hasn't been out for years. So what helped, what did we resort to? So first, we did the Drupal 6 refactoring in a test room kind of way using unit tests. Second, we took the content migrate, which was the main culprit for the two-day sting. And we made a completely re-factor version, I guess, for lack of a better word, that ran all the transformations as a single query. And that was much faster. And we tested that. We used Docker that they just talked about for the build process automation. And we developed an integration testing tool called SiteDip that we'll talk about that really made us confident that at every step along the way we actually had the exact same content being moved forward. So for the refactoring side of things, when we were developing this stuff in D6, we said let's clean up all this code base, let's get rid of all this duplicate code. So because it was custom code, we wrote a bunch of PHP unit stuff. We could have used simple tests, but we were sort of forward-looking to D8. And it was OK. It wasn't too complicated to run PHP unit with D7. You just had to write some wrapper scripts and require some files manually, or you can even try auto loading with Composer. We used fixtures that were really super for testing our menu gluing functions that we had, because we had input primary menu simplified looks like this, PHP array data structure. Input book menu data structure looks like this. When they glued together, they should look like this. So that was input fixtures and output fixtures. And we actually used this to refactor the code and make sure that every single change we did still worked to give proper menu output the whole time. And same for nodes. And because we were refactoring the code, we were able to make sure that we were able to feed it fixtures and mock implementations of Drupal functions instead of the real thing to really decouple it. So that's called dependency injection. If you're trying to test code that uses Drupal functions otherwise, it's actually quite tricky. So it's something to be aware of. So our build process, I don't have too much time to go into it, but we had to deploy it in Drupal 6 and make sure it mirrors what they have in production. We had to refactor it to make sure we didn't break anything. We had to de-featureize things and prepare for upgrades, as I talked about. Then we had to run the actual Drush UPDB and the code update. Then we had to finish that off with content migrate. And we had to do all kinds of crazy adjustments, which I don't have time to go to, but these are three or four scripts that have 30 Drush commands each, fixing various bugs and settings. So that took a really long time. Like I said, initially, content migrate along took two days initially. We pared down the production database to have only one faculty with about 10% or 5% of the content. So we were actually doing the upgrade on a subset of the content, which really allowed us to iterate a lot faster. Still, ours, but better than days. Then in parallel, we rewrote content migrate into content migrate tweaks that made certain assumptions that were shown to be correct that allow us to do the whole update for the whole field tables one table at a time with an insert select query, old table structure, new table structure, instead of one record at a time, one delta of every field at a time. So this took 30 minutes before all the fields instead of days. And we were able to actually do a checksum in MySQL of the resulting thing of the full content migrate with all the hooks that it allows and one record at a time. And the simplified form. And we saw that the output checksums are the same. So we were sure that our optimizations were valid for this project, maybe for your projects with crazy custom modules they wouldn't be. Great. And then we have some other performance improvements. Then we needed to come up with a build automation tool, a build environment that ran these builds. It had to be easy to deploy dev and testing environments that are consistent with each other. So we saw a bug in one, we saw another. We needed to have checkpoints. So first for the initial deploy of D6, then the refactor D6, then D6 prepared like all the modules disabled, then D7 up here. And then this was for testing. We needed to make sure that every step along the way we didn't introduce bugs with everything we saw. So we needed something that allows us to have side by side deployments of these steps for iteration. And then we needed something that's simple, because whatever our crazy deploy tool was going to be, McGill Devs weren't necessarily going to learn Chef or Puppet or this or that. So we needed something that looked a lot like bash. Like I guess where you see where I was going to go with this, Docker fits the bill for this quite well. We used a bunch of different Docker files, one for each step of this process that I described. Each one of those Docker files, when you build this image, it starts with a clean Ubuntu image, and then it starts installing all the packages, configures like V host settings and like, runs our deploy scripts, which includes checking out the code base at the right branch, pulling in the database, and then doing all the refactoring and the Drushoff DB. And they worked well, and these Docker files actually look almost line for line, like bash scripts, except the catch is every single line it runs, every command at every step, it actually produces an internal cached image, like hard drive snapshot almost. And it can detect if nothing changed in your built script since the last time you ran it, between lines one and 33, only in lines 34 there's a change. It'll use lines one to 33 snapshots as a base and continue, so that speeds it up greatly. So this worked super well, but we still had to experiment a lot with setting it all up, with various make files, you have to like, leverage some pretty good Linux system and stuff, and there's more than one way to do it, the same problem. So it wasn't obvious how to do it, but we got it working for us pretty well. And on the testing side of things, so that was the deployment script, and that really saved our button. On the testing side of things, we needed to make sure that each step was correct, right? So we needed to make sure that our dev D6 reflected prod in a meaningful way. We needed to make sure that there were no D6 refactoring problems that were introduced. We needed to make sure that once we did upgrade to D7, it was just like the D6 refactored one. And we were thinking, what kind of tool can we use to automatically compare it?  How are we gonna capture all that? I guess we can have representative pages, but exactly what are we gonna compare each element, or what? And the main legal requirement was like, this static content that existed in this version needs to be at the same URL in more or less the same place than the other version. So the HTML output shouldn't change very much from this upgrade, right? So we said, well, why don't we just see if we can do an HTML diff on a page-by-page basis? So that's where I'm going with this, that's what we did. And we had the tool to track our update progress. We could see which pages had diffs how far along they were. Yeah, so the tool that we ended up refining in the course of this and previous projects called SiteDiff, it's open source, it's on our GitHub page. And the way it works is it downloads a subset of pages from the before site and the after site. It also could be the same site before it's cached and then you change it and re-download it and compare. And then it computes the diff at every page.  But they're very easy to take out with a simple regex. So this tool lets you provide these regexes to quickly clean out the differences you don't care about.  But because diffs are way more complicated than BeHot, we also have a web report that's fairly useful, that bullshit. And what's amazing is actually it took this giant upgrade with all the complexity of the site and broke it up into like almost gamified the task, make these diffs go away. Is it a spurious diff? Write a regex, easy, done. Is it a real diff? File a bug and work on this and fix the bug. So it really allowed us to track the upgrade process. And then when we're done, prove that, well, not prove, but be quite confident that we didn't miss anything. So the URL, the URL before, yeah. So the configuration here, this is the before URL. Here's the after URL, like I mentioned. Here are the paths. Obviously this is a simplified file. This is the paths that it takes. And here's a sanitization rule of what it could look like. There's different kinds of sanitization rules. Like you can have a CSS style selector that says remove this block.  It's a block I don't need to diff. So, but this is just a simple find and replace like for absolute URLs. And here's an old screenshot of what the report UI looks like. It's a little bit different now. Dave will show that in a quick demo after this. But what you see is here's the two URLs. Here's the, for each page that I tested, the before link, the after link, if you actually want to visit them and whether or not there was a diff.  So you actually see which parts of the line changed. And you also normalize the HTML so that it's nice diffs. So there's, yeah, the advantages I've already talked about, but particularly we have caching and we have parallelization. So it's actually quite fast and quite thorough. But as we talked about earlier, obviously it doesn't pick up JavaScript errors or CSS errors because it just analyzes the HTML. If you have like workflow and web form kind of stuff, you're gonna need something like BeHot to check that. I mean, this is really comparing HTML. But every Drupal site has, this is useful for every upgrade, but it might not be enough if you have something that's quite a lot more complex than a static site. And the UI, for example, can't do much to help you there. And the use cases for it are for refactorings. Comparing deployments is my Dev and Prod the same. They should be. For content migration, even non-Drupal to Drupal and for upgrades. And we have a quick demo in the next few minutes that they will show. All right, hi again. So I have a different site we're gonna show you this time. Should already be running. Okay, so it's a pretty simple Drupal site. There's not that much here, but there's a few content types and we can see them here. There's the basic article and basic page ones and there's just a test type. So what I'm gonna show now is a basic demo of how to use SiteDiff, getting started with it. How you can use it on your own site to look for differences over time and how you can use it to detect bugs on upgrades. Specifically gonna show it in a slightly different mode than the one Alex was talking about. Alex was talking about how you can compare like one site to another site, but you can also use SiteDiff to compare a site to itself as it was at an earlier point in time, which is really great for things like updates. So I have a directory here and I'm just gonna initialize SiteDiff with this site. So I have my URL and I'm gonna do SiteDiff in it with my URL and this will create a configuration file for me. It'll visit all the pages of the site that it could find. It crawls the site automatically, finds a bunch of pages and for each of these pages it stores the content in a cache file. You can see it here. There's a cache file right there and it also creates a configuration file, SiteDiff.yaml that we'll be looking at later. So I haven't made any changes to the site since I just did the diff. So an initial SiteDiffDiff to do a comparison should you would think show nothing, but instead it shows a whole lot of things. What's going on here? There's a whole bunch of things in a Drupal site that change every time you visit a page. Some of them are things like the form build ID which is basically a random string which Drupal creates every time you visit the page. We're not really interested in that kind of change. So we're gonna take a look at the SiteDiff configuration file which lets us exclude them. We have a whole bunch of things that we call sanitization rules here and one of them is here, strip form build IDs. It was automatically added to the configuration file because SiteDiff detected that it might be useful but it left it disabled by default just in case you didn't really want it. So we can remove the disabled line. Whoops. You can remove that. And now if we do SiteDiffDiff again, we can see that it's not there anymore. There's different things that are differences but that one is gone. So now I can reinitialize SiteDiff where I turn all the rules on so you can see how it really should work. Now when I run SiteDiffDiff to do a comparison it excludes all the spurious changes and it says it's all successful and nothing has changed at all. Now I'm gonna show you how you can add a single page and SiteDiff will detect that change. Just as an example of the simplest possible change that SiteDiff could detect. So here I've added a node, it's on the front page and so there's a change to the front page and we would hope SiteDiff would detect that. So let's find out. We do SiteDiffDiff and it does indeed find some changes. You see that the notice that Drupal gives you the first time you visit a site that says there's been no front page content, that one's gone. And a lot of other stuff has been added including the node that we just added. So this was an expected change. There's nothing unusual about us adding something and that adding to the HTML output. So we can just tell SiteDiff we're happy with that. We don't think that's a change that we are interested in anymore and we're gonna keep the site as it is now with this added content as the new baseline for future comparisons. So there, we did a store and that tells it to use that as the baseline. Now we can go to our site and we can try to do an upgrade. So this site right now is using Drupal 7.35. So let's try updating it and get to 7.36. So it's gonna take a minute and Josh is gonna download all the code for Drupal 7.36 and run up DB and hopefully if the update's good then nothing should change. But if y'all have been paying attention there was a bug in Drupal 7.36 where some content types would just disappear depending on the circumstance. So now if we run the update now if we go to the front page everything looks okay but if we run SiteDiffDiff we find that there's a lot of stuff that's changed. This is really hard to read of course because it's a giant command line diff. So we have a web UI that we can display. I'm gonna launch that now by typing SiteDiffServe and we get this little web report. It tells us that several pages have changed like note add, note add article and we can see what changed. So for example, note add article we can click on a diff and it displays us the whole page the whole HTML of the page pretty printed so it's easy to read including a diff. In this case we can see the page is still there but Lorem the content type that we had before has disappeared it's just not there anymore. We can it can be a little hard to read these diffs so we also have a side by side display. If you click this link that says both sites it shows the old site as served from the cache this no longer exists on a real web server but we still have it cached and in SiteDiff and the new site as it currently exists and you can see that Lorem existed inside bar here but it didn't exist here. So even though your homepage looks exactly the same as it did before, SiteDiff detected a change that would have broken your site and yeah that's basically our demo. We hope you tried out SiteDiff and we hope your upgrades go well. All right, thanks very much guys and we have one minute for questions if anyone is brave and hi. So let's say there's a site that's really not updating from Drupal 6 and we saw that it's gonna go unsupported so what should be our strategy at that point? Should we just keep an eye on the forum and see if there's a security update that we could patch and just survive that site for its remaining life? That's a great question, I'm not sure. I'm actually not sure what's best. I think the Drupal community expects you to upgrade. That's why they pushed back. The end of support for security fixes for Drupal 6 to three months after Drupal 8 comes out. Originally it's supposed to be the day Drupal 8 comes out so you do have three months to upgrade or figure it out. Or panic or yeah. So that's a great question that the community doesn't in my opinion have a satisfying answer for. Hi, I always find myself manually doing minor upgrades for plenty of sites. So what I thought is maybe fork a branch of each website and then apply the update automatically and then merge it to fit success also. Do you recommend that you see any problems with that approach? Sorry, I actually couldn't hear you. Maybe you can speak louder? Yeah. Yeah, I always find myself manually doing minor upgrades to a lot of sites. That's very, that's a drudgery actually. So is there any, you foresee any problems with automating this whole thing? I think with tools like this, it becomes easier to imagine how continuous integration can give you some peace of mind. So if you have an excellent set of VHAT tests or if a tool like SiteDiff can give you peace of mind. So if your tests are really good, perhaps you can do it. There's something called continuous deployment. The like hosted tools, I know one I've tried recently called Cloud 66 that integrates into GitHub and with your CI testing and Travis or Circle. By the way, I don't have automated tests for all my sites. You don't? Yeah, so you do? No, I don't have it. You don't? So you can't automate, in my opinion, until you have good test coverage, you can't really automate that. But once you do, that's called continuous deployment and that's an emerging trend that's really exciting. Thank you. Is there any more questions? No. All right, well, thanks very much everybody and please find us tonight or just after this and I'll be very happy to chat about this with you guys. Thanks a lot for coming to our late session.


Statistics and Excel, Population Variance and Standard Deviation. Get ready, take it a deep breath, holding it in for 10 seconds and looking forward to a smooth soothing Excel. First, a word from our sponsor. Yeah, actually, we're sponsoring ourselves on this one because apparently the merchandisers, they don't want to be seen with us. But that's okay, whatever.  Like our CPA six pack shirts, a must have for any pool or beach time. Mixing money with muscle, always sure to attract attention. Yeah, even if you're not a CPA, you need this shirt. So you can like pull in that iconic CPA six pack stomach muscle vibe, man.  Yeah, as a CPA, I actually and unusually don't have tremendous abs. However, I was blessed with a whole lot of belly hair. Yeah, allowing me to sculpt the hair into a nice CPA six pack like shape, which is highly attractive. Yeah, maybe the shirt will help you generate some belly hair too. And if it does, make sure to let me know. Maybe I'll try wearing it on my head. And yes, I know six pack isn't spelled right, but three letters is more efficient than four. So I trimmed it down a bit. Okay, it's an improvement. If you would like a commercial free experience, consider subscribing to our website at accountinginstruction.com or accountinginstruction.thinkific.com. Here we are in Excel. If you don't have access to this workbook, that's okay because we basically built this from a blank worksheet starting in a prior presentation. So you could start back there. However, if you want to start here with simply a blank worksheet, you can do that as well. If you do have access to this workbook, there's three tabs down below. Example, practice blank. Example, in essence, answer key practice tab having pre-formatted cells. So you can get right to the heart of the practice problem. Blank tab is where we started with just a blank worksheet so we can practice formatting cells within Excel as we work through the practice problem. So last time, what we did is to try to think about this concept of the standard deviation, which gives us an idea of the disbursement, the spread of the data around that middle point, which we are defining as the mean. We thought about the intuitive way that we might come about this if we didn't know firsthand or first off about the standard deviation calculation by starting with an average deviation where we basically took our data points. We've had a very simple data set and we took our data points and we compared it to the mean, the middle point, the average, and then we basically took the absolute value of those items and divided by the count to get a number to give us an idea of where things are populated around that middle point. So we basically took the mean, the average of the distances from each data point to the middle. Now let's make a quick little histogram here just so we can see our data. So I'm going to select our data set and go to the insert tab and then insert tab, chart. Let's add a histogram that we've seen in prior presentations. Pretty boring histogram like that. Let's add a couple buckets here. I'm going to put some buckets down below and we'll go into our buckets on the left. Let's make like eight buckets just to make it. So there we have kind of an idea of our data set, right? Like if I was to picture this data set, what we have is that middle point, the average, the mean is in the middle, which doesn't have any, which is here, and then the data are around that. So we wanted to include some negative and positive numbers just to show that you might have negative and positive numbers on the mean around that midpoint. So then we have two on the negative side and two on the positive side. So that's kind of a pictorial representation of the data. And we're trying to say, well, the middle kind of point and this small little data set is the middle of zero, right? And we're trying to think about what's the distance from basically that middle point with the small data set. Okay, so now we're going to do a similar kind of thing, but now we're going to use the actual calculations that are typically used. And that's going to be the standard deviation and we'll calculate the variance, which is kind of a component of the standard deviation. Now be aware that there's different calculations for if you're dealing with the entire population versus the sample. We're imagining an entire population firsthand. So remember the two buckets we talked about of kind of statistical problems. One, you have all the data, that's what we're imagining here. So we're dealing with the entire population and two, where you have just simply a sample of the data and the calculations will be a little bit different. So right now we're going to look at, they'll be very similar, but a little bit different. Right now we're going to be dealing with a population, the entire population. All right, variance of the population.  And then let's add another formula.  So now we've got our equation item. I'm going to go to the tools now and then ink. I'm going to write in the equation with our little ink thing here. So let's see if we can write this thing in and see if it'll populate properly. So here we go. So I'm going to say this is going to be a sigma. So usually shown as a sigma squared. So it's not seeing my sigma thing. There it is. Sigma squared. And then so here we have it. I'm going to say that that's equal to, that's what we usually use to represent the variance. So the symbol oftentimes will be sigma squared. Okay. So then we're going to do our sum sign looking like this. And so then on top, I'm going to put an N up here, which it doesn't see yet. But then when I go down here and I put the I equals one, then it sees that it still doesn't see my N up top. So okay, let's see if I erase the N. Erase the N. The N is too ugly. It doesn't want to see it N up top. And let's erase this. I think I put a J there. Let's make this an I. Make sure it's an I. So I equals one. Okay, I'm going to keep on going even though it still doesn't see my N. And I'm going to say that this is going to be a brackets. I'm going to say X. So it thinks it's a C, but I'm going to put an X and it picks up the X and then sub I X sub I minus mu. Which is representing the mean. Close it up. And then we're going to put squared up top. So there we have it. It still doesn't recognize my N. What do I have to do? Excel for you to recognize. So I put my N here. Let's try to circle it. Say what? Why can't you see that? So it's still N. So there it is. So I circled it. There it puts the N up top. All right. And then let's put that whole thing over the top of an N. So there we have it. So you can see this is similar to what we did before. And that we're going to take each of our data points. We had four data points. And we're going to subtract them from the mean represented by mu, which in our case was zero. But this time we're going to square them. So that's going to be something that's a little bit different than last time. And then dividing it over the number, which is N. So that's going to be our variance calculation. So I'm going to say, all right, let's insert that. Now this is going to make more sense when we then do the next step to go from the variance to the standard deviation, which we're going to take like the square root. So in essence, we like square it. And then we take the square root of it, you know? So which kind of negates to some degree kind of like the squaring, right? So it's a little bit different than what we did before, which we just said, let's just take the absolute value of it so we don't end up with the negative numbers that will net out to zero. In this case, we're going to square it, which has a similar kind of characteristic that it's not going to, because when we square it, we're not going to get the negative numbers. So that does something similar to the absolute value, but obviously it also increases the value of the numbers. And then we're going to divide it by N. All right, so let's go home tab, font group. We'll make this orange. Let's increase the size of it a bit. And so that looks good. All right, and then we're going to do another one, which is going to be the standard deviation for the population. Standard deviation for the population. Let's make this header formatting, home tab, font group, black and white. Okay, so this is going to be much the same as this here except that we're going to take the square root of the entire thing. So we'll put the whole thing under a square root, for example. And that's why it's going to be represented not with a sigma squared, but simply a sigma. So because we're going to take the square root, remove the square root here and take the square root. Okay, so and then let's go to the insert tab and just draw it again. So I'm going to say make another equation. See if I can write this, hold on a second. Not that that's not what I wanted. Let's do this one. And let's see if we can write it again. And so I'll just do it real quick here. Okay, so I basically wrote the exact same thing except I don't have a squared on the sigma. And then I'm just going to add the new thing I'm going to put I'm going to try to put this whole thing under a square root symbol like so. And so there we have it. So if we were to remove the square root, we would in essence have that variance that we looked at last time, which is we're going to take each data point minus the mean. And then we're going to square it, which has the property of removing all of the negative numbers. Therefore we don't need to do the absolute divided by the count, the number of N. And then because we squared it, you can kind of think about it while we squared it. So what if I then take the absolute value of it? One of the things that that will do is it's going to it's going to remove the negative numbers because when we squared it, we got negative numbers and then we can absolute it, which kind of negates to some degree the squaring and and so now we've come up to kind of a similar thing that we would have, but not exactly similar. That's going to be one of the points when we did the average here. So let's go ahead and insert that. So we're going to bring that down here. So let's pull this down under here. And what's my size? This was came out to be 16. Let's make this 16. And let's make it orange. So you could see this is kind of similar to what we did with our intuitive calculation, which was taking each point minus the mean absolute value, not squaring it, right, but we took the absolute value, get rid of the negatives divided by two versus this where we're taking each item minus the mean and then squaring it removing. So we don't have to do the absolute value, but now we've squared it divided by N and then in essence, taking the square root. All right, so what's the different? Let's see. Let's do the actual calculation and look at our data set. So I'm going to copy my data set over here. Let's just copy this column. And so I'm going to see if I can copy just this. Let's just copy that data set and put it over here. Let's make a skinny V put in my cursor between V and W making it skinny and paste it right there. So it's not in a table, even though it looks like a table because I only copy part of the table. So let's go to the insert tab up top tables and make a table out of it. And there we have it. All right, so then I'm going to do the same starting point. We're going to have the mean, the same top part. I'm just making the numerator here in essence. So we take the mean, which is equal to the same thing we calculated before zero, which is simply the average of our data. So we just took that zero is taking the average of the data, which is, you know, summing them up and dividing by four. And then I'm going to double click on this number. I want to make it absolute. So I'm selecting F4 and the keyboard dollar sign before the D and the one so that each of these numbers are pulling from the same cell. And then I'm going to take the difference against difference. Same thing we did before. This is going to be equal to the six minus the zero. So there's our difference from the mean, which of course are the same numbers in this case, but wouldn't always be that because we picked the mean to be zero. This is where we get something different. We're not going to take the absolute value, but we're going to square each of those differences. So the way you do that is you say equals. I'm going to point to that number and you have a carrot. If you're going to take to the power of something and that's on shift six on the keyboard. So there's the carrot taking it to the two or squaring it. So we're going to say enter. So now we've squared all of them. I'm going to add a total column at the bottom now so we can do that by going to the table design and totals. Now if I sum up the data, if I add up all my data and I just take take the I could take the average by the way if I take the average that's where our zero comes from. And if I count my data here, I could count the data. There's four of them right and then I can take the sum of the differences which is always going to add up to zero because we're comparing everything to the middle point or the mean and then we've got the squared amount instead of the absolute value. So before we had 20 because we just took the absolute value and now we've got of course a bigger number of 104. Alright so now let's take our squared or this is going to be a calculation of the both to this squared difference from the mean. So this is going to be our squared difference from the mean which you can look at either of these formulas but if I'm looking up here I'm going to get to the variance. I've got the numerator so I've got the 104 and then the count so this is going to be the count which is represented by n that equals this number that we counted because we just counted one, two, three, four and let's put an underline home tab font group and underline and that's going to give us then if we divide it's going to give us the variance divide it doesn't want to give me the divide or I have to do it this do it this way and then divide and then variance. If I want to represent the variance with a symbol I could use I can format the cell as one way we can do it or we can enter a symbol for it so for example if I was to enter a symbol and I go to the insert tab symbols I would then go to the normal text Greek and gothic and then you can look for it up top I also have it down here in my recently used so there's my sigma insert it needs to be squared so I'm going to put a two and then select that to right click on it format the cells make it a subscript and so now we've got a subscript of the two I don't know why it's so large though which is kind of odd uh what happened in my I have a huge number two uh it's just the font size got ridiculously large for some reason whoops let's make this a two and bring it down to I think it was 11 is the font 11 something like that this font is 11 number two it needs to be at 11 okay alright and then that's going to be equal to this over this 26 and then we're going to get the standard deviation standard deviation which is represented by just a sigma so if I go into the insert symbols and enter a sigma insert we do that by taking the square root so we're going to take the square root and so that's going to be equal to this actually you got to do a formula with that so it's going to be the square root function which equals sqrt square root of the 26 gets us to five now let's add a couple decimals and you can see it's not exactly five it's a 5.1 so it's a little bit higher which is typically the case when we use this method as opposed to our simply intuitive method of just the average the average deviation so you get a distinct number and that's another one of the properties that is different from the standard deviation than the average so we might go into that in a little bit more in future presentations just to drill down on that point as to why another reason why we might use this number as opposed to doing a calculation like this but for now let's go ahead and make this blue and bordered home tab font group making it blue and bordered if you don't have that blue it's in the color wheel there's the blue and now of course we can also get to the shortcut there by using our excel functions so I can say this is going to be the population variance using excel right and I'm going to say that let's make this sell a little bit larger and this is going to be the same as this so I'll copy that and put it here so the formatting is there with it as well and I could say this is going to be equal to the VA and we're looking for these two here varp.pvar.s we're looking at the population right now and we'll look at the sample in a second and more in a future presentation so if I select my data then we get the 26 same as this 26 up top and let's go ahead and make this bracket and blue and then I can take my I can calculate my population standard deviation let's make this one a little bit wider again so I can then copy my sigma it's going to be represented by sigma so this is going to be equal to ST and once again you've got the standard it's these two we're looking at STDEV dot P dot S we're looking at the population at this point so I'm going to say dot P select my data and enter let's add a couple decimals and we get to the 5.1 let's make this blue and bordered now just to compare that to the formulas which we'll take a look at in more detail later which is the sample variance in Excel so that's going to be equal to the variance so the variance but let's look at the sample just to get the difference and let's pick up the data so if I use that calculation I get 35 adding a couple decimals we'll add some decimals here it's even there and then we're going to say if I took my sample standard deviation in Excel equals the standard deviation for the sample then our data we get something a little bit different right so we'll talk more about that in future presentations because we're focused on the population here but let's make that yellow for now just to say that that's a little bit different of the formula for the population okay in a future presentation we might dive into a little bit more on analyzing the difference between using this calculation and why this kind of more intuitive possibly more intuitive calculation another reason why we might use it use this one instead as the default right


Hey, have you heard about this thing called the nervous system of your body if you're wondering no It's not a system designed to make you feel nervous. That's not what it is But then what is it? Well, let's find out So the nervous system is kind of like the wiring system in your body And one of its main jobs is to allow your brain to control all of your muscles For example, let's say you want to wave your hand saying goodbye to someone Let's see how that happens.  Well now the nerves which are present near the skin of your shoulder They immediately generate electricity the moment you touch it They generate electricity and then the electricity goes from there all the way up to your brain and Then your brain processes it it understands where the electricity came from from which nerve it came and it realizes Ah, my left shoulder got touched And now maybe if your teacher is facing you then you will not do anything But the moment the teacher turn turns back Immediately another signal gets into your brain and that signal now goes and contracts your neck muscles and immediately You'll turn back to talk to your friend Isn't that cool? Every single thing that you're sensing right now and every single motion that you can do with your body is due to your nervous system And this is not just for touch all other senses also work this way For example, when you look at something the light falls on your eyes and that gets converted to electricity It gets sent to your brain if you are smelling something again that gets converted to electricity Electricity gets sent to your brain. So you see another thing about the nervous system one of the important jobs of your nervous system It allows all your senses to communicate with your brain using electricity And so this works for all five of your senses Unless of course you are spider-man in which case you will have a sixth sense to but I'm not sure how that would work Okay, so this nervous system is pretty cool, right? But you may be wondering but what exactly is it made of is it really wires do I have copper wires in my body? No, of course. These are not wires. Then what are they? Well, just like anything in our body. They are made of cells Okay, so if you were to zoom into to one of these nerves and you find that actually cells Arranged end-to-end and if you're wondering hey, that's not what a cell looks like I hear you because these are highly modified cells.  I totally agree with you These are called neurons very specialized cells and they are the ones that conduct electricity But of course, I won't talk too much about these neurons mainly because we have another video Completely dedicated to talk about their awesomeness. Okay, so let's not worry about the neurons and the cells as of now Let's think of them as wires as of now, okay? Okay, then another question we might be having is how many parts does this nervous system have? It looks super complicated super branched out and everything. So how many parts does it have? Well, it turns out that broadly we can divide this nervous system into two parts So let me zoom out a little bit so that we can see better All right. So the nervous system can be broadly classified into two parts Let me just write that down over here One is called the central nervous system. I'm just gonna write central over here central nervous system The short form for that is CNS Central nervous system and the second one is called the peripheral nervous system. So Peripheral Nervous system and its short form would be P N S P N S Okay, so what are they well the central nervous system as the name suggests is the central part of the nervous system Which involves the brain? Which is the command center and your spinal cord? That's right Even the spinal cord is the part of our nervous system. So these two things are the central nervous system again Let me just write that down So your central nervous system contains two parts two parts It contains the brain, which let me use purple for that and it also has spinal cord spinal cord Fine, then what's this peripheral nervous system? Well peripheral kind of means Adjacent to kind of means in the side. So peripheral nervous system is everything else besides the central nervous system Okay, so you can see all these branches These branches that you can see they are the peripheral nervous system Okay, and again based on from where they're branching we can classify them into two kinds So again, let me write that down. So even peripheral nervous system can be classified into two kinds If you have branching happening from the brain Okay, you can kind of see over here if they are branching from the brain.  These are all nerves, right? So these branches coming from the brain are called cranial nerves and Then these branches coming from the spinal cord. They are called They are called spinal nerves Again the name pretty much helps us understand. What is what?  So these are broadly to two parts of our nervous system So here's a question. What do you think are the functions of these two things? We've already taken some examples and we've seen how the nervous system kind of works So can you pause the video and guess what the central nervous system does and what the peripheral nervous system does? Okay, so your central nervous system, what do you think it does? Well, since it has the brain in it if you guess that its main job is to process information You're absolutely right. Its main job is to process information collect all that information think about what to do decide Come up with a decision all of that stuff.  Well, we saw in our examples the peripheral nervous system Their job is to send the information from the brain to the muscles or maybe to send the information from your senses to your brain or sometimes send the information from your internal organs Let's say something gets injured then that has to information also has to be sent to the brain, right? So all the communication between the central nervous system and the other parts of your body the other organs in muscles That happens. Why are the peripheral nervous system? Okay, so peripheral nervous system you can I would just say crudely It allows the different parts of your body the different parts of your body to talk to the CNS Okay, so through the peripheral nervous system all the parts your muscles and your organs Communicate with your central nervous system So that's pretty much it So just to summarize our nervous system can be thought of a wiring system that allows our brain to Communicate with the rest of our body And it uses electricity to do that and we saw that there are two parts to it the central nervous system Which composes of brain and the spinal cord its main job is to process information and the peripheral nervous system All the other parts of the nervous system Except central nervous system is called the peripheral nervous system It's divided into cranial nerves the ones that come out branch out from the brain spinal nerves that branch out from the spinal cord and Their job is to communicate between the different parts of the body and the central nervous system