Wednesday 23 October 2024

BDD Style Testing with MSpec (5 of 12) Automated Software Testing

[MUSIC]. >> Hi, welcome to Visual Studio Toolbox. I'm Robert Green. >> I'm Leslie. >> We're with Phil Japikse for another episode in our mini series on automated software testing. So far, just to recap, we talked about why it's important. We talked about. >> X-unit. >> X-unit in depth. >> In depth in three episodes. Today we're going to talk about behavior-driven design using M-spec. >> Also machine specifications but M-spec for short. >> That leads to two questions. What is behavior driven design what's it got to do a testing, why are we talking about this. >> First thing, I want to show is this slide, so bunch of Legos here. We can all agree that this is really TDD. I am testing my individual unit of work, which in Legos, Lego blocks. You into Legos? I know my kids are into Legos. >> I love Legos I'm obsessed. My wallet, hates me for it. >> We have bins of Legos and no instructions, although you can find them online. I don't know if you've ever tried to build the Millennium Falcon without the instructions, it's pertinent near impossible. >> Yeah hard pass. >> This is test-driven development. We're making sure all of the blocks work correctly. But we're not checking to make sure they work correctly together. Let's look at this Lego, and this is from Legoland outside of Orlando. I know Lozi already knows the answer so I'm going to ask you Robert. What's wrong with this picture? Can you spot it? It's a submarine I'll give you that much. >> It's a submarine. >> You cant unsee it now can you? >> No. >> I don't know. >> I'm going to guess that the unit test for the periscope all pass. The unit test for the hatch all past. But you can't use this particular periscope unless the hatch is open. Why do some marines have telescopes? So they would be underwater and see what's above water. They didn't check the behavior of the periscope in relation to the submarine. What we want do when we're talking about BDD, Behavior Driven Design, behavior-driven development, there's some discussion, but we're going to use a framework called machine specification or M-spec for short, that uses BDD style testing. What we're going to do is rest up a context. Within that context, we're going to have several certs. We still have an arrange section. We only have one action and then we're going to confirm the behavior of those actions. >> We're not using X-unit at all. >> We're not using X-unit we are using a different framework called M-spec. >> Would there ever be a case where you'd want to use the two together? >> Yes. All the time. But you don't use them together in the same tests. You use them to gather in your solution. >> As you're writing your individual units, you're still using X-unit, test those and you never stop. You are still testing the periscope. You are still testing the hatch. This is now on top of that to make sure that as a system, things work together. >> Yeah. If you look at the tidal and I put demo in front of it because it messed up my other tests. When authenticating your admin user, actually you know what? Let's follow up with that same example, and we're going to say, let me get rid of all this, when using a periscope wqe're going to establishes our arrange and I could actually fill it out because I don't want to waste time doing it. Then this is not how you spell periscope. There's my tear down if I need it. Here's my action. This would be the captain is using the periscope. It should allow boat to stay submerged. >> The wording that you're using, can you basically write whatever you want and then apply that to a class? >> Should see above the water and we're not going to go any further than that. Now, you might be wondering why establish clean up because in it are all showing up as keywords. Because they are delegates that come from the machine spec framework. You know what? We did this for n unit. We should do this for M-spec. >> I was going to ask like is this a package? >> This is a several packages that we pull in. I started with an X-unit template. The X-unit template. Lot of times you'll use both together and you can, but also it sets up the test SDK to things that we need to run unit tests and automated fashion in Visual Studio. There's also a command line that you can use with M-spec just as with X-unit. Now, if you were a fan of M-spec prior to.NET core, because it was really awesome back then. It took a long time for M-spec to catch up. It's open source. It's not as actively being worked as X-unit and it's only within probably 6-9 months that actually started working with Visual Studio in.NET post framework. Can we say that of course have done that? Then, you know, again, just as my muscle memory, I always add in MOQ into it. But let's go back we just created this class named when using a periscope and we did two asserts that are worded like this. Let's build and actually this is how periphery, this is. I use ReSharper as well as the built-in test runner right now M-spec isn't working with ReSharper. It was like six months ago. M-spec isn't nearly as popular as X-unit. It has some limitations, but it has some stuff that's really cool that I want to show. If I go to my Test Explorer and then go to my Machine Specification folder and then go into the roots and I see a test here that says when using a periscope and we expand this should allow both to stay submerged and should see above water. What happens here is the parent of the testing group is the name of the class. Every one of the it's is a test. The nice thing about this is I can write out, here's my contexts when using a periscope. Here are my assertions. It should allow you to be underwater. It should allow you to see above water. It should not leak water, whatever they are. I want to build a calculator or when using a calculator, it should add these numbers. It should subtract these numbers. It should divide these numbers. It should do whatever a TI35 can do because that's the best calculator ever. That's some geeky statement. >> I'm for the TI89. >> Yeah you're a little younger than me, it's old school is hard to get out of my system. I have all these its that are verifying the context that I'm in. Your question is, would you use them together? I'm not going to write a data-driven test and M-spec to make sure that my Add function works with all these different inputs. I'm going to do an X-unit. But I want my entire behavior to be tracked. The nice thing about M-spec is and I must say it doesn't work, but I have got working yet in a.NET Core world. But in a prior DotNet Core, you could actually run a command line that would then take all of your contacts, your specifications dumping out in either HTML or MSD and style documentation and there's your entire system, so you've documented everything in there. >> Is this a way to test something like if a new order is entered, it should write the order, the order date, order table. Write the details the details table update the total sales in the customer table, email the customer and email the sales rep. That's an example because each of those are methods that are individually tested. >> Correct. >> But how do we know they're actually occurring in the order they're supposed to occur and that they actually occur when the user clicks Save. Is that a good use for it? >> I agree with everything you said except for the word order. Because you can't guarantee the order of when the delegates execute but yes. Again, these are very trivial, but when authenticating an admin user. Here's my service that I have to create an instance of, that's my arrange. Here's my action. Authenticate with a very secure password right there. I didn't use a P at site SSW0RD, so it's a little more secure if I just spell password out. But it should indicate the user's name and the session ID should not be null. These are things but yes, absolutely. When an order is placed, inventory needs to be reduced the credit card needs to be charged. The packing list needs to be generated. All of these things and so it's the behavior of your system. This is the, I want to do a Kessel Run in seven parsecs, which you're still going to write tests around the engines. You're still going to write tests around the hidden cargo bay, all of those individual thing. The nice thing about it again is when you run at these all come up as individual tests. It really enforces that single action. Because where as you can wrap this in curly braces, I believe you get a compile warning. They built an analyzer and to say, you shouldn't do that. >> But we can also just like everything we've talked about so far. I'm going to talk more in our next episode where we talk about mocking and how we do exceptions. We're going to say, we're going to catch this exception. The new sample service, when an exception is thrown with authentication, we're actually going to catch it and then we're going to examine the exception. Maybe they've logged in with a bad username or password. To be clear, you should not use exception handling for that. Exceptions should be exceptionally, it should not be business logic. But this gives you that capability of saying, I'm going to catch this exception and then let me examine it, so each of the, it's or the assertions are then going to say, here's the reason, here's the argument, here's the details. >> Is this also if you write this ahead of time with stubbed out code, basically the spec. >> Exactly. >> It's you're standing, that you've specked it correctly. >> Correct. >> Then you can sit down with the end user and say here's what I'm testing for and then wait, it's supposed to do this as well. Oh, okay. >> Back in full framework days. Again, I'm not saying that M spec can't handle it. I haven't figured out how to do it yet in the Dotnet core world and that's on me. I haven't done the research, because like I said, it only recently started working in DotNet Core. But back in full-frame workdays is part of our Build Pipeline. We'd actually run the command line to build the HTML of all the specification of the system. We actually published it to a Wiki. The product owner and the stakeholders could look and see what we're testing and because the ones that aren't complete come up like this as not implemented, let me run one of the ones that is implemented so you can see the difference. Any one of these I think will work. Now I'm implemented. This one's not implemented, sees a different icon. Again, when you build that report, they can also track where you are in progress. This test is passing, this test is passing this one hasn't been implemented yet it haven't gotten that far go. There's a couple of more features I like behaviors, it's really been documented as an anti-pattern by the people who took over support. But really what I'm doing is I'm encapsulating certain business rules. Here I have when using behaviors is by contexts, and it's going to behave like these other behaviors that I have and so this is cross-cutting concerns. It should log the call. It should report the error, it should these things that are repetitive, or you can put in here and so it should equal be not null, this is the same tested before, but all I did was, if you see there's a class name is authentication behaviors marked with the behavior label. Behaviors. Vocabulary matters. Then I just say, hey, include all of my tests from this other class into here so it's a way of encapsulating. The reason it's an anti-pattern is there's no way to authenticate that this delegate in the types you're dealing with actually, there's no compile time enforcement, so you can't shoot yourself in the foot. But I still like that. Real quick is also after contexts so after your entire context runs. This is the fixture tear-down equivalent, after everything is done, we're going to clean up after ourselves. Then here's a tear down and set up for each individual context. Now, it will not do it. Because if you think about it, there's only one action and one arrangement in the multiple asserts. It does it after, you have to think of the context in M spec almost the same as a unit test in x unit because it's one encapsulated unit it just happens to be a class and not a method. We talk about setup tear down. This is when the entire assembly has completed. This is before any context in the assembly starts. This is, I said it backwards before. This is the, I'm going to fire this off before any other Tests Runs, or I'm going to fire this off after every test has run. The other one I showed you and I apologize I misspoke. It's easy to do when you're live. This is after each context. Each specification. I mean, that's really it. That is m spec. I really like it using it in conjunction with x unit. Because what I have and we're slowly switching over to this at work because it was about six months ago. I tried a long time ago, six months ago, I realized that it was working again. I know I could probably fork it and do a commit and everything else. I just don't have the bandwidth for that. Now we're going to start to incorporate this into our regular workflow so that we can get that documentation of, you know, when a lead comes in from the field here and the things we have to do, and when all these are done, then you're good. But let's look at this. How did we validate that this is a repeat client or not?. Now we have an x unit test that dives deeper into that using the Inline data, checking phone numbers, checking e-mails, against all of the different situations. >> Sweet. I like this focus on the bigger picture when it comes to testing. I feel like when we talk about testing, not just in this series but beyond, we're always talking about, yeah, just the individual Lego pieces and it's like how does it all fit together? What do we do to make sure that all of these are working in the way that we expect them to. >> Well and as developers, we have to think about the Lego blocks. >> Yeah. >> Because that's what you code, and so if we all start thinking about the submarine, and then go down and get an okay Periscope, I'm going to write Periscope now, right and then we'd go back to the submarine and go, oh, I'm going to do the hatch now. Yeah and then we're not always putting those pieces in place and making them work together until we get into that final application and QA comes back to us and says, we're drowning because I have to open the hatches periscope. >> Exactly. >> All right that's what I got on this one. >> Sweet. Well, good stuff. >> We're now at this point about halfway through. In our next episode we are going to start looking at mocking. >> Finally. >> Yeah, I know I've been waiting for this shoot, I'm going to happen it up for so long. >> We'll see you next time on Visual Studio Toolbox. >> All right be thicker. [MUSIC]

No comments:

Post a Comment

Building Bots Part 1

it's about time we did a toolbox episode on BOTS hi welcome to visual studio toolbox I'm your host Robert green and jo...