1 00:00:03,490 --> 00:00:13,030 So it gives me great pleasure to welcome Fergus Cooper, Dr Fergus Cooper from the Oxford Research Software Engineering Group. 2 00:00:13,030 --> 00:00:18,430 They have their own website. You can see UWW rc talks to UK. 3 00:00:18,430 --> 00:00:28,330 They're also on GitHub with the username Oxford RC, which all one word capital, our capital R Capital s capital. 4 00:00:28,330 --> 00:00:39,130 Today, Fergus is going to tell us three examples this time how to do automated testing examples, in this case with Python, 5 00:00:39,130 --> 00:00:48,670 but more more importantly, connecting that all up to version control on GitHub and continuous integration. 6 00:00:48,670 --> 00:00:57,850 So Fergus did his doctorate in the Mathematical Institute here in Oxford through one of the doctoral training centres. 7 00:00:57,850 --> 00:01:09,000 Siddiqui's Syst. Biol., from 2013 to 2018 and then set up helped set up with Dave Gavigan and Martin Robinson, 8 00:01:09,000 --> 00:01:13,780 the very Oxford research software engineering group that he is in now. 9 00:01:13,780 --> 00:01:18,880 So with that, I'd like to hand over to Fergus. 10 00:01:18,880 --> 00:01:22,660 Well, thank you very much, Garrett. It's a real pleasure to be here. 11 00:01:22,660 --> 00:01:26,380 And yep, as as Garrett said, I've sort of stepped in at the last minute, 12 00:01:26,380 --> 00:01:33,520 so I've put together some material on how to do continuous integration, how to link that up to, in this case, 13 00:01:33,520 --> 00:01:40,510 a small Python project that I've just set up in the last couple of days and really on good 14 00:01:40,510 --> 00:01:44,260 start off with a very short presentation that just goes through a little bit of a reminder. 15 00:01:44,260 --> 00:01:47,440 And the people who might be what half of the previous talk, 16 00:01:47,440 --> 00:01:53,080 why we might be interested in automating the tests for our software, why that might be a good thing. 17 00:01:53,080 --> 00:01:57,490 And then going through a quick overview of what I'm going to be talking about and then 18 00:01:57,490 --> 00:02:02,050 the risk of tempting fate at the remainder of the talk is going to be all life examples. 19 00:02:02,050 --> 00:02:11,590 Well, I'm going to take the Python project that I've set up on GitHub, and I'm going to run through all of the steps to do a number of things. 20 00:02:11,590 --> 00:02:16,690 That's going to include setting up automated testing in a number of different settings. 21 00:02:16,690 --> 00:02:23,770 And then. Linking that up with a number of third party tools that can. 22 00:02:23,770 --> 00:02:30,880 Further help to to add some robustness and some confidence in the software that you've written and really 23 00:02:30,880 --> 00:02:37,090 the benefit is that all of this will be being run automatically whenever you make changes to the software. 24 00:02:37,090 --> 00:02:42,370 And so it's just one less thing for you to have to think about. You never have to run the tests locally on your machine. 25 00:02:42,370 --> 00:02:47,050 It will all be done in the cloud and bonuses or completely free as well. 26 00:02:47,050 --> 00:02:53,740 So without further ado, I'm just going to start off with a very quickly and overview of the recent 27 00:02:53,740 --> 00:02:58,390 software engineering group never going to pass up the opportunity for quick, quick plug. 28 00:02:58,390 --> 00:03:06,510 So what do we do? Well, we help enable your research by by developing bespoke software for you. 29 00:03:06,510 --> 00:03:11,190 And we can facilitate your research by improving the quality of the software that you're 30 00:03:11,190 --> 00:03:18,360 writing and helping to improve software engineering best practises across academia in general. 31 00:03:18,360 --> 00:03:22,080 Doris already mentioned our website where at RC Dot Oxtail that got up. 32 00:03:22,080 --> 00:03:28,100 And if you go on to there, you can fill in a quick form if you are interested in working with us. 33 00:03:28,100 --> 00:03:37,160 Great, so automated testing, so this is just a really a very, very quick sort of two minute recap from things that Graham was talking about last time. 34 00:03:37,160 --> 00:03:44,840 And really the purpose of an automated testing is ensuring that as you develop the project, 35 00:03:44,840 --> 00:03:51,830 as you work on it week after week, month after month that it stays correct. 36 00:03:51,830 --> 00:03:55,060 You know, it's extremely easy when you've written some functionality, 37 00:03:55,060 --> 00:04:00,100 perhaps some quite complicated functions that may be a little bit of time later you go back, 38 00:04:00,100 --> 00:04:03,970 you make some changes, you think, OK, I've got a better way of doing something. Maybe I should. 39 00:04:03,970 --> 00:04:07,000 Maybe this function should take three parameters rather than two. 40 00:04:07,000 --> 00:04:14,590 And then maybe you forget that some other piece of functionality in your code might rely on the old assumptions that you've made. 41 00:04:14,590 --> 00:04:16,750 And when you make that change a little bit later, 42 00:04:16,750 --> 00:04:22,690 you say that they break something and maybe that thing that you've suddenly broken isn't something that you often use. 43 00:04:22,690 --> 00:04:25,600 Maybe it's not something that gets run a whole bunch. 44 00:04:25,600 --> 00:04:32,730 And then maybe later on, maybe a few months later, even you realise that the functionality that you thought you could rely on. 45 00:04:32,730 --> 00:04:40,680 Doesn't work anymore. And so one thing that's really critical is to automate this testing of the software so that 46 00:04:40,680 --> 00:04:47,460 over time you are keeping in the position where every aspect of the software is working. 47 00:04:47,460 --> 00:04:51,690 Now, this might sound as though it's, you know, an onerous thing to do, but really, 48 00:04:51,690 --> 00:04:59,850 if you get set up with the tools that we're going to be talking about today, you get those tools set up early and use them consistently. 49 00:04:59,850 --> 00:05:04,920 It will actually save you a huge amount of time. But just to take a step back. 50 00:05:04,920 --> 00:05:09,450 First of all, the reasons that we need to do this sort of automated testing. 51 00:05:09,450 --> 00:05:12,780 Number one, correctness, we need to make sure that if we're writing code, 52 00:05:12,780 --> 00:05:17,640 whether it's a short script to do some data analysis or whether it's a large simulation 53 00:05:17,640 --> 00:05:25,360 framework that's going to be doing a huge amount of kind of number crunching. You need to make sure that that code is doing what you think it's doing. 54 00:05:25,360 --> 00:05:32,140 We all know we've all come across little bugs that we've written in in codes, and quite often those bugs aren't necessarily a big deal. 55 00:05:32,140 --> 00:05:35,800 They might just change a little bit. They might not actually change the results at all. 56 00:05:35,800 --> 00:05:41,890 But it's important to have confidence in the code that you've written that is true for you. 57 00:05:41,890 --> 00:05:48,190 You need to know that the code that you've written, the results that you've got are not going to just fall out from underneath you and 58 00:05:48,190 --> 00:05:52,080 you realise that that was a critical bug in the software that you've written. 59 00:05:52,080 --> 00:05:57,330 The people who are peer reviewing the paper that you're writing will once have confidence 60 00:05:57,330 --> 00:06:02,970 that the code that you've written is doing what you've told them that it's doing. 61 00:06:02,970 --> 00:06:11,790 And more widely that we'll get on to later, the kind of wider academic community requires you to have confidence in what your software is doing. 62 00:06:11,790 --> 00:06:17,910 I'll talk a little bit about that on the next slide. But the next point is reproducibility. 63 00:06:17,910 --> 00:06:22,920 If you've just got some software and it's sitting in a directory, maybe it's not even under version control. 64 00:06:22,920 --> 00:06:27,090 Maybe you've got two scripts that take some data that you've generated and turns that 65 00:06:27,090 --> 00:06:33,690 data into a nice plot and that floats is Figure 3A on the paper that you're writing. 66 00:06:33,690 --> 00:06:40,050 We've probably all been in the situation where we get a paper back from peer review and and you need to make a few changes, 67 00:06:40,050 --> 00:06:51,380 they asked you maybe to add in another graph or change something or do something, even perhaps a cosmetic tweak to the graph that you've produced. 68 00:06:51,380 --> 00:07:01,300 If you got the tool set up appropriately, then it's going to be absolutely trivial to go back to the version of the software that you used to. 69 00:07:01,300 --> 00:07:04,960 Create that growth if you're testing is in place and has been for ages, 70 00:07:04,960 --> 00:07:08,740 you know that when you go back to that software version that you used to produce that graph, 71 00:07:08,740 --> 00:07:13,900 it's going to work, it's going to work exactly the same as it worked when you actually created it in the first place. 72 00:07:13,900 --> 00:07:22,360 And in this kind of way, reproducibility becomes trivial if you get the tool set up early and use them all the way through. 73 00:07:22,360 --> 00:07:26,080 So we'll talk a little bit about that as well, but also visibility. 74 00:07:26,080 --> 00:07:32,260 If you're automating your testing, you can signpost that to people when they visit your GitHub page. 75 00:07:32,260 --> 00:07:37,330 When they look at your software, when they look at the website that details how to use your software, 76 00:07:37,330 --> 00:07:41,560 you can show them, Hey, look, we're testing this against all the different Python versions. 77 00:07:41,560 --> 00:07:45,610 We're testing it on multiple different operating systems. We have code coverage. 78 00:07:45,610 --> 00:07:51,100 We have X, Y and Z. If you can just show that to people, but that is something that you're doing. 79 00:07:51,100 --> 00:07:57,070 They can immediately say, OK, this person really looks as though they know what they're doing, they're testing it and all of these different ways. 80 00:07:57,070 --> 00:08:03,460 And I can be sure that if I'm using the software, it's I'm going to want to try and reproduce a piece of analysis that they've done. 81 00:08:03,460 --> 00:08:06,820 I'm probably not wasting my time. They're probably correct. 82 00:08:06,820 --> 00:08:14,170 And having that visibility is going to make it a lot easier for you to disseminate your work a lot easier for, say, 83 00:08:14,170 --> 00:08:18,850 peer reviewers on your publications to believe the code that you've written is as up 84 00:08:18,850 --> 00:08:25,880 to scratch and a lot easier to to get your code out there for other people to use. 85 00:08:25,880 --> 00:08:35,780 So why are you really is this important? I mean, one thing that we've seen over the last number of months specifically in this this time of COVID, 86 00:08:35,780 --> 00:08:41,150 we've seen that there is a huge amount of scrutiny now on academic code. 87 00:08:41,150 --> 00:08:44,720 And you know, there are some specific examples I'm thinking of this. 88 00:08:44,720 --> 00:08:53,720 For instance, the the software that Neil Ferguson wrote that that was the famous paper that that really initiated the lockdown. 89 00:08:53,720 --> 00:08:59,180 That code has since been made available on GitHub and rightly or wrongly. 90 00:08:59,180 --> 00:09:06,650 There has been a huge amount of criticism on the GitHub if you've gone since GitHub now and looked in the issues for that piece of software. 91 00:09:06,650 --> 00:09:12,860 There are a very large number of very critical comments some of them warranted, 92 00:09:12,860 --> 00:09:22,580 some of them perhaps not warranted, but particularly now there is a huge amount of scrutiny and. 93 00:09:22,580 --> 00:09:32,630 You are going to be able to insulate yourself from all of that if you are following the best practises, if your code is well tested, well documented. 94 00:09:32,630 --> 00:09:41,450 It's not going to be possible for people to be as critical about your software as perhaps they can be about software that isn't well implemented, 95 00:09:41,450 --> 00:09:44,150 well-designed, well tested. 96 00:09:44,150 --> 00:09:50,690 The good thing, though, is that there are more tools than ever to help you, so this is not an onerous thing to do if you get set up properly. 97 00:09:50,690 --> 00:10:01,250 And the purpose of this talk today is hopefully to demonstrate to you just how easy it can be to get some measure of continuous integration set up. 98 00:10:01,250 --> 00:10:05,540 Once you've got some measure of it set up, you can incrementally add things. 99 00:10:05,540 --> 00:10:09,860 You can incrementally make it more complicated. You can do more and more and more things. 100 00:10:09,860 --> 00:10:18,320 But really, the first hurdle is getting something set up. Once you've got something sets off, it's dead easy to then continue and carry on going. 101 00:10:18,320 --> 00:10:24,380 And today we're going to look at a number of those tools. So what is continuous integration? 102 00:10:24,380 --> 00:10:28,280 This is a phrase that I've been using a lot already, and I haven't really defined it. 103 00:10:28,280 --> 00:10:33,260 I'm not really going to define it either, but you're going to see some examples of it. 104 00:10:33,260 --> 00:10:40,880 But essentially, we can think of it, at least for the purposes of today's talk. It allows you to automate the testing of your code and much more. 105 00:10:40,880 --> 00:10:46,310 It's something that can interface with often many third party services that help make your life easier. 106 00:10:46,310 --> 00:10:53,000 It can run, usually for free in the cloud. This is not software that you ever have to install on your machine. 107 00:10:53,000 --> 00:11:00,080 This will be running in the cloud for free, and it allows you to test your software on multiple operating systems, 108 00:11:00,080 --> 00:11:11,540 multiple software versions, and it allows you to do that easily. There are a number of different services available that provide this kind of ability. 109 00:11:11,540 --> 00:11:14,150 One is try to see what is up there. 110 00:11:14,150 --> 00:11:22,670 And the one we're going to be focussing on today is GitHub actions and GitHub actions is a system that's built directly into getup up. 111 00:11:22,670 --> 00:11:26,000 So again, you don't need to go out to a different service for this. 112 00:11:26,000 --> 00:11:33,800 And GitHub actions in particular is very generous about the amount of compute resources that you're given. 113 00:11:33,800 --> 00:11:40,830 And what I mean by that is what we're going to be setting up is something that essentially allows you to use. 114 00:11:40,830 --> 00:11:50,940 Virtual machines owned by GitHub in the cloud to do some work, and in this case, the work is primarily going to be testing your software, 115 00:11:50,940 --> 00:11:58,800 but essentially you're opening up a virtual machine that has two or seven gigabytes of RAM and can run for up to six hours, 116 00:11:58,800 --> 00:12:02,640 and you can have many, many of those happening in parallel. 117 00:12:02,640 --> 00:12:10,200 And really, that's more than sufficient for pretty much anyone's testing needs in terms of a piece of open source software. 118 00:12:10,200 --> 00:12:19,320 So it really is very generous. And in this talk, I'm going to give you a very quick tour of a simple Python project that I've set up. 119 00:12:19,320 --> 00:12:27,720 We're going to go through live setting up automated testing that's going to test all Python project against multiple different versions of Python. 120 00:12:27,720 --> 00:12:31,050 Then we're going to set up automated testing on multiple operating systems. 121 00:12:31,050 --> 00:12:37,470 So we're going to want to check that this still works on Windows, on macOS and on Linux. 122 00:12:37,470 --> 00:12:42,660 Then we're going to add in coverage testing, and that's going to be using third party service called code cuts. 123 00:12:42,660 --> 00:12:48,600 Again, this is a free service if your software is open source. 124 00:12:48,600 --> 00:12:55,110 We're going to, depending on time, get on to automated documentation generation using read the text audio and again, 125 00:12:55,110 --> 00:12:58,710 at this time, I'll show you something about something called better code up again. 126 00:12:58,710 --> 00:13:05,310 That said, party service that could be integrated for free on open source projects. 127 00:13:05,310 --> 00:13:13,500 And that's the end of the presentation. So what I'm going to do now is get straight into showing you the Python project. 128 00:13:13,500 --> 00:13:21,960 So the Python project is available on the Oxford RC GitHub, so you're more than welcome to navigate to this. 129 00:13:21,960 --> 00:13:27,960 There'll be some things happening live that you'll be able to look at yourself on your own machines if you'd like to do that. 130 00:13:27,960 --> 00:13:34,710 So if you would, you can head over to GitHub dot com slash Oxford RC slash site demo. 131 00:13:34,710 --> 00:13:41,520 It's completely open. So you'll be able to see things as they're happening during the course of the talk. 132 00:13:41,520 --> 00:13:46,230 So in this project, I'm just going to show a few things. 133 00:13:46,230 --> 00:13:56,270 We have a. Python package in this case, it's made the same as the as the name of the project, 134 00:13:56,270 --> 00:14:03,530 all of the functionality of which there is very little is in this final functionality baked pie. 135 00:14:03,530 --> 00:14:10,820 So in here, I've just got two small functions, one function that is going to take a name and it's going to present a greeting. 136 00:14:10,820 --> 00:14:14,900 And one is a function that tells me, Well, I've written this function. 137 00:14:14,900 --> 00:14:16,190 It's just the first thing that came to my head. 138 00:14:16,190 --> 00:14:22,550 It's going to take a bunch of arguments and it's going to return the minimum of all of the arguments in there. 139 00:14:22,550 --> 00:14:25,220 That happens to be real numbers that have an artificial function. 140 00:14:25,220 --> 00:14:32,530 Not sure why you'd want to do that in particular, but I needed a function to test and then. 141 00:14:32,530 --> 00:14:40,930 In this directory as well, we have some tests, so we have a test functionality pie file that uses the unit test framework. 142 00:14:40,930 --> 00:14:44,800 If you're familiar with unit test or not doesn't really matter. 143 00:14:44,800 --> 00:14:49,840 The point is that there is a command I can type from the terminal that will run these unit tests. 144 00:14:49,840 --> 00:14:59,350 And in this case, I'm going to test some basic things that if I use the Graetz method, it will return the greeting I'm expecting it to, 145 00:14:59,350 --> 00:15:05,590 and that if I use the minimum method, it will return the number that I'm expecting it to return. 146 00:15:05,590 --> 00:15:09,820 So it's all relatively straightforward. And now what I'm going to do is head over to my ID. 147 00:15:09,820 --> 00:15:14,830 I'm using Python today and. 148 00:15:14,830 --> 00:15:22,330 Here we can see exactly the same code. So here I've got the functionality two functions, one called greets and one called minimum. 149 00:15:22,330 --> 00:15:31,470 And if I open up my terminal, I can run these unit tests by typing places and flush them. 150 00:15:31,470 --> 00:15:37,900 Units test, if I run, that's we'll see that it ran two tests. 151 00:15:37,900 --> 00:15:45,540 I open up the test will see the two tests that it ran on the test greeting and test minimum. 152 00:15:45,540 --> 00:15:50,760 And in fact, if I put a Dash V on the end, we'll get a slightly more verbose output from unit test. 153 00:15:50,760 --> 00:15:58,380 And we can see here that it's run test rating, which has passed and that's run test minimum, which has also passed. 154 00:15:58,380 --> 00:16:06,900 So that was running locally on my machine. And what I want to do now is run that on GitHub actions. 155 00:16:06,900 --> 00:16:13,010 So what I'm going to do is go back to my web browser and back to the. 156 00:16:13,010 --> 00:16:21,110 See, I am a repository. Along the top here we have, as you're probably familiar, a number of tops and one of them is actions, 157 00:16:21,110 --> 00:16:28,460 actions should be enabled by default if you've created a GetUp repository since GitHub actions existed. 158 00:16:28,460 --> 00:16:35,300 If you don't see an action tab on your GitHub repository, then you'll just need to head into settings. 159 00:16:35,300 --> 00:16:43,410 And then to actions. And then make sure that this setting is enabled, enable local and set policy actions for this repository. 160 00:16:43,410 --> 00:16:45,510 Once you enable that, you'll see the Actions tab. 161 00:16:45,510 --> 00:16:51,570 If you don't see it already and they're not actions, you can see some history in here because I've obviously been messing around with this, 162 00:16:51,570 --> 00:16:58,560 making sure that this is hopefully going to work for this talk. But if you've not got any action set up yet. 163 00:16:58,560 --> 00:17:03,360 What you'll actually see when you come into this page is something that looks like this, 164 00:17:03,360 --> 00:17:08,820 and this allows you to set up some basic starter workflows, and that's what we're going to do now. 165 00:17:08,820 --> 00:17:17,430 So what I'm going to try and do is set up from scratch a workflow that's going to run the unit tests that I've just shown you running locally, 166 00:17:17,430 --> 00:17:24,450 but testing them on multiple Python versions. So I quite like this one, the Python packages. 167 00:17:24,450 --> 00:17:31,020 This is a test workflow that's going to create and test a Python package on multiple Python versions. 168 00:17:31,020 --> 00:17:45,480 So I'm just going to scan has set up this workflow. And this is going to actually create a file that will be added to your repository 169 00:17:45,480 --> 00:17:52,230 itself in a particular directory and a directory called Dot GitHub slash workflows. 170 00:17:52,230 --> 00:17:58,440 And this is going to create a file with a Yamal syntax that's relatively easy to to see what's going on. 171 00:17:58,440 --> 00:18:02,760 So in this file, which is just being created for me, 172 00:18:02,760 --> 00:18:10,680 there are some key features there's firstly a block up here that tells you when this action is going to be run. 173 00:18:10,680 --> 00:18:12,870 So the really important thing, 174 00:18:12,870 --> 00:18:21,990 particularly if you're the only person developing and you're just using gets as essentially a way of saving your files and you just have one branch, 175 00:18:21,990 --> 00:18:27,420 then the important thing is that this is going to be triggered every time there is a push to the master branch. 176 00:18:27,420 --> 00:18:34,580 It will also be triggered if there's a pool of request onto the master branch as well. 177 00:18:34,580 --> 00:18:41,750 Then it's going to run a job and the job is going to build something it's going to run on in this case happened to latest. 178 00:18:41,750 --> 00:18:49,560 This will run on at the moment open to a floor that will probably be updated to take law at some point in the coming months. 179 00:18:49,560 --> 00:18:55,630 And this particular one is going to be a matrix run again, this be generated automatically, 180 00:18:55,630 --> 00:19:02,570 so you'll see this if you press the same button on your Python repository. 181 00:19:02,570 --> 00:19:05,930 We're going to be testing against all of the currently supported Python versions, 182 00:19:05,930 --> 00:19:10,550 which is 3.5 three to three point eight, and then it's going to do a number of steps. 183 00:19:10,550 --> 00:19:15,680 Some of these we're going to have to edit, but you'll see that the steps here. The first. 184 00:19:15,680 --> 00:19:17,600 Step is to check out the code. 185 00:19:17,600 --> 00:19:28,070 The second step is to set up a Python version, and the syntax here is that it's going to get the Python version from this matrix of options. 186 00:19:28,070 --> 00:19:33,920 So this will be replaced at runtime with either three point five, six, seven or eight. 187 00:19:33,920 --> 00:19:40,580 Then we're going to install dependencies. Now this is going to look slightly different to the default, but my particular repository, 188 00:19:40,580 --> 00:19:49,250 because in my particular repository, instead of our requirements stop text, I should be able to just hit. 189 00:19:49,250 --> 00:19:57,170 Install and then dot, it will just install itself. And I've listed the dependencies in my set up that I. 190 00:19:57,170 --> 00:20:10,110 And we're not going to need playtest might set up the play contains the necessary dependencies, so this install dependencies is going to first of all. 191 00:20:10,110 --> 00:20:18,190 Upgrade pick, then that's going to install Flake eight two, which will see in a minutes, then it's going to install my Python project. 192 00:20:18,190 --> 00:20:23,140 The next step in the workflow is it's going to do something with like eight now if it's not coming across at the fourth, 193 00:20:23,140 --> 00:20:31,270 like eight is just a linzer that's going to check that your Python code is up to certain standards in terms of how it's laid out. 194 00:20:31,270 --> 00:20:34,570 And it will also act in a way as a static analysis tool, 195 00:20:34,570 --> 00:20:41,110 and it will try and pick up some common errors that you might have in your package as well with running play dates. 196 00:20:41,110 --> 00:20:48,130 I'm just going to change this slightly because I want it to treat warnings as errors. 197 00:20:48,130 --> 00:20:53,520 I don't want to ignore these things I want, but if there are errors, I want to know about it. 198 00:20:53,520 --> 00:21:00,750 So this part is going to run flat out against my software and check that there are no problems with it as far as black AIDS is concerned. 199 00:21:00,750 --> 00:21:05,760 And then it says here test with blood test will actually I'm using unit test rather than test. 200 00:21:05,760 --> 00:21:17,760 So I'm just going to change this. And instead of I test, I'm going to do Python, Dash and unit test, and then I'll make up the base as well. 201 00:21:17,760 --> 00:21:25,320 So hopefully with any luck, that's all of the changes that I need to make and I can start to commit. 202 00:21:25,320 --> 00:21:39,460 So I'm going to add a new workflow. Christine, you commit that I'm actually I'm going to change this name to probably. 203 00:21:39,460 --> 00:21:46,280 And then. Three point five. 204 00:21:46,280 --> 00:21:51,690 The Python versions. Something like that. 205 00:21:51,690 --> 00:21:55,290 Steinmetz has a new workflow and then I'm going to commit this new file. 206 00:21:55,290 --> 00:22:00,080 This is going to commit straight to the master branch. 207 00:22:00,080 --> 00:22:05,510 This file now exists in the repository, and if you were to go to this repository now, you'd see that this file exists. 208 00:22:05,510 --> 00:22:10,430 Now the magic is if I click over onto the actions, you'll see that there is something happening. 209 00:22:10,430 --> 00:22:15,290 I can click on this. And I can see that now there are four bills happening, 210 00:22:15,290 --> 00:22:26,390 so what has just occurred is that gets her behind the scenes has spun up for virtual machines and each one of those is going to be running some stuff. 211 00:22:26,390 --> 00:22:32,730 And mostly what you're seeing here is the real failing, which is actually completely intended. 212 00:22:32,730 --> 00:22:40,740 So you can look into each of these. Runs and inspect exactly where each of them sailed. 213 00:22:40,740 --> 00:22:45,930 So just to recap, what's happened is a virtual machine is being spun up, running a boom to wait for. 214 00:22:45,930 --> 00:22:50,220 In this case, it has checked out my repository locally. 215 00:22:50,220 --> 00:22:56,610 It has set up a Python three point eight in this case, three point seventy six and five on the other ones. 216 00:22:56,610 --> 00:23:00,120 It has installed the dependencies necessary to my project. 217 00:23:00,120 --> 00:23:05,220 And then it's attempted to Linux with like eight, and it's decided that there's something it doesn't like. 218 00:23:05,220 --> 00:23:10,350 OK, so what has happened here? We look at this error. 219 00:23:10,350 --> 00:23:15,480 So here we're saying apparently there's something over indented on line 22. 220 00:23:15,480 --> 00:23:21,480 All functionality that pie. Okay. Well, I actually knew that that was because I deliberately did that. 221 00:23:21,480 --> 00:23:28,470 So that's the state would fail if I go into functionality that I and then look at Line twenty two. 222 00:23:28,470 --> 00:23:37,410 Oh, okay, yes, I see this written statement is actually indented twice rather than once, so I can save this change. 223 00:23:37,410 --> 00:23:41,310 I'll just go to my guess thing. 224 00:23:41,310 --> 00:23:50,890 I'll actually want to just start that change quickly. Will these latest changes the workflow that was committed directly to get up and just change? 225 00:23:50,890 --> 00:23:56,330 So if I create a committee here who speaks in dense. 226 00:23:56,330 --> 00:24:02,430 Commit that change and push it. Like, go back to the GitHub repository now. 227 00:24:02,430 --> 00:24:11,540 I've now hopefully fixed that. If I go back to the Actions tab, you'll see that it's picked up the fact that I've pushed a new commit to master it, 228 00:24:11,540 --> 00:24:17,480 spun up the floor virtual machines again. And now if I look into this build three point eight. 229 00:24:17,480 --> 00:24:22,580 With any luck, that particular area will no longer be apparent. 230 00:24:22,580 --> 00:24:29,790 So we'll we'll see. This is the benefit of doing it life. I don't know what this is going to work or not. 231 00:24:29,790 --> 00:24:36,400 Magic has. And I'm just going to wait four minutes for the other ones to finish. 232 00:24:36,400 --> 00:24:41,800 Oh, OK. We've got a failure on three point five. 233 00:24:41,800 --> 00:24:47,530 And because it's failed on three point five, three point six and seven will probably bail out partway through. 234 00:24:47,530 --> 00:24:54,460 So we'll see here that now this this links with vacates rather than produced no errors. 235 00:24:54,460 --> 00:25:02,580 The next step, which is actually running the unit tests that has in this case succeeded. 236 00:25:02,580 --> 00:25:07,930 But we have a failure on three point five, so let's go and investigate that links with Flight eight. 237 00:25:07,930 --> 00:25:15,360 OK. It says, OK, OK, this is interesting. So we've got a syntax error on line nine of functionality. 238 00:25:15,360 --> 00:25:19,260 Top pie. OK, so let's go back in and look at functionality. 239 00:25:19,260 --> 00:25:26,080 The Pie Line nine. Was it my mom? 240 00:25:26,080 --> 00:25:29,920 No, it was line 11. OK, I guess so. Line 11 has a syntax error, 241 00:25:29,920 --> 00:25:34,690 and this is now one of the first things that that's really useful about running this 242 00:25:34,690 --> 00:25:40,120 continuous integration in the cloud because I'm able to run on multiple Python versions. 243 00:25:40,120 --> 00:25:48,310 I get more information than if I was just running it on my laptop. If I down here in the terminal, check the Python version that I'm running. 244 00:25:48,310 --> 00:25:56,750 I'm running 3.8 because I'm on a new version of Open two, so I've got a really, really recent version of Python. 245 00:25:56,750 --> 00:26:04,460 I probably want if I'm disseminating my Python project widely, I'm going to want that to work for as many people as possible. 246 00:26:04,460 --> 00:26:08,570 That's why I want to check against Python three point five, six, seven and eight. 247 00:26:08,570 --> 00:26:13,070 And in this case, Python 3.5. It doesn't work on Python 3.5. 248 00:26:13,070 --> 00:26:16,640 And the reason it doesn't work on Python three point five is it's artificial. 249 00:26:16,640 --> 00:26:22,190 In this case, I'm using an f string, which if you're familiar with Python, you might know about. 250 00:26:22,190 --> 00:26:24,600 That was a feature introduced in Python three point six. 251 00:26:24,600 --> 00:26:31,250 So actually, I knew that this was going to fail on three point five, but I wanted to highlight the point that's allowing. 252 00:26:31,250 --> 00:26:38,360 You to run your code against every Python version that supported means that you can get as much 253 00:26:38,360 --> 00:26:44,750 information as as you can about whether it's going to work for the widest possible number of people. 254 00:26:44,750 --> 00:26:50,240 There are still going to be people out there using Python 3.5. So in this case, we could make two options. 255 00:26:50,240 --> 00:26:57,140 We could either just say, sorry, Python three point six and above only if we really want to use this feature, 256 00:26:57,140 --> 00:27:02,340 or alternatively, we can just change this to something else we could do. 257 00:27:02,340 --> 00:27:11,960 Hello plus name in this case. So for the purpose of getting this working on Python 3.5, I'm going to go ahead and make that change. 258 00:27:11,960 --> 00:27:16,280 So I'll create a new commits to make it work on Python. 259 00:27:16,280 --> 00:27:22,140 Three point five. Commit that and push it. 260 00:27:22,140 --> 00:27:28,100 And then if we go back. Two actions. 261 00:27:28,100 --> 00:27:32,330 Might just take a second. There we go. That's picked up this change again. 262 00:27:32,330 --> 00:27:40,590 It spun up its four different. Virtual machines, and with any luck this time this will pass. 263 00:27:40,590 --> 00:27:53,170 I'm going to have a look in on three point five. Just installing the dependencies. 264 00:27:53,170 --> 00:27:57,830 And in this case, great, it's now past. We've got green techs everywhere. 265 00:27:57,830 --> 00:28:04,930 Just waiting for three point six to finish off. And 3.6 as finished as well, great. 266 00:28:04,930 --> 00:28:11,920 So this is nice if I now go back to the actions I can see here. 267 00:28:11,920 --> 00:28:22,720 That we now have a green tick against this workflow. If I click on the something someone, I am sorry. 268 00:28:22,720 --> 00:28:29,620 Unfortunately, the the Zoom thing is in the way as well, which is slightly irritating, so I make it work on Python 3.5. 269 00:28:29,620 --> 00:28:36,190 I can now create this status badge. So if I create the status badge, it hasn't updated itself yet. 270 00:28:36,190 --> 00:28:37,390 It is now passing. 271 00:28:37,390 --> 00:28:51,690 But I can copy this markdown badge if I wanted to, and I could put that in the Read Me Dot, M.D. for this project, like an edit this file. 272 00:28:51,690 --> 00:29:03,030 At the top here, I can now put in this badge. I can probably see a preview here in my I.D., I've got this package Python package is passing. 273 00:29:03,030 --> 00:29:21,050 If I now just quickly alter this comment. It's unfortunate that go back now to my colleague Tamou GitHub repository. 274 00:29:21,050 --> 00:29:26,310 Now we can see in the. GitHub repository home page. 275 00:29:26,310 --> 00:29:34,110 Now that that status badge has has appeared now, in this case, what's happening, it will take it usually usually takes it a few minutes. 276 00:29:34,110 --> 00:29:37,230 GitHub does some some caching with with these patches, 277 00:29:37,230 --> 00:29:41,730 so it might just take it a few minutes for this to pick up the fact that it's changed to being a pass. 278 00:29:41,730 --> 00:29:46,590 But nonetheless, at some point in the next few minutes, I would expect this to turn into a green patch. 279 00:29:46,590 --> 00:29:52,310 And now, when people come to your GitHub repository, they're going to see that the build is passing well. 280 00:29:52,310 --> 00:29:54,390 At the moment, I'll say it's failing, but that's that's not true. 281 00:29:54,390 --> 00:30:02,670 They'll see that this build is passing, and that'll give them some confidence that that's that your software is being checked, which is good. 282 00:30:02,670 --> 00:30:09,830 OK, great. So now, as I said, that the the workflow file is just a. 283 00:30:09,830 --> 00:30:15,410 File that's committed to the repository, so if I go to GitHub slash workflows, there's Python versions. 284 00:30:15,410 --> 00:30:20,420 Doc Yamal is just now source code. In my project. 285 00:30:20,420 --> 00:30:25,400 I can do whatever I like. I can edit it from here and commit those changes, and that will just get pushed through. 286 00:30:25,400 --> 00:30:33,320 That's that's no problem at all. But what if I wanted to now test on multiple different operating system versions? 287 00:30:33,320 --> 00:30:40,280 Well, that's no problem at all. So let's just copy and paste this file and. 288 00:30:40,280 --> 00:30:47,270 Create a new YAML file called OS versions of operating system versions. 289 00:30:47,270 --> 00:30:53,570 And then instead of calling this Python package, I'll call this. When those. 290 00:30:53,570 --> 00:31:06,010 Mac, OS and Linux. Again, this is going to be run on pushes to master instead of runs on open to latest, I can use this matrix notation. 291 00:31:06,010 --> 00:31:08,310 I can change. 292 00:31:08,310 --> 00:31:20,610 Matrix Dot Python version two Matrix Dots OS and then change this Python version here to OS and GitHub actions allows us to run on Linux, 293 00:31:20,610 --> 00:31:31,950 Windows and Mac OS so I can change this now to happen to your latest Mac OS latest and Windows latest. 294 00:31:31,950 --> 00:31:33,030 There are other options as well. 295 00:31:33,030 --> 00:31:39,690 If you want to use a different version of an operating system, there are a small number of options that you can pick from. 296 00:31:39,690 --> 00:31:45,880 But now, instead of Python version, we can just do fixed by compression, so in this case, 297 00:31:45,880 --> 00:31:54,450 perhaps 3.8 the most recent and will change this as well to three point eight. 298 00:31:54,450 --> 00:32:01,260 So just to recap, this is exactly the same script as it was before we're going to run Flake eight and we're going to run the unit tests, 299 00:32:01,260 --> 00:32:12,000 but this time we're going to be running them on. Multiple different operating systems, and that's going to be picked up using this matrix notation. 300 00:32:12,000 --> 00:32:24,410 So I'll save this file. Go over and commit it. 301 00:32:24,410 --> 00:32:39,620 Push it. So if I go back now to the repository and look under the Actions tab, then it might just take it a second to pick up. 302 00:32:39,620 --> 00:32:47,290 We now see that we have multiple things happening on the left hand side, so if I look at workplace and multiple hours now. 303 00:32:47,290 --> 00:32:51,280 This is the one that still checking against multiple different Python versions, 304 00:32:51,280 --> 00:32:55,450 that's fine if I get on the other one, that's less active at the moment. I'm building on it. 305 00:32:55,450 --> 00:32:58,630 Buntu latest Mac OS latest Windows latest. 306 00:32:58,630 --> 00:33:03,430 And so if we have a look at, for instance, the Mac OS, which has just asked for some reason that was the quickest. 307 00:33:03,430 --> 00:33:13,510 It's sets up this job. And you can see and here we are on Mac OS 10.0 15.5 don't know anything about that. 308 00:33:13,510 --> 00:33:19,900 What version that that means it's running on, but it's created a virtual machine that's running Mac OS, 309 00:33:19,900 --> 00:33:28,090 and it's done all of the things says install the dependencies limited with like eight to run the unit tests and we've got a green tick. 310 00:33:28,090 --> 00:33:34,050 Great. And that's passed on everything, and that's probably one more thing still running on here. 311 00:33:34,050 --> 00:33:41,210 No, it's all passed now. So if I go back to the Actions tab, we can see that we have now got two parallel workflows, 312 00:33:41,210 --> 00:33:50,720 both passing one that's checking on every Python version and one that's checking on the three common operating systems that we might be interested in. 313 00:33:50,720 --> 00:33:55,760 I think now this might be a good time to just take a quick pause and ask if there are any 314 00:33:55,760 --> 00:34:02,900 questions about this kind of basic usage of GitHub actions to set up some continuous integration. 315 00:34:02,900 --> 00:34:06,890 Now we're going to move on to coverage checking now. 316 00:34:06,890 --> 00:34:18,270 What is coverage checking? Well, it's all very well that we can now automatically run the unit tests, but we want to have some way of determining. 317 00:34:18,270 --> 00:34:26,520 Whether that we've written are sufficient for the project that that that we're developing to take a really extreme example, 318 00:34:26,520 --> 00:34:32,490 if you've got a really old material project with thousands of lines of code. 319 00:34:32,490 --> 00:34:35,670 And you've only got three unit tests, then obviously, 320 00:34:35,670 --> 00:34:40,350 that's not going to be covering all of the software, all of the functionality that you've written. 321 00:34:40,350 --> 00:34:47,070 And the question is how can you in an automated way determine whether and to what 322 00:34:47,070 --> 00:34:53,920 extent your unit tests are sufficient for the code base that you've been developing? 323 00:34:53,920 --> 00:34:59,470 And coverage tracking is one of a number of ways to give you an insight into 324 00:34:59,470 --> 00:35:05,920 the amount of your project that is covered by the tests that you've written. 325 00:35:05,920 --> 00:35:11,110 And there are some third party tools out there to help with this. And what I'm going to attempt to do, 326 00:35:11,110 --> 00:35:15,940 and this will probably have to be the last kind of module in today's talk is attempts now to 327 00:35:15,940 --> 00:35:22,180 set up some automated coverage checking using a third party tool called Code Cards to Ohio. 328 00:35:22,180 --> 00:35:28,200 And if I go to code calls, that's why you hear. 329 00:35:28,200 --> 00:35:39,270 This is why I say I locked in, I've authenticated with my GitHub accounts and code couple of Io is free provided your repository is public. 330 00:35:39,270 --> 00:35:44,670 If your repositories private, then you would have to pay a small amount of money to access this functionality. 331 00:35:44,670 --> 00:35:53,610 But it's free for public repositories. So what I'm going to do now is as a repository. 332 00:35:53,610 --> 00:36:02,250 And the easiest way actually is I can just type in the URL, so this is going to be my domain. 333 00:36:02,250 --> 00:36:12,120 And what this has generated now is a. An upload token that I will need to integrate into my GitHub actions workflow 334 00:36:12,120 --> 00:36:17,830 to allow it to basically puts the coverage results into the correct place. 335 00:36:17,830 --> 00:36:21,040 So what I'm going to need to do is out this now, okay, 336 00:36:21,040 --> 00:36:27,610 this is a this is a talk for the purposes of getting getting you all up to speed with how to use GitHub actions. 337 00:36:27,610 --> 00:36:32,980 So I'm not super worried about security in this case. You can all write this down if you want to. 338 00:36:32,980 --> 00:36:40,450 It would be slightly annoying if you if you will use this to update errant results to you, to my credit card, but I can. 339 00:36:40,450 --> 00:36:47,140 I can always generate this token after the talk, so this won't be too much of a security vulnerability for now. 340 00:36:47,140 --> 00:36:53,830 But I thought it would be important to show you how to integrate this service with GitHub actions. 341 00:36:53,830 --> 00:37:01,490 So the first thing I'm going to do is copy this token. I'm going to go back to the. 342 00:37:01,490 --> 00:37:07,300 Repository and in the settings under secrets. 343 00:37:07,300 --> 00:37:21,440 I'm going to. At this. Token as a secret in my GitHub repository, and it's a secret with the name code called tokens, I'd already set this up so. 344 00:37:21,440 --> 00:37:25,140 So it already exists that normally you press this button new secret. 345 00:37:25,140 --> 00:37:35,310 So if that's the only thing we actually need to do to integrate code cards with continuous integration in this case, 346 00:37:35,310 --> 00:37:41,190 because it's a Python project, this is actually a relatively easy thing to get set up with the coverage checking. 347 00:37:41,190 --> 00:37:47,340 So I'm just going to show you now how to do that, going back to my idea in true Blue Peter fashion. 348 00:37:47,340 --> 00:37:57,900 Here's one I did earlier, so I'm just going to copy and paste my workflow from my my git folder, which was. 349 00:37:57,900 --> 00:38:01,870 In the run directory, home and workplace. OK. 350 00:38:01,870 --> 00:38:07,510 And I'll just give you a quick go over of what's in this file, it's relatively straightforward and in fact, 351 00:38:07,510 --> 00:38:11,890 it's less complicated than the other two because I'm not using a matrix. 352 00:38:11,890 --> 00:38:18,520 In this case, I'm using a fixed operating system open to latest and a fixed Python version three point eight. 353 00:38:18,520 --> 00:38:19,720 And the install dependencies. 354 00:38:19,720 --> 00:38:27,850 This looks exactly the same, except that I'm also installing two additional Python dependencies, one called coverage and one called code calls. 355 00:38:27,850 --> 00:38:37,680 So Code Code is a Python library developed by the website that we're going to be using to integrate this coverage information. 356 00:38:37,680 --> 00:38:41,190 And the difference here is that what I'm going to be doing is running coverage, 357 00:38:41,190 --> 00:38:50,940 so I'll get rid of that setting for now, and coverage is a an executable programme and I can cover its run. 358 00:38:50,940 --> 00:38:54,640 And then in this case, my unit tests. 359 00:38:54,640 --> 00:39:04,050 And what that coverage programme is going to do is keep statistics about which lines of code were hit by my unit tests. 360 00:39:04,050 --> 00:39:15,090 Then if that coverage was successful, I'm going to run code cards, which will upload those results to code cards, dot the website that we were on, 361 00:39:15,090 --> 00:39:24,330 and it's going to use this secret too, that I've just sat in the GitHub repository as the token to ensure that it gets to the right place. 362 00:39:24,330 --> 00:39:31,500 Now the nice thing about this setup is that because I'm using this code couple token, that's in the secrets. 363 00:39:31,500 --> 00:39:34,650 Anyone who's looking at this public GitHub repository. Remember, 364 00:39:34,650 --> 00:39:39,720 this is just a code file in the repository won't be able to see what this token is and therefore won't be able to 365 00:39:39,720 --> 00:39:47,220 abuse the fact that they could use that token to upload their own coverage results to your Code Cup instance. 366 00:39:47,220 --> 00:39:52,930 So that's all there is to it. I'm just going to commit to this and push it. 367 00:39:52,930 --> 00:40:03,600 So it's coverage checking, and I'm going to push that. 368 00:40:03,600 --> 00:40:09,580 And now, if we go back to the Actions tab. 369 00:40:09,580 --> 00:40:18,320 We'll see that coverage is now running. And can we can just keep an eye on this? 370 00:40:18,320 --> 00:40:30,540 It might just take a few moments to spin up the virtual machine and get going. 371 00:40:30,540 --> 00:40:35,530 There we go. So it appears to have worked. 372 00:40:35,530 --> 00:40:41,380 So it's run the coverage again, all we see is that the normal output from the unit tests. 373 00:40:41,380 --> 00:40:50,080 And then it's run code. It's detecting a lot of things that it's found the the XML files that it dumps out when running the coverage checking, 374 00:40:50,080 --> 00:40:53,200 and it's successfully uploaded it to code. Great. 375 00:40:53,200 --> 00:41:01,160 So now if we go back over to the dashboards on code calls and if I just refresh this or go back to the overview. 376 00:41:01,160 --> 00:41:05,370 Beginning. Refresh. 377 00:41:05,370 --> 00:41:12,270 OK, here we go. Great. So now we see coverage information and we see a graph here. 378 00:41:12,270 --> 00:41:18,450 OK, it's there's not much code in here. So this would be more informative if you had more source files with more stuff in it. 379 00:41:18,450 --> 00:41:24,120 And we can see down here functionality by clicking here. Now, we can see the coverage report. 380 00:41:24,120 --> 00:41:31,800 So here I can see that pretty much most of the lines were covered were hit exactly once. 381 00:41:31,800 --> 00:41:38,580 What does that mean? It means the unit tests were successfully hitting these lines of code once, but actually we've got one line that wasn't covered. 382 00:41:38,580 --> 00:41:45,150 Now this is something that you might not have noticed if you were just not checking the coverage, your files. 383 00:41:45,150 --> 00:41:51,000 But here this function is checking whether all of the arguments are actually numbers. 384 00:41:51,000 --> 00:41:55,350 If none of them are numbers, then it's just going to return. 385 00:41:55,350 --> 00:42:00,570 And then only after that is it actually going to go and do the bit of functionality that we thought. 386 00:42:00,570 --> 00:42:02,160 So if I were to change this now, 387 00:42:02,160 --> 00:42:12,520 I could add in another test and the source sponsor if they're going to test functionality in test minimum, I could add another. 388 00:42:12,520 --> 00:42:18,370 Asset like a desert is none. CIA demo dot minimum. 389 00:42:18,370 --> 00:42:23,260 That takes no arguments at all. That should hit this new line of code. 390 00:42:23,260 --> 00:42:36,430 So if I were to save this now, commit this change. That's not what I want. 391 00:42:36,430 --> 00:42:43,650 Stage that and so ABC's coverage. 392 00:42:43,650 --> 00:43:00,870 That's. And then whilst we're waiting for that to run the new job and hopefully update the code curve, we are running up towards 4:30. 393 00:43:00,870 --> 00:43:07,170 So what I'm going to say at this point is that there were a number of other things that I would have gone through if I had some time. 394 00:43:07,170 --> 00:43:14,310 But what I want you to know is that this repository is public on GitHub. 395 00:43:14,310 --> 00:43:17,750 So you know, there's going to be an opportunity in a moment to ask a few more questions. 396 00:43:17,750 --> 00:43:23,910 I'll happily stay around and answer as many of those as you like. But this repository is going to be public. 397 00:43:23,910 --> 00:43:25,320 It's not going anywhere. 398 00:43:25,320 --> 00:43:32,080 If you want to try this out on your own projects, which I really encourage you to do, getting set up in the first instance is the hard thing. 399 00:43:32,080 --> 00:43:36,030 Once you've got the system set up, it's really easy to keep it working. 400 00:43:36,030 --> 00:43:42,150 If you have any questions about any of this or you're getting stuck on anything or you don't know how to do some particular thing. 401 00:43:42,150 --> 00:43:50,250 Please feel free to come along to this repository and just open a new issue and tell me what you, what you're trying to do and what you can't do. 402 00:43:50,250 --> 00:43:54,780 And I'll get a notification about that, and I'll hopefully be able to to answer those questions for you. 403 00:43:54,780 --> 00:44:03,000 So please feel free to open an issue on this any time after this talk, if you're trying to set something up and need a bit of a hand with it. 404 00:44:03,000 --> 00:44:09,980 I'd be very happy to go over anything with you. OK, so now let's see whether any of this has worked. 405 00:44:09,980 --> 00:44:16,560 Say it back to functional coverage, get back to see it move. 406 00:44:16,560 --> 00:44:20,520 OK, great, so now it looks as though it's slightly greener than it was before. 407 00:44:20,520 --> 00:44:26,970 I think if I go here, I can see that the coverage is now 100 percent like back into functionality. 408 00:44:26,970 --> 00:44:33,870 I can see that this line here that was previously not being hit is now being hit. 409 00:44:33,870 --> 00:44:39,750 And with that, unfortunately, there were more things that I would have loved to have gone over, but we've run out of time. 410 00:44:39,750 --> 00:44:47,210 So with that, I'm just going to finish there and take any questions.