Iterative processes that include writing test code and production code together, such as TDD, help make coding fun. Gio Lodi, author of TDD in Swift, joins the show to discuss Test Driven Development, software workflows, bottom up vs top down, rapid feedback, developer vs customer facing tests, and more.
This transcript starts as an auto generated transcript.
PRs welcome if you want to help fix any errors.
00:00:01 Iterative processes that include writing test code and production code together, such as TDD, help make coding fun. All of us that care about developing quality code with the help of testing can learn from each other, of course, regardless of the programming language. Today we step outside of our normal Python comfort zone and talk with Gio about TDD in Swift. Thanks, Geo, for this great interview and thank you, Datadog, for sponsoring this episode.
00:00:41 Welcome to Test and Code. Am super excited today on Test and Code to have Gio on the show short for Giovanni, which is a cool name. And Gio. You’re in Australia, right?
00:01:02 Hey, Brian, thank you for having me. Yes, in Australia, it’s currently 02:00 p.m. Here. So I need to say thank you for taking the time. It’s late in the evening in your time zone, so. Yeah, thank you for having me.
00:01:16 Oh, you bet. It’s my pleasure. So you’re writing a book on TDD, right?
00:01:21 Yeah, correct.
00:01:22 I’m writing a book on test driven development in Swift. There’s actually the title of the book, Test Driven Development in Swift is going to be published at the end of June unless something breaks in the pipeline.
00:01:38 Very excited.
00:01:40 That’s just right around the corner.
00:01:42 Yeah. Sweet.
00:01:43 Congratulations. Is this your first book?
00:01:46 It is, yeah.
00:01:48 Were you a blogger? Did you write on the side before?
00:01:51 Yeah. So the publisher, Apress, contacted me because they discovered my work through my blog.
00:02:03 I’ve been blogging about testing and test driven development for iOS developers since 2015, more or less.
00:02:14 Before having children, I was able to keep up a pretty regular weekly schedule.
00:02:21 Kids arrive and they mix up your life for the better. But, yeah, I haven’t been really on the spot on the weekly post release string for a while.
00:02:31 Weekly. That’s a good goal, actually, before we get into testing too much, I don’t know much about Swift.
00:02:38 So Swift is a programming language that Apple developed and introduced, if memory serves me right, 2014.
00:02:48 So it’s relatively new, as programming languages go. But it has been introduced by Apple and they already had this massive user base of developers. So it had a very fast adoption and it was designed to replace Objective C, which is the language in which we were developing applications before.
00:03:18 And it’s a lovely programming language. I really like it.
00:03:26 It picks up the best bits of many others.
00:03:30 And I guess you often have guests on the show to talk about Python.
00:03:42 I’m very green in Python, but my understanding is that Python is a dynamic language that is interpreted. Is that correct?
00:03:49 It’s kind of both interpreted and compiled, but it’s compiled to bytecode at runtime, so you can think of it as an interpreted language, not too far off. Yeah.
00:04:00 And Python as a dynamic type system. Right. Like if I write something, I don’t need to say, this is going to be a string.
00:04:11 You don’t have to declare your types ahead of time.
00:04:15 A big difference in Swift is that it has a strong type system, so the code needs to know what the compiler needs to know the type of everything.
00:04:28 And that’s pretty cool. It adds a bit of override how fast you can write code. But I feel like you get a lot of benefits from having the types.
00:04:39 So I’m familiar with C and C as well. I don’t know if you are familiar with either of those back in the uni days.
00:04:49 Too rusty to say something.
00:04:52 But does Swift feel like a C like language?
00:05:05 Is Swift completely different and more like a.
00:05:24 Yeah, but you mentioned in some of the emails that we’ve exchanged that I’m a complete newbie in Swift, like newbie and that I have not touched it at all.
00:05:39 But it is a compiled thing, though, right? It’s not an interpreted language.
00:05:44 Yeah, it has a compiler, and I feel like it’s a superpower because the compiler is like when you do pay programming and so you’re driving and writing the code and your pet is next to you asking questions and helping you out. And that’s the same thing with the compiler.
00:06:07 It always picks up all sorts of error that you might be making.
00:06:13 This function returns a string, but you’re asking your treaty needs like an array, that kind of stuff. It removes all of them.
00:06:23 Okay. But it does that bit of a compiler. I’m curious about the workflow stuff. So we do want to jump into TDD, actually, let’s just start with TDD, clearly.
00:06:36 Well, I assume you’re a practitioner of test driven development, since you’re writing a book about it.
00:06:41 I am.
00:06:43 I feel naked when I work in a code base without tests, and even in a code base that doesn’t have testing, I try to add tests for the code that I introduced. Yeah, definitely.
00:06:59 Yeah. But a lot of test driven development tutorials have this quick feedback cycle. Introducing a compiler in the middle of it does throw a wrench in things a little bit, right?
00:07:17 You’re also saying it’s an iOS thing. Okay, so I read some Swift code for, like, maybe something that’s going to eventually live on a phone or something.
00:07:27 Do I have to run it on the phone or can I run it on my computer?
00:07:31 All right, yeah.
00:07:32 So Swift is a language that can be used for many different things.
00:07:39 It runs on Linux as well.
00:07:44 You can use it on Linux and Macass. You can write a script in Sift and run it with the Sift tool chain. So you can do many things. But definitely it is mostly used to build iOS and Mac OS applications.
00:08:02 There’s a few frameworks for Swift in the server, and thanks to hosting providers like IBM, you can deploy your back end returning Swift for the server.
00:08:15 It’s pretty neat. I don’t know of any company that uses it, but I’m sure there are some.
00:08:25 Like even if your code is targeting a mobile device, if you can run it on your computer, then you can run tests on it on your computer.
00:08:34 Yeah, absolutely.
00:08:38 The main way to write Swift code would be through Xcode, the ID that Apple provides. There are other, but definitely you need to jump a few Hoops to configure them. Or maybe you want to use the JetBrains ID. The name is Casey Upcode. I think that’s the name. Okay.
00:09:00 Anyway, let’s assume that you’re using the standard tool chain and you’re using Xcode.
00:09:05 And yeah, you can run the app and your test through the simulator. Apple spins up a simulator and they add a Chrome around it so it looks like a phone and you have very accurate experience of how it would be on the phone.
00:09:28 Have you ever wondered what your code is spending time on, how much CPU or memory it consumes, and how you can optimize it? With Data Dog APM and continuous profiler, you can investigate every service and individual request in testing and in production all the time, and visualize bottlenecks with the Data Dog flame graph, gain code level insights on CPU utilization, memory allocation, lock contention, garbage collection, and more. To optimize your code, reduce latency, improve your user experience and save on cloud costs, visit Test And Code. Comdatog to start a free trial and get a free Data Dog T shirt.
00:10:13 So that’s Swift and compiling.
00:10:17 How does Test driven Development work in this? And what is test driven development?
00:10:21 Okay, yeah, I’ll answer this question the long way around.
00:10:29 We have testing, right? So we write code and we write our functions, our programs, and then we want to know if they work properly. And a way is to just launch them, run them in whatever environment they are, and go through the user flow that would trigger a certain behavior.
00:10:50 This is certainly a way to verify the behavior, but it takes time.
00:11:00 It’s also victim of all the flaws of our mind. We can forget something, we can miss something. So an alternative way to verify the behavior, our code is to write test.
00:11:14 And so we are using code to test other code, then the problem I see with writing the test after the code has been written is sometimes we don’t write code with the test in mind. So it might be a bit hard to write a test with this code because we didn’t design it from that point of view. And anyway, if we see the test pass, we only know that we’ve seen the success in the test. We’re not sure that it’s going to catch an issue in the code. So to be 100% sure, I’m usually paranoid about my code. One would have to go back and introduce a bug in the code on purpose, like command something change true to a false, that sort of stuff. To see the test fail.
00:12:04 Test Driven Development spins this around and say, okay, first I’m going to write my test, which is for the code that I haven’t written yet. So the test is going to fail in some way because it lacks the real implementation.
00:12:19 And then this already shows me that the status is somehow accurate because it shows a failure. If the code doesn’t work and the code doesn’t work because they haven’t written it yet, then the next step is do the smallest bit of implementation that comes to mind to make the test pass.
00:12:41 Once you see the test pass, you can start a quick loop of changes. So I make a little change and run the test again. And if the test is still green, then I know that my change was correct and this would be the refactor step in the TDD workflow, which would be red, green, refactor.
00:13:07 So yeah, this is test driven development in a nutshell, I would say, and we can touch on that later. But this simple technique has a lot of benefits when applied consistently over time.
00:13:24 I think your question was about, well, I need to compile the code, I need to run it in the simulator. So doesn’t this slow down the feedback loop? Doesn’t it have a bit of extra steps?
00:13:39 Yes, it does, in the sense that if we compare to Ruby, I did some testing in Ruby in the past, and Ruby being an interpreted language, you can write a test and for a method that doesn’t exist yet. And the test is going to say, hey, I didn’t find this method. This is the error.
00:14:07 If you were to do that in Swift, you wouldn’t get a test error. You will get a compiler error. The compiler would tell you it would fail to compile the application.
00:14:19 And this is why I say that the compiler is part of the Test Driven Development feedback cycle, because it helps you find this kind of early issues.
00:14:36 Yeah. Okay, so let’s say you got to the point where you have a method you can call or how do you even call it then? So with the test framework in Swift, is the test compiled with your code? Is it part of it or is it an external thing and you have to have an API.
00:15:05 A few years after the introduction of Swift, Apple developed Swift packages, which are like self contained libraries.
00:15:19 It works a bit different for Swift packages, so I’m not going to touch on that. I’ll keep focusing on Xcode for the sake of the conversation. So in Excode for an iOS or a Mac OS application, you have the application target, which is where all the source code of the applies, and then you can create a new target, which is the test target. You can have two types of targets, the unit test target and the UI test target.
00:15:48 Okay, that’s handy.
00:15:54 The main difference between the two is that UI tests, they look at the application as a black box and they interact through it like a user would. So you cannot call instantiate classes or call methods of your code base. You can only tap the UI, interact with the UI and that is super handy. You can write high level tests with that that verify end to end user journeys. But to write that kind of test, you need to have all the implementation done already, so I don’t recommend it. I’ve never seen anyone using UI test for Test Driven Development because you would have to write a lot code before seeing a green test. And that is the opposite of what Test Driven Development pushes you to, which is moving in very small increments.
00:16:59 So this leads us with the UI test target.
00:17:03 And that is you write your test, you import the application target and you get access to all of this code. So you can instantiate any object, call any function, use any of the types in your code base in your application code base. And Apple provides this framework. It’s called Xitest usual X unit style test framework. So you create a test case class and every function that start with test is going to be the test runner is going to pick it up and run the code and if everything is fine it’s going to take it green, otherwise it’s going to report a failure.
00:17:55 Okay. And then I assume it’s got like set up and turned on procedures. You can yeah, it does both.
00:18:04 Before every test or before all of the tests. I can run once or I can run it before each of the tests. It is better way to say it.
00:18:19 Now, are you mostly targeting a lot of your testing around functional stuff like making sure a function that takes input and produces output?
00:18:35 Is that the type of testing you’re doing or are there state based testing that you’re working with or you kind of do both?
00:18:44 Good question. I would say I lean more towards the input output style test because those are the easiest tests to write. And regardless of Test Driven Development, once you start writing tests seriously, you soon discover that usually code that is easy to test is also easy to work with in the code base because the tests are nothing but another consumer of the API that your code exposes.
00:19:21 And something that I love about Test Driven Development is it puts this pressure on you as a developer to write code that is easy to test, hence easy to work with. Because as soon as you start like the set up for this test is taking a while to write, I need to instantiate this object and this object, then the light bulb turns on. Maybe this class that I want to test is doing too much. Or I thought I’m designing it with too many input parameters, something like that.
00:19:59 Definitely many times I’ve had a function that totally made sense when I was thinking about it, and I even wrote like, maybe a couple of tests that made sense at the time, but maybe there’s three or four parameters that go into the function.
00:20:17 And then I get into a situation where I’m trying to extend the test suite and I don’t know what to fill in for some of the parameters. So there’s some use cases that there’s nothing to go in there or I don’t know that information yet. I’ll learn it later. So it’s a way to test the API to make sure not necessarily a in the API big level, capital level APIs.
00:20:46 It’s just like the interface to a function or the interface to a class.
00:20:51 If you can’t use it as a test, then it’s not going to be fun to use later in development, right?
00:20:57 Yeah, exactly. And that goes back to the feedback cycle.
00:21:03 Feedback, as in information that comes back to you, the software writer, to give you some guidance on trying to find a word that is not feedback to describe this process gives you some input on the quality, the ergonomic, how your code works, both from a correctness point of view and also from how easy it is to consume to work with.
00:21:34 Yup. And even sometimes just a day, a day delay, one of those sleep on it sort of things. You can come back to code that totally made sense yesterday, come back to it the next day and you’re like, oh my God, these tests are ugly. I really hate this. I really got to change the interface.
00:21:50 Yeah, absolutely. It’s crazy what our mind does in the background.
00:21:58 Many times I go in, I go down a rabbit hole and I like Dongita from a chef 2 hours because I just keep coding and coding and coding. I want to fix this issue. And then either I have the self awareness to stop or more usually my kids need something, so I need to leave and then I come back with a relative refresh of mind and I find a solution immediately.
00:22:28 Yeah. And it’s like you’re kicking yourself. Like, oh my gosh, if I had just given up 2 hours earlier, I would have gotten 2 hours extra sleep and not have lost any work at all.
00:22:40 Yeah, so true.
00:22:44 This is what you said about it. I wouldn’t have lost hours of sleep and today I would feel fresh instead of tired. And so your productivity stays at a constant level instead of really being suffer from that stint of working through the night.
00:23:09 That is something that I find a common critique or question against test driven development that comes up is the fact that it takes longer to write code because you have to go back and forth and also you’re writing these test. So depending on the ratio at which you write test, again, source code, production code.
00:23:42 If the only thing that we were to measure was key tabs and line of code written, obviously writing tests on top of the code takes longer.
00:23:52 But the fact is, testing itself and in particular test driven development, they help you write code that is easier to work with. So in the long run, it’s going to be easier to maintain and to make changes to your code base.
00:24:17 In writing your code, it takes longer to finish writing that piece of code because you’re adding the test.
00:24:26 Don’t tell anybody.
00:24:29 Over time helps you move way faster because it’s easier to make changes.
00:24:38 Yeah, maybe I’m just doing it different, but it’s always faster. To me, it’s always been faster to write tests and code at the same time.
00:24:48 Now, I’ve never experienced that. It’s slower to write test and code at the same.
00:25:01 I tend to agree.
00:25:02 Again, as I said, if the only thing that you measure was the line of codes that it takes to make a certain feature happen, writing ten lines for just the source code or 20 lines for source code and test would take longer. But we are not just writing the lines of code for the source. Right. We are verifying that it works correctly. We are making the software fit with the rest of the application, working through the implementation as we go along. So, yeah, not being able to run automated test on the code really slows you down.
00:25:48 Most of the times that I add tests to new code bases is because I just can’t stop having to go through all the manual steps that I need to verify every little change that I make. And so I write an automated test, and that does for me.
00:26:06 There’s a lot of places I want to go before we wrap things up.
00:26:11 So you’ve written a book. You got the first draft done, but the official first draft. So did you just start at page one and write the whole thing without making any changes and then at the end turn it in?
00:26:27 Or did you rewrite some stuff?
00:26:31 I wish it was that easy.
00:26:33 It’s been very hard.
00:26:37 So there’s rewrite.
00:26:40 This might be the first drop you turned in, but you changed things.
00:26:44 Okay, now I understand what you mean. What I turned in is the final draft. It was the fourth rewrite, end to end rewrite of the book.
00:26:56 Right. So that’s what I’m getting. Is that’s what I really love about tests? Because I tell people that the most qualified person to write any bit of code is somebody that’s already written at once. So a test allows you to get it right once and then completely rewrite all of your code if you have to.
00:27:18 And the tests are there to make sure that you don’t miss something and you can get it done.
00:27:24 And that freedom to go into part of your code and then go, I don’t understand this function even though I wrote it three months ago. So I’m going to rewrite it and I’ve got the test to verify that I’m going to get it right. That is so liberating.
00:27:42 You can create code that you’re proud of.
00:27:45 Yeah. The word that you use liberating really resonates with me.
00:27:50 I find that the test driven development process in particular, because first you write a test, then you write the simplest code that comes to mind to make the test pass.
00:28:07 The couples detaches separates the job of getting the code right and then getting the code.
00:28:18 Nice. Getting the code to fit in the standard of the code base can back the creator. Or as he describes himself, the rediscoverer of test driven development has this quote which is make it work, make it right, make it fast.
00:28:39 And I think it really encapsulates this iteration based way of working that I feel test driven development really helps you to achieve in a structured way. But regardless, having test, having something that really quickly allows you to verify the quality of your changes enables you to iterate in this way.
00:29:09 So we’ve been talking mostly about test driven and I think around like developer level tests, like whether they’re functions themselves or classes or modules or packages.
00:29:23 From a developer’s perspective, there’s user perspective tests too of like, does this functionality work from the user’s perspective?
00:29:33 Do you have testing like that in your development workflow or does somebody else take care of that?
00:29:39 Okay, yeah, great question.
00:29:43 Well, I’ll give you some context of books. Writing one book on test driven development is not my full time job.
00:29:52 So by day I work as a mobile infrastructure engineer for Automatic.
00:30:01 Automatic is the company behind WordPress.com and other products in the WordPress ecosystem like WooCommerce. We also have a note taking application called Simple Note.
00:30:15 And as part of my job as a mobile infrastructure engineer, combined with my passion with testing, I helped different teams, the mobile teams that Automatic create code on a schedule. This is very buzzwordy way to describe my job, but getting practical. Recently we’ve been talking about with my team about your testing and automation, how to write this kind of user level test that makes sure that all the pieces are connected properly. Because what you get with test, even development with unit test, is high coverage of the units in isolation.
00:31:05 You can complement that with higher level, still automated unit kind of test that connect multiple units.
00:31:19 But that still isn’t the real user experience.
00:31:24 So for that we would use two kind of tests, UI test, which are the ones that we were talking about before spin up the app, has a black box and interact with it just through the UI.
00:31:42 And another type of test is called snapshot testing, where you load screens in the app or view components and the tooling takes a snapshot of it, and then there’s a diff with a prerecorded source of truth. And if the image doesn’t match, it generates a test error. And depending on the framework and the tools that you use, you can even see the actual diff. So I don’t know, something was supposed to be a circle, but it ended up being a square. And so you would see the intersection of the circle and the square in the diff and just, hey, this doesn’t match.
00:32:29 And those sorts of things are really great for like, we totally refactored one of the libraries, but we didn’t intend to change any of the behavior. So the user shouldn’t change any change.
00:32:42 Yeah, a lot of people use the word refactor when they really mean rewrite or like a changed generic change. But the actual meaning, original meaning at least of refactoring is changing the factor of the code. So how the code is implemented under the hood without changing its outside behavior.
00:33:17 And tests are great for that. I was speaking with someone recently and they were saying that they were planning a lot of work in the app and I was well, I would recommend investing in a few putting up a lightweight suite of UI test, depending on the industry in which you work with, like a user acceptance test, functional test acceptance test, some high level test that at least you have this safety net that you will know that you haven’t broken anything major end to end in your application.
00:33:54 Yeah. And you can target that. So like if somebody’s, for instance, I don’t know what kind of application like, let’s take a simple note, like the note taking thing, target. If you’re refactoring something that would affect maybe the recall of notes or something like that, then you can target the tests around that and then go and go ahead and do your refactor and then go back and run those and stuff. So, yeah, that’s a cool idea.
00:34:27 I feel very lucky after talking to you about this, because in my entire career, I have been working with test equipment, and all of it has a programmable API. So there is a user interface that’s visual but don’t have to test to it because everything is accessible through an API as well, so that’s indent tests don’t have to be graphical.
00:34:56 That’s pretty neat. What kind of test equipment do you work with?
00:35:03 So it’s communication test equipment.
00:35:06 Actually, I’ve done a lot of stuff, electronics over the years, but most of my career has been around communication test boxes.
00:35:16 So let’s say your cell phone or tablet or something. It’s talking to something over wireless. So it’s either WiFi or LTE or some other cellular standard.
00:35:32 So the box I work on tests, all of those things, all of the wireless standards. And then plus my focus right now is WiFi stuff. So some of the newer WiFi standards.
00:35:44 And is that how you got into testing and developed your expertise?
00:35:50 Yes, actually, I was reading in the 90s or early 2000s about extreme programming and lightweight models and lightweight methods and Pragmatic Programmer and Test Driven Development. And before Test Driven Development was called that, it was called Test First Programming and all of that. And that just sort of threw a light bulb in my brain to say, hey, I think we could do this for us.
00:36:28 And also the test equipment I’m using is compiled. It’s C plus. Plus, you would probably be like, hate the feedback cycle we’ve got. Compiling, Loading, and restarting the instrument so that the new code is up. Anyway, that’s super interesting since in the last ten years and stuff, I’ve been learning more Python. So there’s a lot of projects I do that are pure Python base too as well.
00:36:56 You were talking about Test Driven development, mostly from the smaller scale, and I take it from the upper scale. So I try to write the highest level test I can that gives me information as a developer. And it’s interesting to see both perspectives work.
00:37:22 Actually, I think they’re more in common than we probably let on. I probably end up writing more unit tests anyway, because there’s times where I jumped out. So let’s say I’ve got like the simple Note application example. I want to recall some stuff. So I want to make sure that that system works. There’s some way to call it through an API or something, let’s say, or at least like a package that I can say, hey, do the recall thing.
00:37:49 And if that test is enough, that’s great. But if I’ve got to test something that’s a little tighter, like algorithm bit, well, then I can jump in and write a test around that small algorithm.
00:38:01 That particular bit.
00:38:03 Yeah, I think it was Kent back. Maybe somebody else talked about it as running fast and slow so you can run as fast as you want with higher level tests. But when you start tripping, then you slow down and do finer grain tests.
00:38:20 Yeah, that’s a nice way to put it. Yeah.
00:38:22 Because I have to tell you, I hate the refactor part. I mean, I’m going to refactor anyway. But this idea of intentionally writing the wrong code and the wrong test, I’m impatient. So I’m going to attempt to write the right test and the right implementation at first, even though it’s going be wrong.
00:38:47 Kenback talks about it in his book Testament Development by Example, and I don’t recall the exact wording. He has a nice way to put it, but basically says obvious implementation. Maybe he’s mnemonic.
00:39:07 You should write the simplest one that comes to mind. If what you’re working on is straightforward, you shouldn’t go out of your way to make it incorrect or wrong or suboptimal just so that you can get a bit of feedback or that you can tick the box in your checklist of this is how you do test driven development. And I think that’s totally true. And this is the wording, the semantics matter, right? Is the simplest one that you come up with. And often a simple implementation is a correct one. It’s an elegant one in simplicity. So, yeah, just go with that.
00:39:56 Actually got to tell you, a lot of times when I do that, I’m doing that also. But I’m writing the most obvious solution that I can think of, even if there’s times where I’m like, okay, I’m just going to do the brute force method.
00:40:12 I’m just going to go and collect everything I need, do the algorithm and do the output. And then I write the test and I’m doing the test to save time, of course.
00:40:21 But then I look at it and I go to refactor it and I go, you know what? It’s actually pretty readable. And readability is what’s really important to me.
00:40:31 And then there’s other times where I try to refactor it to make it more elegant and it actually looks worse. It’s harder to follow. So I go back to the original in the first place, and I think that the writer the most obvious way. First, I think it was a trick that Kent put in the book to just try to get people to write obvious code more often.
00:40:58 Maybe you should get him on the show so he can give us the backstory.
00:41:03 That would be a great conversation.
00:41:05 He’s working on a new book, I think he has a newsletter on substance where he occasionally shares ideas that he is working on for the book in a very test driven fashion, I should say, because this way he gets feedback from his platform readers, audience on the ideas, whether they resonate or not. And eventually they will call us into a straightforward narrative in the book. But yeah, I’m subscribed and I’m always looking forward to want to see a new email from him.
00:41:44 Oh, we have the secret. Now I’ll have to try to find that link and stick it in the show notes. But hey, we unfortunately got to wrap things up. But I really enjoyed talking with you.
00:41:57 It was my pleasure, Brian. Thank you for having me.
00:41:59 So, again, if people want to try to find your book, what’s it called again?
00:42:04 Test driven development in Swift, I put up a little website for it is Tddinswift.com should be easy to find.
00:42:16 People can find more about me at Geo Codes, that’s G-I-O. Codes.
00:42:26 And there’s all the links to where I write and other GitHub and Twitter.
00:42:32 It’s all in there.
00:42:34 Well, thanks so much for taking the time to talk with me today, and I wish you luck on the finalizing of your book.
00:42:42 Thank you very much, Brian. Thank you.
00:42:50 Thanks, Geo. Great chat and good luck with the book. Thank you, Patreon. Supporters. Join them at Test And Code. Comsupport. Thank you Datadog for sponsoring get started with a free trial at Test And Code. Comdatog and Datadog will send you a free T shirt. Those links are in the show notes at testandcode.com. 158 that’s all for now. Go out and test something.