Setting Up Integration Testing

Now that we understand both web and authentication components of our application, let's take a look at how we can test the interaction between these two applications. This section will explain:

  • Which parts require integration testing,
  • How we can implement these integration tests, and
  • How we can incorporate these integration tests in our build process.

Explanation of the Tests

As can be seen in the application files, it is the auth.go file in the web application that contains the code, that interacts with the authentication service. This means that the integration tests must focus on testing the following methods:

  1. Login (func (a *authService) Login(username, password string) loginResponse),
  2. Authenticate (func (a *authService) Authenticate(username, token string) bool), and
  3. Logout (func (a *authService) Logout(username, token string) bool).

In addition to simply testing these functions, we also need to test a functionality that combines the use of these functions.

The web_test.go file contains the integration tests that test whether the web application's interaction with the authentication service is as expected. Before we look into the tests in details, we need to set our project up to properly process integration tests.

When we run the go test command, test functions from all the test files, i.e. files in the current package whose names end with _test.go, are executed. This is great for unit tests but we might not want this behavior with integration tests for various reasons.

To ensure that integration tests run only when explicitly asked to, we need to tag the relevant test file. Notice line 3 of the web_test.go file:

// +build integration

This line tags this test file and indicates that go should pick this file up only when supplied with the integration tag. In practice, this means that go will test the functions in this file only when explicitly asked to. This can be done using the following command:

go test -tags integration

Executing this command will test all the test files which are tagged with the integrationkeyword.

The web_test.go file contains the following tests:

  1. TestWrongUsernamePassword,
  2. TestCorrectUsernamePassword,
  3. TestInvalidUserRequestAuthentication,
  4. TestUserRequestAuthentication, and
  5. TestUserRequestAuthenticationAfterLoggingOut.

Let's take a look at what each of this test does.

1. TestWrongUsernamePassword

This function expects the authentication service to return a blank token, an indication of failed authentication, when supplied with the wrong username and password.

2. TestCorrectUsernamePassword

This function expects the authentication service to return a valid token, an indication of successful authentication, when supplied with the right username and password.

3. TestInvalidUserRequestAuthentication

This function first performs a login against the authentication service with the wrong username and password. It then tests whether an authentication request using this username and the returned token should fail.

4. TestUserRequestAuthentication

This function first performs a login against the authentication service with the correct username and password. It then tests whether an authentication request using this username and the returned token should succeed.

5. TestUserRequestAuthenticationAfterLoggingOut

This function first performs a login request against the authentication service with the correct username and password. It then uses the returned token to perform a logout request. The function checks that the logout request executes successfully. After a successful logout, the function tries to authenticate against the authentication service using the same username and token. Finally, the function tests that this authentication request fails, which is the expected result as the user has logged out.

Once this is set up, you can run the following command, in the directory of the web application, to perform the integration test:

go test -v -tags integration

If the test finishes without any failures, you should see something similar to the following:

=== RUN   TestWrongUsernamePassword
--- PASS: TestWrongUsernamePassword (0.00s)
=== RUN   TestCorrectUsernamePassword
--- PASS: TestCorrectUsernamePassword (0.00s)
=== RUN   TestInvalidUserRequestAuthentication
--- PASS: TestInvalidUserRequestAuthentication (0.00s)
=== RUN   TestUserRequestAuthentication
--- PASS: TestUserRequestAuthentication (0.00s)
=== RUN   TestUserRequestAuthenticationAfterLoggingOut
--- PASS: TestUserRequestAuthenticationAfterLoggingOut (0.00s)
PASS
ok      _/some_directory_on_your_machine/web-server 0.009s

Note: For all these tests to work, the authentication service should be running. This setup assumes that the authentication service is running on port 8001. Should that change for you, be sure to update the main.go and the web_test.go files in the web application accordingly.

Setting up Semaphore to Automatically Test After a Push

