The concepts and basics of unit testing are not covered here, but you can refer to some official go guides and other materials on the web:
For components that need to operate k8s, the key to single testing is how to construct a k8s cluster in the single testing function for the business function to CRUD the corresponding resources. The general idea of constructing a k8s cluster is divided into two categories: using a fake client to construct a fake and constructing a real, lightweight k8s cluster in the process of single testing; the following will introduce these two methods one by one The two methods are described below.
Note: Depending on the test object, it is sufficient to choose the appropriate method that can achieve the test purpose, and it is not necessary to force the use of a particular method.
Using fake client
The fake client can only be used to CRUD various resources (but in fact this can cover most of the scenarios), some other operations such as triggering the callback event of the informer is not possible, so if the test code also wants to cover such scenarios, you need to use the following method of constructing a real cluster; using the fake client test steps The test steps are roughly as follows.
- Construct test data
- construct the test data, i.e., the (native and custom) resource objects needed in the various test cases
- use the above test data to generate the fake client
- Append these test objects to the fake client
- replace the client used by the business function with the fake client
- This depends on how the business function is implemented and how the k8s client is obtained
The fake client can be subdivided into the following two categories.
refers to the native client-go and the typed client of each CR generated using code-generator, which provide the corresponding fake client method. is easy to construct, just use one function and add all the objects needed for testing.
A simple example is as follows, starting with a business function defined as follows.
I need to test just two scenarios: adding an event and updating an existing event, and constructing test data for these two scenarios.
Generate a fake client based on the test data of the case and execute the test.
Note: The test function does not have to be written like the example, focus on understanding the process and the method of constructing the fake client can be.
For the controller test, if you use the lister, you need to add the required resources to the informer of the corresponding resources, so that the lister can read the corresponding resources in the business code, a simple example is as follows.
After that, just replace the client and informer and run the test again.
refers to the generic client provided by controller-runtime, unlike the typed Unlike the typed client above, this client is a generic client that can be used to CRUD any resource. The test method is basically the same as above, only the method of constructing the fake client is slightly different, but the rest of the process is the same. The following will only introduce the method of constructing the fake client, and the rest of the content will not be repeated.
The biggest difference in the method of constructing the fake client of the generic client is that it needs to contain the scheme of all the resources to be CRUDed.
The general construction method of scheme is as follows.
Constructing lightweight clusters
This method can be used to test scenarios that cannot be covered by using a fake client. It is very convenient to start a real cluster in a unit test using the envtest library provided by controller-runtime, and since a real cluster is started, this method is applicable to any client.
The test steps are roughly as follows.
- prepare the cluster-related configuration and start the cluster
- Generally, no additional configuration is needed, a function can be started, if you want to pre-register CRD and so on, you need to configure more configuration items, you can refer to https://github.com/kubernetes-sigs/controller-runtime/blob/master/pkg/envtest/server.go#L105
- use the kube config of the cluster created above to generate various clients
- create test data (if needed)
- Run the tests and destroy the cluster when finished
Start the cluster as follows.
Note that the method needs to install kubebuilder in advance, it relies on the apiserver that the kubebuilder package provides several binary files, the local words themselves download to install it, if the CI environment requires it, you can add these files in the base image, an example.
The following is a simple example for a normal client with business functions defined as follows.
Then you can use the above
apiextensionClient to execute the test.
A simple example for the generic client is as follows.
Comparison of common scenarios
|fake client||real cluster|
|use lister||supported, requires additional processing||supported, no additional processing|
|informer events||not supported, cannot be triggered||supported|
|running dependencies||none||requires kubebuilder|
fake client is simple to use, very lightweight, fast execution, but it basically can only cover resource CRUD scenarios, other operations of the business code can not be covered, there are some scenarios can be covered but need some additional operations, a little bit of trouble; construct real cluster can completely simulate the components running in the online cluster, almost all the business code can be covered as long as you want to test However, the execution speed is slow and there are special requirements for the environment; a simple way to judge which solution to choose is to use the fake client to test the fake client that can be covered, and then use the method of constructing the real cluster if the fake client cannot be covered.