Transcript from the "Testing" Lesson
>> Let's talk a little bit about testing in Go and let's make a quick unit test to see how that works. So testing, it's in Vanilla Go. So actually, it's included in Go by default, I don't need to use an external framework. That doesn't mean that they're not libraries or frameworks if you don't like the one that comes with Go, okay, but we do have one in Go.
[00:00:25] If you are used to do testing and unit testing, you might not like some ideas here, okay? Just a warning. What is a test? A test or a test suite is a file with the suffix_test. So any file, _test will be a test suite that you can run.
[00:00:50] Where do you put those files? Typically, and this is the part where some people say I like this, within your code in the same folder in your package. You just know that they are tests because they have the _test. You define functions in that file with the prefix Test, capital T and they have a special signature, we will see that in a second, that receives a pointer to a T structure, a T type, let's say for now.
[00:01:27] It's an argument of type T, okay, the package testing. Inside the function you call methods of T, okay, of that T argument that you receive and you can create sub tests as goroutines. So one test can open a lot of sub tests in different goroutines, okay? It sounds weird but anyway.
[00:01:50] You can use the CLI and type go test and you will run all your tests. You don't need to specify which one from which package, it will just go over all your files and find the ones that are following the rule that I mentioned before. Also there is a design pattern that you can check later if you want, it's called TableDrivenTest.
[00:02:10] It's not actually from the Go team, but it's one that is being used a couple of times. So actually with idea, it's a design same pattern not an API. The idea is that, we realize that sometimes most of our unit tests are just receiving different arguments and testing the API over different arguments.
[00:02:32] So, why don't we create a table of different arguments? Let's say pass zero and zero, zero and minus one, zero and two, zero and three, and what's the expected result in a table, in a format. And then we create a test that goes over the table, make sense?
[00:02:48] Something like that, that's the design pattern but it's used in the Go ecosystem. From Go 1.19, we do have super fuzzing, not sure if that is important fuzzing, what is that? Okay, we'll show you what is that. It's an automatic testing that manipulates input to find bugs. So for detecting security exploits and vulnerabilities, it can detect for example, SQL injections, script injections.
[00:03:19] So you pass a function or a method and it will execute that function with different arguments with values for the arguments. So it will like random and non-random. So it will stress your functions to see if they can find problems, security problems, or bugs. Okay, that's pretty simple.
[00:03:40] So let's go back to our code and let's create a test. It will be a simple test, but just to understand how that works. For example, let's test the API. So I'm going to create a unit test test one test, you will get the idea very simple. So it's a new file going to create a new folder, no new file.
[00:04:01] I can call this CEX, C-E-X_test.go. What's the package? Look at this, probably you have seen this before. When you are in a package, you always receive the hibitation to use the name of the package or the name of the package under core test. And that's the one we are going to use now, okay, makes sense?
[00:04:30] By the way of course, if you go to the Go.the website, you can find, lemme see what that is in the learn section. I think they have a section for testing, when you have examples they used to have one for testing. So you can see, let's see, this is the one I'm looking for, see this is one.
[00:04:55] So you can see examples in case you wanna check for example here they have an example of this, of a function testing something, right? So what was the idea we create functions in this package? Starting with Test, you can see here it's suggesting me this, TestXxx and we are in the x package with Xxx yeah anyway.
[00:05:18] But that's Visual Studio saying that you should put something there so if I press enter it will change the Xxx with something. So for example we can check calling the API the API call you just put the name here and we receive A pointer to testing.T and we typically call it lowercase t, that argument.
[00:05:47] And I need to import the testing framework. And look at this, when I have the right signature, VS code will show me a nice red play button. Okay, that one, that appears in the margin. So you can actually, and also you have some actions, debug text, run test, available here.
[00:06:12] So you can run the test, okay, and it will give you an answer. Right now, the test is empty, so. And for example, maybe I wanna do just one test. What happens if I call get rate with an empty currency? I wanna receive an error, okay, make sense?
[00:06:29] So let's try that. So first, how do I call my API? Even if I'm in the same package, I'm actually not, I'm in the test package. So by the way, everything that has _test won't be compiled in the build. Even if it's in the same folder, it's still Go code, the build process will know that, yeah, it's now for building.
[00:06:55] So actually I need to talk to my API package and we need to import the API as if we are in a different package. So I can call get rate and pass an empty string and then I'm gonna receive the result an error. I don't care about the result, I care about the error, and I actually need to check if the error is not nil.
[00:07:18] Because if it's not nil actually we can check if it's male let's go with nil, if it's nil is that the test should fail, it shouldn't be nil, okay? Do we have a third here? Actually no we have a simple way to define things, we don't assert so the assertion is something that you do on your own.
[00:07:42] And if you wanna fail, you just call t.error and there are two T error and error F and at this point you should like recognize what that F stands for is for format in case you wanna format the message. For example, I can say that error was not found, well, in this case, I don't have a format.
[00:08:07] I can just say error, okay, we like that. So if I run this, it's an error, so we are not passing the test. Because we didn't check this and I don't know what's going on, but maybe I know what happens with the API when you don't pass, maybe it's responding something.
[00:08:27] Well, it's not working, so I need to go and change this, okay? So in this case, I should add here at the top something like if the length of the currency is 0, actually it should be if it's not 3, I should just return. Well nil, an error that they can create on the fly, something like three characters minimum.
[00:09:00] And you can say it's gonna require and you can say %-d receive. You can pass the length of the currency, oops, as an argument. So then we say, we are expecting three and we receive one or zero characters or something like that. Okay, do we have a third SQL as now?
[00:09:30] Of course, there are frameworks and libraries for Go that will help you to make things faster, but you have the basics. You throw an error over the T option, remember we are doing this over the T object. What's the T object? The argument that we receive in that call.
[00:09:55] So if I run again, now we are green, we are passing the test. Okay, also if you are in VS Code in this section for the test, you can run all your tests. You can see all the tests, tree, run them. That's kind of new in VS Code, and it works with Go.