 Okay, yes so I'm Bruce and today I want to talk about how to write better unit tests with aspect and especially why you should stop using before and let. So this idea might be strange to some of you, all you need to know now is that you can certainly write good test case without using before and let. And the first question you might want to ask is that how do you write your test call without using before and let? Write is important, right? So first of all, yes, write is important, but in test case, you should favor a damp over dry in most of the case. And the reason is that sometimes too dry, you remove the duplication and f-trade and over up-trade, then it's harder to read because it's not straight forward anymore. And which is particularly bad for test case because test case itself should be a document for your application as well. That being said, you can certainly extract out some common code snippet and reuse it. By one of the techniques that you're already familiar with, which is, okay, so for example, we have this example and all the preparation, all the setup is within the example, which is the heat block. And how do you extract out without using before and let? So first you move these two code snippets down to a method. And then you're calling it from your heat block. And by this you can extract out some common code you want to reuse. That's all. It's so simple, right? So simple, okay. So actually, by at least point, you already know how to simplify your call and reuse your test call without using before and let. So now you get an idea, we're happy, and everyone is happy, right? No. And because the reason is that the hardest part is actually not learning the technique. The hardest part is actually how do you convince other people? Because if you don't have a good reason, why would people use something that they are not familiar with? Which is easy for them because they are familiar with it. So that brings to the next question, which is, what's wrong with before and let? So let me give you an example. So let's say that you're assigned to a new project, I mean you're assigned to a project which you've never been part before. And you are helping them to overcome the problem of how to maintain code. And your first ticket is to find an investigative bug, which is somehow a teenager is able to watch a R21 movie. So you look into it and you realize, okay, there's actually one test case to capture this scenario. So you look into it and you say, okay, what's wrong with this test case and this code? So first thing you want to know, who is the user? So you scroll all the way up to the file and you find, okay, so with that user is uncle Lin, he's all enough to watch R21 movie, right? So the user is uncle Lin, right? No, because somehow he overwritten by an inner context and now it becomes drunk. So all right, so it's drunk, right? And he's 20, no. So again, the age, the name can be overwritten or can be modified within that or before. And of course, you might say this is not the proper way to use aspect. But that's because as I just mentioned just now that you are joining a project that you've never been in before, you're helping them. And that's how it is. And this actually happened quite frequently. Okay, yeah, and then this goes on and on and on. You spend ten or half hours just to answer one simple question, who is the user? So this can be bad. And then this is another part, so as I showed just now, we know that sometimes it can be hard to read. It can also be hard to change. So for example, we have this, for this case case, we need to set up a lot of things. And why if I want to add something, add a new small behavior that you also apply for the cache bag, for the membership reading, the other coupon, the other type of coupon. So add a test case as well. But now the old test case fail. And this can be, imagine that you have this kind of structure all over the place, over 10, 1,000 lines in one file and it's all been like this. And yeah, so it can be also very hard to change. And this is a simple scenario only. Yeah, so and yep. And then, yes, yeah, yeah, yeah, yeah, yeah. Okay, who am I? Yeah, so now you might thinking that, okay, I know there are some potential pitfalls, so I can avoid it. Or that as long as it works, it's okay, right? You can handle it. But why it matters? Because yes, there are proper ways to use aspect before and later. But if you have tight deadlines and you don't have a lot of like top engineers or like aspect book writers or aspect commuters, you eventually encounter all these problems. Trust me. Because when you want to rearrange all the context that make it reasonable, but you don't have time, your boss is short at you and ask this feature to come out by end of today, what are you going to do? You just insert one more context or just copy over and change a few words to make it work, to make it pass the test case, but it makes the structure even worse. Which is why we have hard to recall at first place. And secondly, because test case test is the safety net for refactoring. And if your test case is bad and it's technical dead by itself, then you are working a tightrope without the safety net, which is very bad. And most importantly, that you're working on this kind of project is a death march. Which is you are not happy. Your teammates are not happy. And your management are not happy because asking for one line of change cost you one afternoon to fix all the test case. And you know everything will come to an end when you reach certain point, you cannot take it anymore. And there were very serious things happen. So it's not a very good situation to work with. And especially because technical depth is not a technical problem. It's about people. It's not about tech. It's about people. Because people are not happy with it. For machines, as long as it works, it works. So it's about people. And speaking of this, there's a very good article. It's about how to control your technical depth by TDD. So it's a very good read. I highly recommend to check out when you get home. But it doesn't end here. There are still a lot of techniques, a lot of knowledge you need to know to write a good test. So here are some tips that I think is very helpful. Personally, so first one is one test, one topic, which is you should only test one thing for one example. In this case, we are testing, he should only allow to watch a tantrum movie if he sees a doll. But in this case, we are conveniently also testing about the name, behavior about the name, which doesn't belong to the concern of this test case. So what we should do is to remove this and make it a test case, an example by itself. And the other problem is the other principle is that you should only give the exact important detail to test. In this example, we are testing the behavior of first name. It should return the first part of the full name, which should be the drum. But in this test case, in this setup, you can realize that the agent active, it doesn't really matter to this behavior. So we don't need that. And another thing is that if you notice, there's a let. So this let, although we don't need the movie at all, but it was actually still wrong. And because it's a let ban, so it was still wrong. And which is bad? Because not only did this confuse you, why my test case care about movie? It doesn't really care, right? But it involved in your test case. So not only did it confuse you, it also slowed your test case down, because it runs every time, even if you don't need that. So that's the other problem with that. And then it goes the other way. Just now it was too much information. Now it can be too few information. For example, you build a user and the first name is drunk. Why? So I think most of us use either Factory Girl or Fabrication. They are cinema in mouth to allow you to set up some default value. And if your default value happens to be John Lin, for example, this case case will pass, which is strange because why? Where the name come from? So we should add the important information to a test. So this is final result. No more and no less. Just exact important detail to test. And then also I would recommend to flatten the context. Sometimes people are very tempting to group your logical branch within the context, which is good. But in some case, you are making it harder to read. As I mentioned, the example just now that in every context, you try to override something in the upper context so that you can test the behavior you want. And it makes the test case very hard to read because you spend 10 minutes to figure out who the user is. So you want to flatten it. And for the branch, the different logical branch, you can add a when or if right in the description to differentiate what is this test case testing at. And then for first test, so this one, the principle here is that most of the time that your test case will contain four different things. Once you want to set up, you want to prepare the scenario that you are testing, then you exercise coding the method you are testing at, or call the attribute. And you verify the return or the change. And lastly, sometimes you will need to clean up something so that it won't affect the following test case. And you will want to separate this four face with new lines so that it's easy to see which price is what. And then also, I would recommend you to enable the documentation format so that when you run the aspect, it will generate a nicely formatted result. And also notice that let's go back to the previous one. So you see the context and the it, they are actually template for it. So your first level of context should be the one, the method you are testing at. Or if it's controller, then it's the end point which is post something or get something. And every it block, the description should start with a verb. And it should be third person presents tense. So it does something or it does not. It returns something like that. So that you can have this sort of document or report. This can be easily understand even for non-technical background people. So you call first name and it returns this. You call watch is either race in session if certain scenario or something does not race in session if certain scenario. So that is easy to understand. But this all this technique will help you change the way you write a test case and immediately help you to write better, easier to maintenance code. But how do you know this is working? How do you know this works? There is no silver bullet. But we do have a reliable matrix which is for the five minutes because it's very straightforward metrics. And so it's like, OK, there's some jokes from network from internet. Does anyone ever do this? Yes, I did. So this was me one and a half year ago. And I was joining a project that I never take part before. So yeah, that's how it was. And in case you didn't notice, 35 was within one hour. So you can imagine how bad it was. So yeah, that's how you know if this technique works. Conclusion. So before we go into conclusion, I have very important things to mention. I have to mention it, which is yes. So we are hiring. NSV is a delivery central company. And we deliver a lot of things. For example, we can deliver grocery and food to your house, to your home. And we can do laundry for you as well. So there are a lot of new services coming out as well. There are a lot of development going on. So we need people. So do talk to me if you are interested in joining us. And the benefit that I'm joining right now is that you can work with the coal base that it's qualified for many lower than 10 per day, which is nice. OK. And then next I want to share that my gen. This gen can give you some nice formatted, and also it gives you the environment name right in your prompt so that you won't do something stupid in production. And also nice format. And you can even have a table so that you can easily share within stack. And you can get all this within just two steps. So remember, go check it out. And also, this is another open source project that if you are sick of all the rubbish in your download folder, you can clean up without doing the daily cleaning up by yourself. So you can get this script. You can install it within just one command. And it will automatically clean your download folder for you every day. And the best part is that it works even if your computer is asleep during the time. Because you will do it after you wake your computer. Yes. So check it out. It's also open source. And lastly, I'm writing a new book about best practice of Ruby and Rails. So if you are looking for a book that tells you not I mean, if you are looking for a book that is not teaching you how to use the basic syntax. Raider tells you what are the best practice and why it matters, how it works. I explained to you what's the problem with before and that. So please give it a try. And you can register your email. Please leave your email. And I promise there will be coupons once it's released. So please leave your email if you're interested. OK, so back to the conclusion. So this technique is simple. And with this technique, it's easy to read. You can write easy to read test call. And it's easy to change. And also it works everywhere. And by works everywhere, I mean you can copy this over to another project without worrying about if we will break because missing of one gen. And you will also work with debugger. You can step into the method. And also it will also work with your existing go-to definition tools of your editor. Because after all, it's just a Ruby method. It's nothing special. Also writing test case without using before and that, good test case without using before and that is possible. And most importantly, reducing the hodlify counter from dozens to a few is also possible. So let's write better test and be happier. Thank you. So in case you miss it, there are some links here. Any questions? We have a few minutes for questions. There I will be first. But then you can follow, don't be shy. So you mentioned that on the first level of unit test, you test by method nine. In controller test, the first level is the name of the end point. What about the integration test or the feature test? Yeah, so unfortunately, I didn't spend much time on that. Yes. But in the integration test, I think that, OK, so if you have a Q18 in your company, what usually will happen is that they will set up their own integration test for you in maybe in Selenium or Corn Helles. So to us, to me, I focus more on the unit test. That's also why my topic was actually how to write better unit tests with aspect. Yes. So, yeah. OK, right now. Yes? What's real benefit? OK, I understand the point of wanting to get rid of. I understand your argument for getting rid of Latin before. You want to reduce abstraction that isn't immediately obvious to the maintainer. But the one thing they let, in particular, gives you is memoization. If I have a variable that's defined using ordinary let, not let bang, ordinary let, then that's defined when I need it and it uses the same definition each time I need it. Yeah? OK. Isn't it more productive to say let bang is a smell that we're going to work hard to eliminate at the earliest possible opportunity? Because what you're really saying there is there is some state. Let bang says there is some state that has to be set for all tests, even the tests that aren't obviously using it. And if it's not obviously using the state, then what's the point? OK, so. So let bang do has its own scenario. And sometimes we have to use it. And the second thing is that in some scenario, this actually happens that using let, which is lazy loaded. So you won't run unless you are coding it. And your test case don't really code in it. Yes. But your before in two contexts away is actually using it. And you are not care about this one in your test case. So it's still eventually be loaded. And actually this loaded is not very bad. The worst part is that it confuses you because you need to go and find all the users and you select let user and you find all the users from this same test case. And you found 30 of them. Which one is real? Right. That's the bad part. Yes. And yeah. It's real real big. OK. Yeah, no questions. Thank you once again. Thank you.