Go is built from the ground up to be simple and easy to use. This extends to its testing framework. Rather than learning a whole new set of programming constructs, writing tests in Go is just like writing any other code. It is, however, a complete framework with various conventions and tools available to make writing tests easier. This course is designed to introduce you to testing in Go. For the casual developer, module one gives a nice overview of the major concepts without bogging you down in the details. More advanced users can then move on to the other modules where I will walk you through an in-depth, step-by-step investigation of Go’s testing capabilities and leave you ready to write well-tested applications into your production environment.
Michael Van Sickle is an application architect in Akron, Ohio.
He is a mechanical engineer by training and a software engineer by choice.
He is passionate about learning new programming languages and user
Unit Testing Hello. My name is Michael Van Sickle for Pluralsight. Welcome back to this course where we are learning about the testing capabilities of Go. In the last module, we took a tour of a lot of different concepts getting a good idea about what Go's testing ecosystem looks like. This time, we're going to dive deep into Go's capabilities around the creation of normal tests, that is those that are intended to prove that the application performs correctly when called with a set of stimuli. First, I'm going to take you on a tour of the features of Go's testing API and how they interact with the test runner. We've already talked about a couple of these features, but there are quite a few more that I'd like to introduce you to. Next up is the creation of a custom test runner. If you're used to using the xUnit style of testing frameworks, then you're probably looking for the setup and teardown functions. Well, Go doesn't have those as special functions. Instead, you can create a custom test runner to control what happens before and after the tests are run. After that, we'll learn about how to create table-driven tests with Go. Like a lot of other things we've talked about, this is done with regular Go code, but the pattern for creating these kinds of tests is so common that I thought it made sense to talk about as a dedicated topic. Finally, I'll use the Purchase Order Management System demo to introduce how to create mocks for your tests. Along the way, we'll see some of the challenges that you might face when you try to introduce tests into a code base that was not developed with tests in mind. Let's start out by playing around with the test runner and how we can influence its behavior.
Code Coverage Analysis Hello. Welcome back to this course where we are learning about the testing capabilities that are built into Go. In the last module, we examined the tools that can be used to ensure that the code that we write works as expected. Now it's time to see how well we've done writing tests that exercise the entire code base by using Go's test coverage capabilities. I'm going to be honest with you. We've already covered a lot of this material in module one. The fact is that Go's test coverage capabilities while powerful are simply not that complicated. However, there are a couple of things that I think we can learn when looking at the tools in the light of a realistic application. I want to start at the beginning and make sure that we all know what code coverage is and what it's used for. Next, we'll review some basic test coverage analysis tools and how they perform in the POMS demo application. After that, we'll move into reviewing the two detailed code coverage reports that we have available to us. Finally, we'll review a version of the HTML coverage report called a heat map. This report allows us to go further than the basic test coverage by telling us how often a section of code is actually being run by the tests, a useful thing to know for certain bits of code that are sensitive to a lot of different edge cases and you want to have confidence that you are thoroughly exercising it.
Blackbox Testing Hello. My name is Mike, and welcome back. So far, we've seen how to use Go's testing package to test our own code for correctness. We then looked into its code coverage capabilities and saw how to use them to find sections of our application that we haven't covered with tests yet. In this module, we're going to talk about Go's Blackbox testing capabilities that are included in the testing/quick package. The testing/quick package is designed to fire multiple sets of randomized inputs into a Test function and then inspect the results. The Value function is the primary tool that is used to generate these random inputs, and so we'll look at that first. Next, we'll look at the Check function that is designed to check a single function's behavior and use as a simple true/false return value to signal the result to the test runner. The companion to that function is the CheckEqual function. This is a great tool for checking if two different functions provide the same output when given the same input. We'll use this to check if two algorithms give the same results. Normally, tests are passed randomized inputs that span the range of data that they can hold. That means that an argument that accepts a float64 can receive very large and very small values. By implementing the generator interface, we'll be able to control how those values are generated. Finally, we'll talk about the config object that can be passed to the Check and CheckEqual functions. You can use this to further customize the behavior of the test cases. Let's get started by looking at the Value function.
Performance Benchmarking Hello. Welcome back to this course on testing with Go. We've just finished talking about the Blackbox testing capabilities that Go has, and wrapped up the aspects of the framework that are designed to test the correctness of your code. However, just proving that the code does the right thing is not always enough. Applications often have requirements surrounding how quickly they respond and how many system resources they use. Benchmark tests are an ideal tool for ensuring that these requirements are met. I want to start out our discussion with the benchmark tests themselves. There are actually a couple ways of creating these, and I'll show you both. Next, we'll investigate how to work with the timer that the benchmark is using in order to make sure that we are timing the things that we should and ignoring setup code and other things that aren't really part of what we want to test. Next, we'll talk about how to create parallel tests. This is a bit different from basic tests since we are concerned with the ability to run multiple tests at the same time. For benchmarks, parallelism is about executing multiple test cases at the same time. Finally, benchmark tests can be used to measure the memory load that the test applies to the system. By measuring this, it can be easier to make sure that the application's host systems are properly sized. As a bonus, I'll wrap up the module with a trip to the Purchase Order Management System demo project and measure the total performance of a couple of the application's HTTP endpoints. Let's get started with benchmarks.
Example Tests Hello. My name is Michael Van Sickle for Pluralsight. In previous modules we've talked about the unit testing and benchmarking testing capabilities of Go. Now it's time to introduce the last major test type that is available, example tests. These tests occupy the same place as unit tests in the testing framework. So they are guaranteed to work correctly by the test runner. However, they are structured differently so that they can be integrated by the Godoc tool directly into the application's documentation. I want to start the discussion with how to create example tests themselves. I've already covered this back in module one, but I want to review the syntax and rules here as a reminder and a point of reference if you want to review this material later. Next, we'll take a brief tour through Go's integrated documentation generator called Godoc. While I'm not going to go too deeply into this topic, we need to know enough in order to get at our code examples. Finally, we'll look at the naming conventions that example tests must adhere to in order to guide how Godoc includes the examples in the API documentation. Well, that doesn't seem too bad. Let's get started by writing some example tests.
Testing Web Applications Hello, welcome back. At this point, we've covered most of the critical parts of testing with Go. There is just one more small topic that I'd like you to be aware of in case you find yourself testing an application that exposes or consumes web services. After that I have a special bonus for you, but let's not get ahead of ourselves. Web services are great, since they allow your application to be broken down into areas of specialization. By breaking common operations out into web services, all of your applications can take advantage of enhancements that are added to them. However, participating in this kind of distributed ecosystem makes each application more challenging to test. To address that, Go comes with a couple of tools to help us out. First up are servers. These aren't the production HTTP servers that our application uses to expose its services. Instead, these are mock servers that are designed to allow you to quickly control how a given request is handled. We'll use these to mock how a web service call responds so that the test can control the environment better and help ensure that test results are repeatable. Next, we'll look at the ResponseRecorder. This little gem allows a web service call to be made without having a server up and running at all. This will allow us to test the HTTP endpoints that an application exposes without requiring true HTTP calls. This will not only speed up the tests, but make them less susceptible to the occasional network hiccups that can sometimes make the service calls unstable. Let's start by looking a little deeper into what mock servers are going to do for us.
Performance Profiling Hello. Welcome to this final module in this course on testing applications in Go. We've already covered all of the testing-specific content that I have for you. But there's one more topic that I think might be useful to know about. A while back we talked about how to create benchmark tests that can measure the resource usage of an application. However, we didn't have any tools to figure out where those resources were going. In order to address this, Go makes its performance profiler available to tests so that they can more easily be studied. If we're going to talk about profiling, I don't want to just focus on how to use it in the test runner. As with a lot of things in Go, the concepts involved with profiling aren't much different across its use cases. So I thought I would cover these areas as well. First, we'll take a look at creating an application that generates profiling information and investigate a couple of types of profiles that we can generate with it. Next, we'll move into the world of tests and see how to generate those same reports with profiles generated during the test run. Finally, we'll cover web applications, which as usual, require a little different handling. The basic concepts are the same, but the integration is a bit different. Let's get started by writing a simple profiling app next.