About this video
What You'll Learn
- Map BDD example-mapping outcomes into concrete Gherkin feature files for git-sync behavior.
- Define repository bootstrap rules around missing directories, conflicting paths, and incorrect local Git states with precise scenarios.
- Choose test boundaries between library-level acceptance coverage and two focused CLI happy-path checks.
Ciaran McNulty joins David to apply BDD to the git-sync Rust library. They turn example-mapping outcomes into Gherkin scenarios, refine wording, group rules, and decide between library-level and CLI end-to-end acceptance tests.
Jump to a chapter
- 1:15 Introduction and Sponsor
- 2:25 Context: Recap of Previous Session (Example Mapping)
- 4:49 The BDD Process: From Discovery to Formulation
- 5:55 Reviewing Example Mapping Outcomes (Miro Board)
- 11:24 Structuring BDD in Gherkin (Features, Rules, Scenarios)
- 12:41 Writing Scenarios: Initial Repository Cloning (No Local State)
- 14:49 Refining Scenario Wording and Detail Level
- 27:58 Writing Scenarios: Handling Non-Git Directory Conflicts
- 32:56 Writing Scenarios: Handling Existing Git Repositories (Multiple Cases)
- 53:10 Grouping Scenarios and Refining Rules
- 1:02:53 Determining Testing Strategy (Library vs CLI)
- 1:08:00 Identifying Scenarios for CLI End-to-End Tests
- 1:13:05 Why Test Core Logic at a Lower Level?
- 1:15:10 Demonstrating Unimplemented Scenarios
- 1:17:08 Planning Implementation Using BDD Workflow
- 1:18:54 The Role of Acceptance Tests
- 1:20:36 Conclusion and Next Steps
Full transcript
Generated from the English captions. Timestamps jump the player to that moment.
Read the full transcript
1:15 Introduction and Sponsor
1:15 Hello, and welcome to today's episode of Rawkode Live. I am your host, Rawkode. Before we begin, I just wanna take a quick moment to say thank you to Equinix Metals. They are my employer. They are a bare metal cloud, and they give me the time and resources to invest in the show and produce content that we can all learn from together. If you wanna check out Equinix Medal, please use this at Rawkode dash live coupon. This will get you $50 of compute. That is roughly one hundred hours on our smallest instance. Certainly enough for you to have some fun
1:48 and play with. Now today, I am joined by my friend, Kieran McNulty. Welcome back, Kieran. It's always a pleasure to have Hi, David. So I can hear you, though your video has frozen on you. Although, I think it's coming back. So you can you hear me okay? Yeah. Alright. Okay. I can. I'm just gonna prioritize my laptop, my network. Someone got Netflix on. Yes. Alright. I'll give a little bit of context just now while you get that sorted. This is it's turning into a bit of a series. We're taking a look at behavior driven development through
2:25 Context: Recap of Previous Session (Example Mapping)
2:33 multiple episodes and real world application. I have been building out or, you know, failing to build out, but being guided by Kieran, a get library called get sync, retina rust that aims to provide the backbone of get up stale operators or event driven applications. We kind of started by an example mapping session, which was roughly two weeks ago now. We used a middle board and in real time, we kinda tried to discuss the application, flesh out those requirements, loads of stackies to add colors, very nice guidance from keeping on how that all works. And then we could look very briefly at,
3:13 well, how do we store this in a get repository? How do we how do we use GERKIN to write scenarios and kinda give other people, not just my own understanding of the application, but share that with other people. And I think we wrote half a scenario, and then you told me to go in, do my homework, and and do more, and I didn't. And then we thought, well, why don't we just continue the series? Let's do this live. You know, it's always a pleasure to have your guidance because I really do. I'm really terrible at this. So
3:43 No. No. No. Yeah. So the thing we did last time was is broadly speaking in this area of discovery, deliberate discovery. So we sort of took time to I I didn't know anything and you knew a lot. And then maybe we added a bit during that conversation. And I think if we'd had more people, we'd have had more sort of insightful questions that that helped us flesh it out a bit. And we came out of that with a kind of shared understanding of what it should do, what we've decided that it should do. Yep. Because we don't wanna make it too, like,
4:21 spec y, too contract y. But, you know, we we'd have done that quite soon before we're gonna build it, and we kept all understanding what we just agreed. And I think what what we might find is because it's been two weeks, we'll have kind of forgotten the context. So I guess we're gonna look at the mirror board. We might not quite remember what some of it means, you know, because it's kind of scrappy notes. So the idea is that shortly after that, someone would capture that that conversation, and that's where the kind of second step of
4:49 The BDD Process: From Discovery to Formulation
4:57 so formulation comes in where someone you you're trying to slow the meeting down by capturing everything in the meeting. If you've ever tried to do that in a meeting, you know it's absolutely painful. Everyone stop talking while I type this. So you can avoid that, but then you try and sort of dump it out shortly after. And then share it with everyone and make sure you captured it right and maybe get some feedback so that that there's a few cycles inside that process before and and then you take that through to development. That's the kind of gist. So
5:29 I guess we're at that step of we're gonna try and capture what we talked about last time, write it down in a way that we think is gonna be clear. I remember you were one of the reasons you're doing this is to have documentation for people in the future. Yep. So capture it in a way where it's gonna be clear for those sort of future generations. Definitely. I don't want people to run this enough any surprises about what is is actually happening. So I guess we'll get up the middle board. Let's run through that briefly, and then
5:55 Reviewing Example Mapping Outcomes (Miro Board)
5:57 we'll start putting our scenarios together. We have our first comment as well from someone I think we both know, Mark. Hey, Mark. How's it going? Alright. Let's pop this up. Let's see. Because I am. A little bit. Yeah. So the to recap briefly what the structure is, we've got and I the blue thing is the most important things. They're business rule. They're things that have to be implemented somewhere in the system. So it's really important to understand where they are. They they kind of they do directly map to this the the code you're writing in a way.
6:34 Yeah. They're they're build they're like what is Oop. I lost you, mate. And he's gone. I'm still here. Alright. Yeah. You threw something for a second there. Oh, dear. Yes. The the the other things and when you're doing example use you sort of think of it as I'm not no. You're you're you're in and out, Kieran. Your video has has has given up, and your audio is Can hear me at all? Yep. I'm just gonna check my connection just in case. Oh, Mark, if you sent her in the comments, if you let me know if it's
7:40 just one of us or both of us. My connection looks pretty solid. I've got 500 meg. Alright. You've not frozen on me in the last thirty seconds, so we'll continue. What I might do is disconnect briefly and come back. Is that gonna break anything? No. No. No. You do that. I will I'll tell jokes. Yeah. Thanks for the comments, Mark and Wolfgang. I think it is just Kieran's connection. I'm not sure if there are too many Netflix sessions going on or it just needs Maybe it's the new m one Mac. Maybe the networking is not very good on it. Although
8:24 it we'll see. So this middle board then oh, it's back already. Let's see if that's any better. So the middle board, the blue stickies Our rules. Good save. Thanks. Our rules. And then the green cards were examples of things that we think happen within those rules. The yellow, I don't remember what that was, and the red was questions. Yeah. So the important I don't know how much you caught before I broke up. So the important thing is the business rules. They're gonna be implemented in the code. So all of this is so everyone understands the business rules in a in a way.
9:07 The other thing is called the feature in this context, but it's really just a way of grouping the rules together into something that we're gonna deliver as a block. So you could think of it as, like, which things which rules need to go together for it to be worth releasing it or saying or counting it as done. You know? So they might be the things that you have in your backlog if you're doing a sort of backlog driven development. You might think, one this first rule, repositories are cloned if not already. We wouldn't want that if we haven't implemented
9:39 the other rules as well. So the rules become a nice way to break down your chunk down your work. Mike Cohen has some acronym SPIDER without an e of of different ways of breaking down big or he says user stories because it's Mike Cohen. Breaking down user stories into smaller ones, and the r is rules. So are there some of the business tools we can implement first without the rest is a nice way of doing it. Okay. The others are other stuff. Spike path, identity and data. But like, one of the strategies for chunking stuff down is to break it up by
10:19 rules. It's nice if you can say, actually you could do these first. And actually, maybe some of the rules could be, this is going a bit deep. The rules can maybe relate to feature toggles. So say, maybe the rules could be feature toggled. But anyway, so Yeah. To say that we've done initial cloning of the repo and ticket is done on our list of to do, those three business rules are gonna be implemented. And the way we know they're implemented is for each rule, we came up with an example. At least one example. And in third case, we had three different
10:52 examples of ways it might work. Yep. So the examples there so that as a developer, I can sort of say I can I can read the example and it gives me a better understanding of the business rule? But also, you know, we on the third one, we need these three different cases to all be true. And naturally, that'll help us test it later. So it helps us understand the rule, and it helps us test the rule. But they're only really there for the rule to make sure the rule gets implemented. The end game is the rule is implemented by
11:22 the software. Okay. That makes sense. So we identified three features. The is there a semantic or heuristic that says that this is one feature fail or one scenario or multiple scenarios? Like, how how do we then translate this to to the language then? I'd put it in one feature file per feature Perfect. Sure. Initially. But if if if it's sort of so sometimes later in a project, you're working on something that's more like modifying the existing rules. You might instead edit an existing feature file. If that's So because the first step for us would be
11:24 Structuring BDD in Gherkin (Features, Rules, Scenarios)
12:02 then to work on our initial clone feature and then try to take these rules and examples and flash them out as full scenarios that we can then use for documentation and for testing. And if you're right if you're doing this first and for deciding what order you're gonna do things in. So it's to guide your own workflow. So I'm if if I'm working on this project, I would think which feature am I gonna work on next. Maybe it's this one. As I'm working through it, maybe I'll think, oh, okay. My first thing I need to
12:33 do is I need to implement repositories are cloned if not already. I'd get that going, you know, do that sort of test driven thing. Yep. But let's write the feature. We'll write a feature file and then see how it goes. Alright. So You know, there's this thing about writing tests first. It's popular with the kids. And not with me. I've never been very good with that. But I will I I will try to fix my my bad habits. So What what one of the points of BDD so so TDD exists, and people tend to apply TDD at a low
12:41 Writing Scenarios: Initial Repository Cloning (No Local State)
13:08 level when they're trying to work out an algorithm or something. One of the reasons for BDD is to sort of encourage applying that pattern at higher levels. This this higher level is of a feature. So let's let's design the feature first in a in an automatable way, and then we'll write the code, which is kind of TDD, but it's just sort of phrasing it differently to make it more likely that people do it. And this is what we wrote last time. Right? It is. Yes. So we we slightly reworked this is a good example. We slightly reworked some things from
13:45 the example map, and that's perfectly fine. If you were if you're in the session and you think of a better name, it's it's fine to, you know, editorialize a bit. It's kinda what you meant to be doing is clarifying. And then you would share this with well, you're sharing it with me now live. But you might you might do this writing down outside of your repository. You might do it in it's good to match the communication methods that people are happy with. So it could be a Google doc. It could be in a field on a
14:17 like, some field on a Jira ticket. Yep. It could be you paste it into Slack and say, what do you guys think? You sort of do it informally because you wanna you're expecting people to say in some places that's not really what we talked about or tweak it a bit. But let's do it the Git repo. So you've got the the feature title. You've got a bit of explanatory text that is just for readers. It's not for the computer. Yep. We've identified a rule. We've got one example. So what's the rule? If the directory doesn't
14:49 Refining Scenario Wording and Detail Level
14:49 exist, the repository can be cloned. So given I've got no local directory, when I sync a Git repository, then the Git repository is cloned. What do you think of that one? I'm not sure because I I don't even remember who wrote that, if it was you or me or a collaboration. To me, it makes sense. I mean, one of the things I struggle with when it comes to ratings scenarios is trying to understand the the subject. Like, you know, I think because yeah. I I I know there's, like I don't know if the rules are are guidelines,
15:28 but, you know, avoid avoid the term of the user and such. Yeah. And here we're using I. I mean, is that is that that the same? Yeah. It's fine. You could switch it to the passive voice if you want to. Okay. Given there is no local directory when the Git repository is synced. K. So, I mean, just try to There's two stylistic things. One is being eye centric, which some people really like. Being saying, you can also do a sort of third person thing where you say, when Bob syncs his Git repository. And then that's useful if you've got some
16:09 concept of, you know, different user personas or maybe different types of users, like you're trying to cater for people who are really familiar with the system, but also you want to think about, you know, James who is not tech savvy at all and has different challenges or people who are really familiar with it. So if you've done that kind of user scenario thing that usability people like to do sometimes, you know, returning users, new users, you could have names and, you know, flesh all that out. Some people do I because, again, it makes it feel a bit more immediate,
16:44 Whereas the passive voice like a plural, like, Kevin, we have no local directory when we sync. Yeah. I mean, There isn't a right or wrong. It's it's I'd match what I would try and do is match what people would how were people talking about it in the in the in the the session. So Okay. People in the session, were they saying, when I go here, I should be able to do this? Or were they saying, when when they, the customers, come to our site? I'll try and match that. It's probably the best. Okay. Let's stick with I for this afternoon's
17:21 session. We also have a quick question from Wolfgang who is asking rules and examples aren't still the same. Yeah. So this can happen when the you've only got one example. And that there's two type that one of one of the hard things when you're writing when you're writing a scenario is how much detail do I need to put in there. So using rules is quite important for this, to help this. It's one of the reasons that rules have been adopted quite a lot is one reason for adding specifics into a scenario is gonna be because it's relevant to the
18:02 rule. So what's the rule about? It's about directories and what directory existing or not means. Mhmm. So any detail that's about that can lead to some questions. Right? So what does directory existing mean? Could it what happens if sometimes it leads to questions. What happens if it exists but is owned by someone else? What happens if it exists with a different case? What happens Yeah. We never really get into a lot of we never really for me, because of my user permissions, but I can't create a directory with that name because there is one in the file system.
18:54 All of these might be technical things. But so so one reason is to explain the rule. I think we could put the name of the directory in there to make it clearer, to make it more like an example. Okay. It not be part of the Even I have no directory called something when I sync the yes. So, actually, that's a good question. In Git, what determines the name of the in your system? Is it always gonna use the name of the repository as the folder name? Not quite. Did we touch about that on the config?
19:37 No. I don't think we did. Think we spoke about it last time, but what we said was there there is the concept of configuring get synced to tell it, you know, where the cache directory is gonna be to store these repositories and stuff like that. But we'd never we what what I said was that functionality, I don't mind being just hard coded as sensible defaults for now and bring configuration later. So we haven't really said it's gonna clone to this. But, yeah, I think realistically, it's gonna be the name of the project. Okay. So let's put a let's give an
20:10 example of a project name that makes it so one reason is to make it explain the rule better. The other reason for extra detail is to make someone reading it understand the domain we're operating in a bit more. Project a okay? Or Yeah. You you want it to be you don't want to be too silly. Like, if you if you make it too abstract, if everything's foo and bar, it's harder to read and it's less real to people. They don't think about their real projects. The project a is fine. Yeah. Repository a b c, I think, makes more
20:45 sense than project because we're we're dealing with get here, not not something else. Yeah. And then so that's the context. The action is when I sync a GET repository, you could either say, what is the name of the GET repository? Or you could say a Git repository that would be cladding to repo a b c. If you want to sort of defer that config those config rules for somewhere else. It's something like that? Yeah. If you're happy for that, that's fine. Or should that be a should I just use a real repository rather than Yeah. Why
21:25 not? Like, I guess It makes it real, isn't it? It can clone itself. So, actually, let's just do that. That's an organization. Get When I click when I click on the get sync repository, we actually just clone ourselves as part of the test case. Into get sync output. So try and have the steps at a similar level of abstraction. We or I would say This is supposed be sync during the sync. Right? I mean, sync is Yeah. Then the repository is cloned. And I would say either, I would say, into git sync or I would say
22:04 that directory. Just depending on whether there's too many too much repetition. Let's do that. Where's the temp come from? I was just making that up. Alright. Okay. So we're just gonna You could put it in there, but I'd I'd put something like given my sync folder is temp. But we we don't have a sync folder yet. So yeah. We we we would just clone it to the current working directory. How do how do we use that as an example? The repository is cloned into What? The current working directory as, I think. Okay. So does that mean you should mention
22:47 the current working directory in the given? So given I am in in that end seems a bit funny, but and the slash temp directory, and I have what do I call get synced? Is that what you mean? Yeah. But now it feels a bit too detailed, doesn't it? Because the temp the the temp location isn't really relevant. K. So given Given I have no directory called git sync in the current working directory. So given I have no directory called git sync and Is it the current working directory? Would would a reasonable reader assume we're talking about the current working directory?
23:54 I don't know. We don't have a reasonable reader. A reasonable future person joining the project. I think we spoke about this last time as well where I I was trying to avoid bringing this up as long as possible, but it runs as a library and it runs as a command line application. And I was trying to keep the the for both? No. They kept the library version of it would require you to configure the the the clone directory. So let's take in that current let's take that current working directory concept out. Okay. It's not relevant to the rule,
24:30 and it's narrowing our options. You could have something like I don't suggest you change this, but you could have something like, given look at the background. Given the clone directory is configured to be, And then write everything with that included. But it's it's a bit of extra stuff. I think if I read this, if I've got no direct to call git sync, I'm kind of imagining there's a there's a folder. There's like a target folder. Is this something we would just, like, context to set up multiples features or scenarios and say, hey. We are assuming your code directory is
25:08 is set up as this. This feature isn't available yet, so it's hard for you to use slash tab. Like, could would we just add that as a better blurb somewhere? Yeah. I wouldn't bother. No. Okay. Because it's not about that rule. Like, maybe when we're writing this stuff about conf when we're talking about configuration and how syncs map to, which folder things get synced to, we probably will want to include all that detail. But for for the purpose of this, we we don't because all all we're really you know, what's the rule gonna be? It's
25:41 gonna be an if statement that that lists some files and then fails outright. So to understand this rule, I think we've got enough. Okay. So that means we just move on to rule two? Yeah. I mean, I don't wanna put words in your mind. Would would you do something else? Okay. So Is we're never gonna get to perfection as well, are we? And these are living documents. They're gonna change over time. Isn't that why you're here? As we implement things and as as we implement the tests, as we implement new features, we're gonna modify these.
26:18 It's, like, quite common I think that quite common that happens is, like, you don't mention the folder that this is all happening in like we've done. Right? And then later, you realize there is a rule that's really specific about which folder it's in, and you have to go and add add givens to the the other features. But you don't you don't you can't include all of the detail that's needed to execute it in every scenario. So you've got to pick and choose which bits are gonna be written here in the Gherkin and which bits are gonna be implementation
26:47 details of the test I'm gonna hard code in the test. And and the important thing is which bits do you think someone should read. Like, to automate it, we're gonna have to get the system into the state where it knows which folder it's syncing into and it knows what the what the direct it's able to list that directory and stuff like that. But is that gonna be in the test implementation, or is it gonna be visible to human readers? It depends whether it's useful for them to understand the rule. Alright. Okay. And it depends whether it's important
27:18 for them, yeah, for the rule to be validatable. So all of the detail that you need to understand the rule should be in the scenario. Okay. So the the bit that's slightly missing for me Uh-huh. But but it might not be missing for most people is in that in that previous one. Is it obvious that it is taking the last part of the folder name, and is that a standard git behavior? I think it's a standard git behavior, isn't it? It is. If you do a git clone x y z, it's gonna create an x
27:51 y z directory. I'm trying trying to do as much extensible get defaults as possible. And that's not a rule of our system, so let's not worry about it. Alright. So our second rule is if the target directory exists and is not a get repository, then we exit we enter and exit with non zero code. So the rule is if the target directory yeah. If the target directory says this is not a Git repository. Mhmm. Yeah. So there's a folder at that location that is not a git repository. Given I have a directory called git sync that is not
27:58 Writing Scenarios: Handling Non-Git Directory Conflicts
28:33 a git repository. K. Her example is this kind of the same one one map that you said that would happen that we have a a rule with a single example. So Yeah. I wonder if you can think of is there any situation where no. There's not a situation where it would sync into the folder anyway. Not if it's not a GET repository. Like, that's our like, we we don't wanna touch that. It's not managed by us. Let's just leave it. It's Scott. You you can move your not implemented tag up to the feature if you want
29:12 to just for So I'm a go I'll I'll just try and take this up, and then let's, I guess, review it and see. So I have a that right It's worth it. While while you're typing, it's worth mentioning that underneath the rule and underneath the example, you can put free text. So between the the rule and the example keyword and between example and given, you can put some paragraphs of explanatory stuff if it's useful. So, you know, you can flesh these things out quite a lot. Yeah. So what's the non CLI specific bit of that of the then?
29:53 If you're talking about the library Well, I was about to type then I crashed and I'm like, well What does the library do? It would return an header object or type. Alrighty. So then I then the repository should not be synced. It'll be cloned. Then it should be cloned. Makes sense? Yeah. And you could put so there's there's a user interface thing creeping in. You could put and an error reported or something like something generic like that. If it's, like, if it's important business if it's important to the business rule that an error is reported rather than the error
30:47 just being a nice thing to do for users. So the distinction there is, did someone who cares about the business say, we need and then we need to definitely know it didn't work. Or is that just a nice thing we're gonna do because we're nice to people and print out nice error messages? Yeah. I I I think what I want peep like, if I try to put on my I'm about to consume this library or CLI application as an external user, The most important for me to get back out of this file would just be that I know
31:19 that directory is not gonna be mutated, modified, blown away. Yeah. I don't know if that then covers that enough. That's a common mistake. Right? Is that so a feedback thing in in bad examples is, like, people would just put then I should get an error message. And they won't capture. The directory should have been cloned over. My data should have been preserved. They sort of missed the the actual side effects and they focus on the UI, is, like, getting that getting error message. So should I maybe be a bit more explicit here? And it's it's not that we
31:54 don't clone anything. It's that that existing directory is left untouched or something. Yeah. If you think that's important, I'd base it on understanding the business domain, whether that's an important part of the rule. Then? Like, it might be you've had a history of this application destroying your existing data, and everyone mentions it in every scenario that and all the data should be preserved. Because these are for people, it's always contextual with the audience. Yeah. So the important thing in the given is that the directory called GitSync, which is not a Git repository. So you can either put that in the
32:36 in one line or you can put, like, a new line in and. K. I put either it or git sync between and and is. And the final one then, it is a directory. Is a get repository. Multiple examples. So Mhmm. Let's see how we go on with this one. So as we now we're now we've got a few. If there's a step that is really similar to a previous step and it's just like a couple of words different, just use the wording from the original step or change the change the previous step Just for the automation. If the if the
32:56 Writing Scenarios: Handling Existing Git Repositories (Multiple Cases)
33:24 same thing said two ways and it means something slightly different, even if it's the same underlying step, I wouldn't there. You see what I mean? I don't know if that makes sense. Okay. But something is wrong. It doesn't match the remote. So something is not captured in our middle board. Mhmm. Okay. No. We do capture here. It's just our rule here is, like, if the directory is get doesn't match the remote dot colon, but then we actually have an example where we we did it at colon. So, like, the rule was probably just I don't know if it's a rule or
34:06 or what, but this is basically it's just saying that we have a directory and it's a Git repository, then there's a few things that can happen. Mhmm. A rule specifically is does that mean we got something wrong? The rule is don't clone it if it's But we do yeah. Like, oh, the origin points to the right URL, so we assume it's the right one and we start reconciling. Yeah. Often, if there's a rule, like, you can only do x if y, you'll have an example where you can do an example where you can't do. There'll be a happy and a sad. In
34:38 this case, we've got two sads and a happy. Okay. So what does that mean for a rule here? Because I I that means I probably shouldn't be saying that we don't call in in the rule. So as this isn't a rule anymore, is it? It is because there's an if at the start. So we don't if x, then we don't y. Right. Okay. You can still have an example where we do. You can rephrase it. I I this. Do not clone it. And then you still need the rule should be like an algorithm. So you put f at the start because
35:17 you're a developer. Uh-huh. Some people I think non developers often will put the thing first and then say if. Just match what someone said. So well, let's I I just wanna make sure I get it. I I don't know if I'm complaining about semantics. They're not really important. Right? But the rule here is if the target directory doesn't exist, and then we have an example of what happens. And then here, we probably shouldn't say there's errors. Instead, we should just send if the target directory exists and it's not a GET repository. And then down here, we're saying, okay. If it does
35:53 exist, then it has a GET repository. And then we have other examples. Yeah. But you don't have the rules. If the target directory exists and it's a Git repository, what's the rule? Well, that's what I was saying. Should. Here. There's there's no rule anymore. Yeah. It needs to be a rule. Okay. So as the target directory doesn't exist Exist, we can clone. Okay. Clone. Maybe a bit too example. Hang on. So what is the rule? Maybe we can collapse them a bit. Alright. I think I split them out in the example mapping. So that first one that first example is
36:48 the the sort of happy path, isn't it? The happiest path. Yeah. So if if if there's no local state, then we just we clone it, we're off. That's it. Reconciliation starts. There's nothing to worry about. So is that is that not in a rule? Is this just an example of this feature? Yeah. Maybe. Just take the rule out for a moment. Maybe someone in the chat can suggest what the rule is there. The rule is it okay. The rule is it clones it into the right place. But is that not just an example? Do do we need an explicit rule there?
37:29 I guess I'm back to this. Maybe this is the same kind of question that Wolfgang asked earlier. I'm not sure. When the rules and examples map directly like that. It should be not just to met the rule. And then when we have multiple examples, then maybe the rule can be enforced and we structure the the scenarios a little bit differently. Yeah. I've been trying recently not to omit the rule. I wonder if the rule is something for that first one, it's something like it gets cloned into the right place. It works. Like, oh, your software can work.
38:05 That mean, is that a real I don't know. If the if the if the repository has not been synced, we create a new folder. Not sure how I feel about that. Okay. Is it easy to put the examples for this, and then we'll group them into rules? Yeah. Let's do the examples and then see if we can and then see if our rules reflect what we had in our example. So so the first example, happy example is, here's what happens when you sync. The second example, I think these maybe these two are about if there's something else on disk
38:53 in a colliding folder name, we don't clone. Alright. Let's get the exam let's see the sample center, and then we'll try and we'll try and reverse engineer the rule. What we're seeing here is a local directory as the wrong get repository. So we have a dot get directory. It has an origin configured, but the URL does not align with what we were expecting. So we have Yeah. I like I like the example title you've given there because the detail is gonna be in the steps. But but we're illustrating a general case. Bet I got something right. So
39:35 we have a directory called git sync, and it is a git repository. And it has Use the word but there. So but is the same as and, but I think it reads better. No. No. The second one. But But it has an has a remote called origin that points to a different repository. Because we're gonna name the repository in the when step. Why don't you name the repository in this step? Why don't you give the explicit URL? And it points to parity. Yeah. Let's see. So just a different repository. I thought it was maybe to some other
40:31 name. I don't wanna cause any confusion. So Mhmm. Alright. So we've got our given and the but. And then when I sync the and then but let's just copy this. Oh, come on, computer. Repository, then the directory is left untouched, and nothing is going. Mhmm. Now they seem the same because they got the same outcome. So it's like there's something there that isn't a clone of the thing we're trying to clone. Alright. Let's get the other two, and then then we'll Alright. We'll we'll chase the we'll we'll try and pull that set a bit more.
41:25 So we've got the has origin wrong URL, has no origin. Right? So this is pretty much gonna be can you have a look and look at them by names per example, or would it be a new example? A new example. Even though the example title would be the same. Is that okay? Why is it the same? It's still the wrong get repository, or should we be more specific for sorry. Yeah. Just say it doesn't have a remote. It doesn't have an origin remote. Okay. There actually is a local local. Okay. Let's I'll fix this first. So we have
42:09 a the retro call gets sent as a git repository, but it has no remote call It did. Origin. Yep. So the example is local directory with raw with no origin remote. You don't have an Example title isn't mandatory, by the way. Alright. Okay. Would I keep calling this local directory or would I say local get repository has no like, does that make it more correct? The local GET repository has no remote Local clone, local checkout. Yeah. Local local clone. Yeah. That makes sense to me. Local clone has no remote And then local yes. This is clone in the one above.
43:01 Yeah. So local clone has incorrect remote for origin. And remote incorrect URL for origin. Yeah. Yeah. Okay. Yeah. That that So I think they grouped together now, don't they? So You wanna keep going. Let's keep going. Let's keep going. Well, the last one is that it works, the happy path. So do we I think you're right and that we've said, okay. These are very, very similar. This is the rule. It's a different happy path. It's a different happy path. Right? It's a happy path where there is a local checkout, and we're gonna skip. So it's a different outcome. Different context and
43:42 a different outcome. So local colon is the correct is has the correct origin remote. But given I'm just gonna Yeah. So maybe it's not a happy path. It's that with Okay. I'm gonna have this directory as a good repository, and it has remote. Hold on. Is it also completing from the other thing? With this being on the end, the Depending on your idea. Well, if you look at line 34, we've already phrased this a different way. Like, that structure is something we can use again to be consistent with how we Yeah. To change the repository.
44:41 Because I don't call origin points there. Yeah. You're right. So then when I sync those repository and You need to change the URL on on the built. Right. Thank you. Then it colon repository. No. No. No. It doesn't used up here. No. No. It doesn't. It doesn't come in repository. Don't tell me how my software works. Right? Okay. You're right. It then it reconciles. I don't know what that means yet. Okay. And the but in this one is an and because it's not it's not surprising. So I tend to use but when it's like, here's the thing that's gone wrong.
45:32 Yeah. Highlight. Is this this but? Now let's refactor. Does we do we need to say it's a Git repository if it has a remote for a reasonable reader? So for me Could we skip it? Maybe this is the mistake I'm making. But Zest to me is something I implement as a step and the codes test they say that says I need to create this I need to make this a Git repository. Yeah. Yeah. But you could always do it manually when you're setting up the origin, couldn't you? You know? K. So does that mean first we move
46:20 move So so decide on readability first. Local clone called get synced. That's the language we used earlier. That's nice, isn't it? Here. Have a local colon. Call get sync. It explained if it's the wrong one? A directory and a local colon. So Which makes it kinda makes sense. I I think kinda get I I I like local clone. I think that's in most of the examples that we have here. It makes sense to me. I know that it's a get repository. I know that I have an orange I have a remote, and I can inspect it. So yeah. I
47:04 think that language works well. So so just when we got to that last example, it's like and the system carries on to the next step to reconciliation. Right? Which which made me realize we haven't really captured in the previous ones that we bail out. Where we said nothing is is left untouched and nothing is cloned, we need to sort of say we stop. And and and the the clone fails or, you know, some what whatever you think sounds best that makes it clear that it doesn't then proceed to start reconciling that. I mean, we don't
47:48 do anything here except say it's cloned. We don't really mention. So Maybe maybe that's not important. Maybe it's just the director is left on top. Yeah. I feel like we need something that captures the fact that it's not an exception, is it? But if it's an error comes back or the CLI, you know, exits. Yeah. I mean, that's one of those weird system y things. I never know how to create a phrase when it comes to these scenarios. Well, I mean, do you have an idea? Are you trying to tease something out of me here or no? Okay.
48:30 Then And an error happened. And and and an error is something like that. Do it bad yeah. Keep puts me bad in. And And we'll fix it later. The clone fails? What's this bit called? Bootstrap? Yeah. There we go. Bootstrap. There is. I think it's it's header. Yep. Yeah. And then put that in the places that it's good to try and take stuff out. Take out the nothing is cloned. Then what's the then? Nothing is cloned, maybe. Bootstrap. Complete. What we're saying here is that there are two states of bootstrapping. Either we're gonna complete or we're gonna enter.
49:35 That, to me, is a very definitive, hey. I've got a some optional return type here. Yeah. Okay. So put that in the other happy path as well. Yeah. And on that last one, let's use the word already in there just for clarity. So scroll down again. Make you ping around. Here? And it already has a remote on on the yeah. There. Something like that. You know? But isn't that what we define with the I have a local clone. Not you know, unfair from that. Okay. Yeah. Put it in the example title then maybe. Already local clone already has the correct origin.
50:34 I I don't can you try and articulate the value of that already? It's over what we have. Yeah. If because no. Okay. Leave it out. I'm easy. So let's see if can put some rules in. It seems like there's a rule for the second and third the second and third ones. These ones. Yeah. The rule is if we have a local Like existing local clone has to have the correct the or isn't correct. Is that a rule? No. It's not a rule yet. Then header. Is a rule? Yeah. Or you could put it like, if
51:27 we have a local clone, the rim the remote has to be correct. Oh, okay. Yeah. If we have If you already have a local clone, then the remote has to be The origin remote must be correct. Yeah. Sounds good. Means that comes in. And now the indentation here, does that does should this example move above the rule? Does So once you start adding rules, the indentation doesn't matter. So if you want that to not be in the rule, you should move it up. But I think maybe it's in the rule. Okay. Yeah. This is all about local clones.
52:10 Yeah. And this is just the correct clone. You're right. Okay. And what so what was what are the rule less ones up top? No local directory and not a GET repository. So the rule is don't clone if don't clone if there's a clash with an existing non GET directory. Do we need a rule for the first two? You don't have to. They're just sort of useful sometimes because you got to if you think it's obvious, you you you you could maybe go on the side of leaving out the example title and putting the rule title in if you
52:51 wanted to make sure you already have the rule always have a rule. I think what is kinda making sense to me is the first two well, the first one's what I would expect to happen most of the time. The second one is a very explicit one rule, like, hey. That's a directory. It's not gonna be positive. There's no ifs and buts there. And then the third one, I feel it should have a rule because, yeah, they're they're different forks in that code path. Like, it's like, hey. We actually need to check a whole bunch of things for this
53:10 Grouping Scenarios and Refining Rules
53:19 rule to be true. So So so think about it this way. This think about two different types of rules. Some rules are constraints and things you're not allowed to do, and that's what we've got so far in our rule. It's like, you're not allowed to do. Here's here's something that would cause a problem. So we've got two examples of the problem and then the sort of happy version of how we resolve it. Mhmm. But there's another type of rule, which is like an enabling thing. What how is the thing actually operating? So that that first happy path, what are
53:47 the rules behind it? Is that we clone we'll clone the remote repository to local disk if we can. So we could write a rule like that. We could those two examples could go in a rule. It's like, well, part of the beach trapping is we clone the repository. What do we have in the mirror board? I had an idea there. I'll I'll go to the mirror board in a second. So if Yeah. Go on. As the what if we what's the words I'm looking for? I'm failing. As a rule to specific here, as a rule
54:30 that if something exists on the desk, we won't destroy it. Is that a rule that then captures this one too rather than this very specific rule about the remote being great? Yeah. Yeah. That's a good rule for us first two, is that we're gonna preserve any colliding folders. So as a rule, I'm gonna put Again, the the rules kind of the rules kind of the the things you call a business rule and the things you just write as part of the software depend on the the business priorities, don't they? So you're gonna write this whole system.
55:15 Is it a business priority that it doesn't clobber the local data? Maybe it is. You only really find that out in the real conversations with stakeholders. I think that's what what I'm thinking. Was like, the reason I want this documented is I I don't ever wanna be in a position where we just where someone runs us and we destroy something they have locally. Well, the rule is if there's a local directory, we're not we're not gonna touch it. We're just gonna leave it unless there it fits the criteria which we have here. Yeah. Maybe there's a Think of the rules
55:45 like the rules are kind of like acceptance criteria. These are the these are the things that if we implement them, the business is gonna be happy. Business is you in this case. But they're the things that will make the system correct if they're implemented. There's loads of other stuff. There'll be much smaller decisions we have to make about how it operates. But it's like the reason we're writing these in this document is these are the ones that are at they're at that business tech engagement level where non tech people have to be able to see what the system does.
56:18 Okay. We yeah. If if a local directory exists with the colliding name or, you know, we on the side of safety. Every local directory exists, we must confirm correct configuration or something. What what I heard you say was that it's really important to preserve the existing data. Preserve it and show an error. But we fail early. You know, one of these things. We don't proceed. Yeah. I think I think there's something there. I'm not really sure what, though. Let's put this side by side for a moment. So I think where my head is trying to
57:37 guide me here is that these can both be articulated as a single rule with these all being examples of how to proceed. And what the rule I'm trying to explain is, like, okay. If we have a local colliding directory and additional checks must be made before writing before it's taking control of the the the word the thing. So If you have a local existing directory, it must be a correct Git clone. It must already be but then I I I would probably try and break it out into more rules. I think your instinct is to collate more than mine
58:24 is. Right. Let I guess it's not not really that important. Like, guess that's just another thing I've got in my head. Right? These these these are 11 documents. These can change over time. In fact, the the title of this episode was 11 documentation with BDD. So, like, I don't need to get this right now. I just need to have a really good base understanding. And then as I actually start to write the code, I may start to I may start to pull out more of those phrases, rules, guidelines, and my understanding improves. Yeah. And I think the thing
59:01 we may be missing, if you scroll up a bit to the top of the feature Yep. Someone's reading about git repository bootstrapping. We maybe need to have a rule there, which is like, we clone it to the local disk on first bootstrap if this folder doesn't exist. Maybe that's the rule that's it captures the first. Like, there's some you you wanna write that down somewhere. We're actually we do we do a we do a git clone. Does that need to be said? I mean, the feature is I mean, we're calling a bootstrap, but the the feature is
59:44 we're gonna yeah. We're gonna interns joined. Your interns joined the company. So read these in order. This is the first thing they're reading. Wording is hard. The the only reason I'm pushing this in this direction is I want the symmetry of everything being in a rule, but it's okay if I do it. It's not really gonna affect anything. Because I have seen people, like, grappling for rules. Okay. So I would would on the side of having the having the stuff in the rule description and not having an example description. Hello? What's the thing we actually do? We claim
1:00:32 the thing. We claim the local we claim the local repository. No. I thought we were kind of in a position where if there's one rule and one example, then we'll met the rule and just go with the example. I I thought that was kind of the the heuristic we'd adhere to there. But then you were saying, well, you want them all to have a rule. But if the rule and the example are the same, should we not just have met the rule? I mean, that's just still a rule. It's just it's just codified as an example. That's
1:01:05 kinda where my Yes. And why not put the rule in? Because they're it's same. What is this rule for? Just so we've got everything on the rule level, because the rules are rules are the important thing. We're going down the rabbit hole. Let's stop let's stop. Okay. So we've got I'm happy I'm really happy with this. I think this Yeah. Explains our bootstrapping process where we either you start in with a clean stateless directory and we start to clone the get the things we take under management of get sync and so the directory. And there are rules
1:01:41 as existing state exists of how we can bring that under get sync management. And we've codified that we need a more code origin. It has to point to the right directory. Otherwise, we wanna exit the bootstrap. Like, to me, that is that seems pretty complete in my Mhmm. Yeah. For that bootstrapping. The question is, like, what would happen next? The reconciliation. But this is a deliverable. Right? When you when you bootstrap a thing, you've got a lot you've you're guaranteed to either have an error message. Yeah. I have a correct term. Yeah. I mean, I I that's well, actually,
1:02:19 I think that's actually retroactively describes the existing behavior. Yeah. You know, we do have Rust code here that calls our repository. You know, there's some authentication I'm gonna omit for now. But it does try to open it, so it checks if it exists, and it checks the remote URL, which is hard coded to look for the origin. You know? This what Rawkode does right now. Go back to the feature for a minute. There's something we can talk about. So you would we talked a bit last time about what what level of the system you'd test this at.
1:02:53 Determining Testing Strategy (Library vs CLI)
1:03:02 Okay. And you've kinda got a three level system that simplify it. You've got Git provided by someone else. You've got your library, and you've got a command line application. And I think we said last time, you wouldn't try and basically, the way you choose to test it, the the the the testing setup you you try for your automation is going to constrain where the rule gets implemented. It's one of reasons I like rules in there. So what's the one rule we've got? Can you put it make it visible? Scroll up. But yeah. If you have a local clone, the origin
1:03:48 remote must be correct. Now some of these examples might be implemented in Git itself already. Your your Git library might error when we try and do some of these things. Mhmm. Like, if it already has an origin, you're trying to clone into it, it might say, what the hell are you doing? So if we test your library and get together, some of it might be implemented already by get, and some of it might be implemented by your library and sort of pre checks. And you're kind of if you're kind of fine either way, then a good place to test this is
1:04:27 at the library level. Right? Yep. Because that means you're you're not opening yourself up to the possibility that the rule is implemented in the CLI application. You guarantee it's either in your library or it's a need to get thing that you're catching and handling nicely. Yeah. I think that's where I want most of my testing to happen, not on the CLI itself. The CLI is really just a wrapper around the library functions. So definitely. Yeah. So so just to pause on that conversation for a second. The bit we've just done, we would then share it with the people we've talked to,
1:05:01 get feedback, massage it. Now we're at, like, architecture day. We're gonna build it now, And we're talking about where we're gonna test it. So this stuff about the origin already existing, we don't care. The way we're designing the tests, we don't care if your library reads the origins, checks it's right, or if your library just tries to do the action and catches an error from Git, we're fine either way. Yeah? Mhmm. So that gives you some freedom to to to do it. But we'll know for sure that the we're not relying on the CLI implementing the
1:05:40 rule. It's it's implemented to the library. That's pretty that's pretty strong. So I think we should automate all of these tests at the library level. Mhmm. And with git real git. And then we'll have to see how slow Flake is. So it's using lib git. It just it doesn't shell out to, like, the git executable. Mhmm. But the get executable is just a wrapper around lub get anyway. So it's at it should be relatively fast provided I mean, it is actually going to clone these repositories. So Yes. And you might so you might need to look at that and
1:06:20 then say, maybe I should change it to local git repositories on the same box if if the network speeds are slow. So I'd look at that as you go. Yeah. Now in another situation, if you maybe had a web app, right, where it has a logic layer and some database I mentioned this because the because of the audience. That's a different situation because in that situation, you might not be happy if the stuff is implemented in the database. You may be, but you might not be happy if if the key business rules are implemented as database
1:06:54 constraints or triggers because there's this feeling in future you might use a different database. Like, I don't wanna move from Oracle to Mongo and then realize all my business rules are in the Oracle. Yeah. I I want to to know they're in that layer. So in that case, you would deliberately test it without the real infrastructure as the first test. The first rigorous test, you test it with a fake database. Mhmm. And then you would know that all the rules are implemented in your your core business layer. Whereas you're happy with this being very tied
1:07:27 to Git. Right? Yes. I am very happy with it being tied to git. I think I have say Otherwise, we'd have for the next five years. Yeah. There'd be some, like, abstraction layer of VCS interface, you know. Yeah. I mean, I could call it commit sync and, like, abstract abstract that a way to work with CVS or an SVN for Mercury or whatever. But, really, I'm quite happy to tie this into kit. So So the only concern you've got you need to worry about is performance. So that's the only place we might cheat some things.
1:07:55 So I would test all of these at the library level. Now the the first question I have is, if all of these are validated already at the library level, which ones would you then need to rerun through the CLI to be happy the CLI works? Let's look at them from the top and see. Let's imagine they're all validated in the library already. Uh-huh. So that first one, what would we be testing if we then also tested it through the CLI? Nothing? Well, you're still testing something. You're testing the CLI calls the right function on the library.
1:08:00 Identifying Scenarios for CLI End-to-End Tests
1:08:40 That's all you test testing. Right? That's all you'd be validating is, like, your CLI does in it does the right command to the library. Yeah. I guess. So so that might be one we want to test. So you could put a tag on that one saying we wanna test this happy path through the CLI. Yeah. We can you can you can be a bit agnostic and say, like, super important that UI because it then if you want web interface as well, maybe we test this one through the web interface as well. True. I do plan on compiling this to
1:09:18 WASM and running it in a browser. So Yeah. So that so that would that would test the the button on the web page. When I click it, it calls the right thing in the library. Okay. So by adding this to the list of things we're gonna verify through the full stack, we're getting a bit of confidence about that. And the second one, what what's the interaction between the CLI and the library here? It's the same command. And then I don't think I follow. Okay. So I'm talking specifically the boundary between your CLI layer and your library layer. What's what's the
1:10:00 interaction? And I want us to cover enough tests that we validated all the different interactions without too much duplication. Okay. So the So the only difference have we talked about what what what changes between running get sync of the CLI application rather than consuming it as a library in your own code, really, I think the only thing that we would need to test is that the CLI is gonna provide configuration. Yeah. But it's not part of this feature. Yeah. Like, I don't think there's anything the CLI, in this case, in the simplest form is just gonna be a mapping to
1:10:38 library functions. It's not really gonna do anything else. Yeah. It's just like control a remote control for the library. Right? Yeah. Exactly. So all we need to look, which is really common, the UI layer is just gonna send some commands to the back end and look inspect some return values or handle some errors. So in that first one, we're checking that it sends the right command, tells the library to do something. And we're kind of checking that it's well, we're not checking yet, but we're assuming it's looking at the return value that says, yes. I've done it. Yep. So in the
1:11:12 second one, local directory is in the Git repository. It's the same command, but in this case, there's an error. So maybe you wanna check that as well. The CLI handles errors that come from the library Okay. And exits with a non zero exit code. Right? Yep. Are there any exam are there any examples that do anything different? No. They're they are all checking that return value as a library, really. Yeah. But would I check as features CLI instead? You know, because we don't need to test those other ones with the CLI. So I think from what you've said, if
1:11:52 those first two run correctly through the CLI, I believe the others will all behave correctly. Gotcha. Okay. Given that we've given we've run them all given we valid if we validated them all at the library, we only need to test those two through the CLI. And this is a really important pattern because it's the thing in the web world, you know, this is where people test every scenario through the web interface. But really, all the web interface does is it calls one service and it shows the value that comes back on the screen. So this kind of thinking about what what's
1:12:29 different in each case really helps us narrow down the end to end tests. So by tagging these these two CLI, I'm confirming that CI knows how to handle a successful bootstrap and an error bootstrap. Like, those calling those two functions and handling the return types. And that's that's kinda what I want the confidence with that tag. Right? If I understand it right. Yeah. Yeah. And there isn't anything else that it does. All the other scenarios where it's called it tells it to clone something, and it either gets an error message or a success message back.
1:12:55 So running those through CLI tests aren't gonna be useful. So in your Okay. Yeah? Yeah. It makes sense. I was I was kinda really confused and lost when you were talking about the CLI tag, and I didn't know where we were going and then It's not a magic tag or anything. It's just something you've you've come up with. Right? It was just that one that where you said, no. We don't need to test those and that's why. I realized, oh, like, the way that we test the mapping works is by packing one successful one error and we
1:13:05 Why Test Core Logic at a Lower Level?
1:13:25 know that it's been handled. That that that completely makes sense to me now. I got it. Yeah. Good. Because because an alternative would be to test everything for CLI, not test everything for the library. That would give you confidence that the library works. Mhmm. It you slightly lose some confidence that maybe some of this stuff is implemented in the CLI. Now because your CLI layer is quite thin, that's maybe not a concern for you, but you can sort of imagine in in a more complex app or in a website, people might put all the logic in their
1:13:58 controller layer or they might put all the logic in the JavaScript. So this the practice of testing a lower level first really comprehensively at your kind of application interface layer, application service layer, it is really valuable because it it guarantees to you that your core model implements the business rules. And that's bulletproof then for for any you know, if you write a web UI that doesn't actually hand handle the error messages that come back, that's fine. It won't be a good user experience, but the kind of Yeah. The the directory will have been left untouched.
1:14:37 So that kind of thinking about where to where to apply tests really helps constrain your architecture. Yeah. Makes a lot of So you would run Cucumber once with a world where everything's going through the library. That will work. I've used this Rust one. Sorry. And then you'd run it again with a different set of automation with the at just running the ones that are tagged at CLI. I just wanna I'm gonna see if I can just get this to run enough so that it tells me it's not implemented. I did try to implement some of these
1:15:10 Demonstrating Unimplemented Scenarios
1:15:15 tests, and I'm just gonna Yeah. Comment them all out for now. So world is the shared state between scenarios? Yes. So the the this library has I mean, I could have called that in if I wanted, but that's yeah. It's called world, and then we can configure a new world with an empty state, and then we define the steps using power matching and then attach that to functions. So I'll comment all over for now, and we should just see, I guess, a list of scenarios unimplemented. The the Rust library actually seems really, really good, actually. I've been quite impressed as I've
1:15:56 been thinking with it. The the thing a lot of cucumbers are missing is this is a way of running the same features at different levels of automation as part of one execution. So has that and has for a while. But and there's some talk of bringing it to the rest of Cucumber, but what you tend to have to do is explicitly run Cucumber twice with different config files, different configurations, which is alright because you've got the kind of fast in memory stuff and slower end to end stuff. Oh. Yeah. I think my look at to
1:16:38 that's another problem with dynamically linking. But Let's see if that I mean, this add the reinstall flag to that. Yeah. Try it one more time. And I think so if we were to say, like yeah. I'll need to fix that. I'll maybe stick in a container from just remove remove this weird host stuff completely. So my next steps then would be to implement well, I've already got the feature. So to connect up the testing for this to make sure it behaves the way that we want, and then we would come back and we would write the scenarios
1:17:08 Planning Implementation Using BDD Workflow
1:17:21 for the for the reconciliation loop. Yeah. The sort of TDD way of doing it. Imagine you haven't written the code. You would I think, you've got a tag that doesn't run the things that aren't implemented. You'd have just the first scenario not implemented, and you just read what it each step, you'd automate step by step. That really guides my workflow when I'm working on stuff. You know? The first one, I'd I'd automate the first scenario. It would fail. So look at the first scenario again. If you pop open the so I'd I'd I'd automate this first. Right?
1:17:59 So the the first step, I would have something that checks there's no file called there's no directory called git sync in the current folder. I do that as a check rather than deleting it if it exists. So I'd I'd set the current working directly to directory to some temp folder. I'd check there's no file there. I would call I'd call the method that doesn't exist yet when I sync the blah blah blah repository. And then I'd run Cucumber and it would tell me there's no method called in the library called sync, and I'd go and implement it. I was kind of hoping
1:18:37 I'd be able to show that actually. I just I've blown away the target directory, so I'll give that a minute and we'll we'll see. But yeah. That makes sense. But, yeah, I'd basically do TDD until the first scenario passes and then I'd maybe think about committing and make myself a cup of coffee. Yeah. I think we discussed this in the last steps towards a couple of weeks ago as well. It's like this because there's not a lot of business logic here, I am relying heavily on get. There's not really a lot of unit tests for
1:18:54 The Role of Acceptance Tests
1:19:04 me to write here. This this as an integration project that needs to be tested, I think, in this way. Yeah. I mean, you could go down this whole route of having value objects for everything. And and the testing strategy this acceptance testing strategy is is from your library down. It checks the library, does everything. Doesn't have anything to say about the quality of the library. Yeah. That's that's always still up to the professionalism of the developers because below that acceptance test level, we do get into the the arena of developer tests where developers are deciding what tests to write. Mhmm. And that's
1:19:46 just up to the team. The the value of acceptance test is you do have some testing that is at that, like, business delivered boundary, and you you start moving towards the the more you do this kind of example mapping and then writing things down and then automating the test based on it, the more trust you get where people trust that the things in the document have all been checked automatically. And and manual testing and acceptance testing can focus on the things that we forgot to talk about, stuff around the borders, stuff that you only see when it's real.
1:20:19 You know? So you could you could automate those steps against your library, get it working, and then you could all you could either oh, nice. Yeah. There we go. That's what I wanted. Yeah. Okay. So the first thing is, well, let's do this on the next stream. Yeah. Yeah. So I'd I'd get the first scenario passing with the library. I'd then, depending what time of day it is and how I feel, I'd then either hook it into the CLI and get those tests working, or I'd sort of progress through all the other scenarios on the library. But
1:20:36 Conclusion and Next Steps
1:20:54 but hopefully by the end, I've got all of these things passing in the library. I've got two things passing in the CLI. I hit commit. I commit the scenario with the tests, with the code. Here's or, you know, if I write it afterwards, I squash it so it looks like I did it in the right order. Nice. That's my PR. Yep. Awesome. Feature done. Happy with that. That was good. Good place to end then. Yeah. I think if we got another one of these scheduled, I'll teach you a little bit of Rust and we'll work to implement
1:21:26 some of this together. That'd be really good fun. And then we can have we'll hopefully tackle the Delete all my code. Yeah. And we can retreated it. Now you know how it works in your head. Right. Okay. Yeah. Fine. You don't have to. Maybe just comment to all or put it into backup dot r s or something. What I will do is because we're at a pretty good stage now is I will commit as impicious. We'll speak afterwards. We'll get something else scheduled where we Yeah. We actually write the test, connect up the steps, really handle that libraries to allow and tag
1:22:02 and what that looks like. And I think that's pretty awesome. I'm really happy with that. Cool. Alright. Great. Well, oh, well, I mean, as always, Kevin, you've got a lot of knowledge and it's great to be able to extract it from you and thank you for sharing it with me. No worries. If anyone watching wants to know more, get in touch. Yeah. Kieran McNulty on Sorry? I'll come and do it at your company. Okay. Definitely. Yeah. Alright. Well, thank you again, Kieran. I'll speak to you afterwards. We'll get something scheduled. If you enjoyed that, you know, drop something in the comments.
1:22:40 Let us know if there's anything that we you want to see us cover from a BDD scenario, then obviously, we'll try and do something on the next episodes. And of course, out to Kieran if he can come and help you with your own domain. He's a wise man. Thanks. Alright. Thanks a lot. I'll speak to you again soon. Have a nice day. See next time. Bye.
Technologies featured
Meet the Cast
Stay ahead in cloud native
Tutorials, deep dives, and curated events. No fluff.
Comments