Semaphore makes it trivial to automatically build and test your code as soon as you push it to your repository. Here's how to add your GitHub or Bitbucket project and set up a Golang project on Semaphore.

The default configuration for a Go project takes care of the following:

  • Fetching the dependencies,
  • Building the project, and
  • Running the tests (without any special tags).

Once you've completed this process, you'll be able to see the status of the latest builds and tests on your Semaphore dashboard. After this is done, we need to modify the setup to do the following:

  1. Set Semaphore to use Docker,
  2. Run the authentication service in Docker during the build process, and
  3. Run the integration tests during the build process.

1. Set Semaphore to use Docker

By default, new projects on Semaphore use the Ubuntu 14.04 LTS v1604 platform. This platform doesn't come with Docker. Since we are interested in using Docker, we need to change the platform settings in Semaphore to use the Ubuntu 14.04 LTS v1604 (beta with Docker support) platform.

2. Run the authentication service in Docker during the build process

After logging in, visit Semaphore's homepage. You should see a list of your projects similar to the following:

Semaphore homepage

On this page, click on the Settings link highlighted in the above image. This will take you to the settings page of your project.

Project setting page

On this page, click on the Edit Thread link of the Setup section highlighted in the image below:

Setup section edit link

This should make the setup commands editable as follows:

Edit setup commands

Edit this section to contain the following (we'll soon see what each command does):

go get -t -d -v ./... && go build -v ./...
git clone https://github.com/demo-apps/semaphore-auth-server.git ../auth-server
cd ../auth-server
go get -t -d -v ./... && go build -v -o AuthServer ./...
docker build -t auth-server-image .
docker run -d -p 8001:8001 --name auth-server auth-server-image
cd -

Fill the setup commands

After entering the commands, click on the Save button to save these commands.

Saved setup commands

Let's take a look at what each of these commands does.

Command 1 (go get -t -d -v ./... && go build -v ./...) fetches the application dependencies and builds the project.

Command 2 (git clone https://github.com/demo-apps/semaphore-auth-server.git ../auth-server) clones the repository containing the source files of the authentication service. These files are put in the auth-server directory which is located in the parent directory of the main web project.

Command 3 (cd ../auth-server) changes into the auth-server directory.

Command 4 (go get -t -d -v ./... && go build -v -o AuthServer ./...) fetches the dependencies of the authentication service and builds the project. The resulting executable binary is named AuthServer.

Command 5 (docker build -t auth-server-image .) builds a Docker image named auth-server-image based on the Dockerfile in the auth-server directory.

Command 6 (docker run -d -p 8001:8001 --name auth-server auth-server-image) starts a Docker container based on the image created by the previous command. It exposes the application on post 8001.

Command 7 (cd -) changes back to the directory containing the files for the web application.

These commands set up the build server so that it has the authentication service up and running in a Docker container. At this point, the integration tests can be executed against this service.

3. Run the integration tests during the build process

On the project settings page, click on the Edit Thread link of the first thread under the Threadssection, as highlighted below:

Click on the edit thread link of the threads section

This should make the setup commands editable as follows:

Edit test commands

Edit this section to contain the following (we'll soon see what each command does):

go test -v ./...
go test -v -tags integration ./...

Fill the test commands

After entering the commands, to click on the Save button to save these commands.

Saved setup commands

Let's take a look at what each of these commands does.

Command 1 (go test -v ./...) runs the unit tests in the project. While this particular project doesn't have unit tests for the purpose of succinctness, a real project is very likely to have those.

Command 2 (go test -v -tags integration ./...) runs the integration tests in the project. Specifically, this command runs all the test functions in the test files that have been tagged with the integration keyword.

After completing this setup, your project will now build and run all the tests automatically, as soon as you push new code into the project repository. Semaphore has a lot of options, that let you customize how and when certain build processes are run. For instance, you can schedule a build process to run at a specific time, or you can manually run the build processes should your project require that.

results matching ""

    No results matching ""