-
Notifications
You must be signed in to change notification settings - Fork 44
Tutorial
In this tutorial, we are going to use Shepherd with the testify suites to write a test that verifies a created project member can create a namespace successfully using one of the Rancher Clients.
Tests can be grouped into files and packages however the developer sees fit.
A suite can share clients and a session across all its tests. By sharing these functionalities a suite's tests can reuse the suite resources.
For example, if we were writing tests that ensure project roles have appropriate access to project resources, a suite could contain all tests for every role and share a project across all tests. This will save time because each test will not need to create a project.
Using the shepherd clients when possible will ensure that any resources created by tests will be cleaned up, and not interfere with other tests.
A test is responsible for cleaning up any resource it creates fully before the next test is run. See sessions for how to track resources in tests.
First, we will need to define a test suite struct. The struct will inherit suite.Suite, for the testify functionality, and the resources that would be shared amongst the tests. As explained above, we always want to count on having the client, and session.
In this tutorial, we are also sharing the standardUser and project. If the test is going to test a test case with both an admin and a standard user, we can have a *management.User object defined in the struct.
type DemoTestSuite struct {
suite.Suite
standardUser *management.User
client *rancher.Client
project *management.Project
session *session.Session
}
Next, we'll need to implement the setup. The suite setup is where the shared resources will be initialized, and created. Which in this case, will always include the session and client. To make sure there are no errors, we can use the testify's require to make sure there is no error.
func (d *DemoTestSuite) SetupSuite() {
testSession := session.NewSession(p.T())
d.session = testSession
client, err := rancher.NewClient("", testSession)
require.NoError(p.T(), err)
d.client = client
projectConfig := &management.Project{
ClusterID: "local",
Name: "TestProject",
}
testProject, err := client.Management.Project.Create(projectConfig)
require.NoError(p.T(), err)
d.project = testProject
enabled := true
user := &management.User{
Username: "testusername",
Password: "passwordpasswordd",
Name: "displayname",
Enabled: &enabled,
}
newUser, err := users.CreateUserWithRole(client, user, "user")
require.NoError(p.T(), err)
newUser.Password = user.Password
d.standardUser = newUser
}
Then the Suite Teardown, the teardown is where the final resource cleanup occurs through the session. The session has kept track of all the resources created, and simple a call to Cleanup() makes the teardown very trivial.
This Cleanup() function can be called anywhere when needed, for example in a test case, in a Suite.Run or Test.Run, in this example we can clean up the resources in the teardown.
func (d *DemoTestSuite) TearDownSuite() {
d.session.Cleanup()
}
Next up is defining the actual test case. The test case is a member function of the test suite defined above, and would always have Test as the prefix, you can learn more from testify suite.
func (d *DemoTestSuite) TestExample() {}
In some test cases a subSession can be defined if resources need to be cleaned up after the test case is finished. This is for the session to only keep track of the resources created by the test case, like for example the same namespace name is used across tests. WithSession will reinitialize the client to use the new subSession.
subSession := d.session.NewSession()
defer subSession.Cleanup()
client, err := d.client.WithSession(subSession)
require.NoError(d.T(), err)
For functions that complete common operations used by tests, and can be implemented into actions or extensions, you can check actions vs extensions. Helpers ideally should not require much configuration or support multiple behaviors.
err = users.AddProjectMember(client, p.project, p.testUser, "project-member")
require.NoError(p.T(), err)
Then there's the validation, in this example, a namespace is created as a project-member, and the validation is simply checking that creation has occurred successfully. For validation checks the testify assert package can be used.
createdNamespace, err := namespaces.CreateNamespace(testUser, namespaceName, "{}", map[string]string{}, map[string]string{}, p.project)
assert.NoError(p.T(), err)
assert.Equal(p.T(), namespaceName, createdNamespace.Name)
Finally, the test suite should have this test runner function in order to be able to run the whole test suite.
func TestDemoTestSuite(t *testing.T) {
suite.Run(t, new(DemoTestSuite))
}