Running end-to-end tests in Docker

There's one more component I've added to the NerdDinner solution in this chapter, which is a test project that uses a simulated browser to interact with the web application. The browser sends HTTP requests to an endpoint, which will actually be a container, and asserts that the responses contain the correct content.

The NerdDinner.EndToEndTests project uses SpecFlow to define feature tests, stating the expected behavior of the solution. The SpecFlow tests are executed using Selenium, which automates browser testing, and SimpleBrowser, which presents a headless browser. These are web tests that can be run from the console, so no UI components are needed and the tests can be executed in a Docker container.

If that sounds like a lot of technology to add to your test infrastructure, it's actually a very neat way to perform a full integration test of the application, which has been specified in simple scenarios that use human language:

Feature: Nerd Dinner Homepage
As a Nerd Dinner user
I want to see a modern responsive homepage
So that I'm encouraged to engage with the app

Scenario: Visit homepage
Given I navigate to the app at "http://nerd-dinner-test"
When I see the homepage
Then the heading should contain "Nerd Dinner 2.0!"

I have a Dockerfile to build the test project into the dockeronwindows/ch10-nerd-dinner-e2e-tests:2e image. It uses a multi-stage build to compile the test project and then package the test assembly. The final stage of the build uses an image on Docker Hub that has the NUnit Console Runner installed, so it is able to run the end-to-end tests through the console. The Dockerfile sets up a CMD instruction to run all the tests when the container starts:

FROM sixeyed/nunit:3.9.0-windowsservercore-ltsc2019

WORKDIR /e2e-tests
CMD nunit3-console NerdDinner.EndToEndTests.dll

COPY --from=builder C:e2e-tests .

I can run a container from this image and it will start the test suite, connecting to http://nerd-dinner-test and asserting that the content in the response contains the expected header text. This one simple test actually verifies that my new home page container and the reverse proxy container are both running, that they can access each other on the Docker network, and that the proxy rules have been set up correctly.

I only have one scenario in my tests, but because the whole stack is running in containers, it's very easy to write a suite of high-value tests that execute the key features of the app. I could build a custom database image with known test data and write simple scenarios to verify the user-login, list-dinner, and create-dinner workflows. I could even query the SQL Server container in the test assertions to make sure that new data is inserted.

The next step of the Jenkins build runs these end-to-end tests. Again, it's a simple PowerShell script that does this, building the end-to-end Docker image, and then running a container. The test container will execute in the same Docker network as the application, so the headless browser can reach the web application using the container name in the URL:

cd .ch10ch10-nerd-dinner

docker image build `
-t dockeronwindows/ch10-nerd-dinner-e2e-tests:2e `
-f .docker erd-dinner-e2e-testsDockerfile .

$e2eId = docker container run -d dockeronwindows/ch10-nerd-dinner-e2e-tests:2e

NUnit generates an XML file with the test results, and it would be useful to add that to the Jenkins workspace so that it's available to view in the Jenkins UI after all the containers have been removed. The PowerShell step uses docker container cp to copy that file out of the container into the current directory of the Jenkins workspace, using the container ID stored from the run command:

docker container cp "$($e2eId):C:e2e-testsTestResult.xml" .

There's some additional PowerShell in this step to read the XML from that file and determine whether the tests have passed (you can find the full script in the source folder for this chapter, in the ci4_test.ps1 file). When it completes, the output from NUnit is echoed to the Jenkins log:

[ch10-nerd-dinner] $ powershell.exe ...
30bc931ca3941b3357e3b991ccbb4eaf71af03d6c83d95ca6ca06faeb8e46a33
*** E2E test results:
type : Assembly id : 0-1002 name : NerdDinner.EndToEndTests.dll fullname : NerdDinner.EndToEndTests.dll runstate : Runnable testcasecount : 1 result : Passed start-time : 2019-02-19 20:48:09Z end-time : 2019-02-19 20:48:10Z duration : 1.305796 total : 1 passed : 1 failed : 0 warnings : 0 inconclusive : 0 skipped : 0 asserts : 2 *** Overall: Passed

When the tests complete, the database container and all the other application containers are removed in the final part of the test step. This uses the docker container ls command to list the IDs of all containers with the ci label – those are the ones that were created by this job—and then forcibly removes them:

docker rm -f $(docker container ls --filter "label=ci" -q)

Now, I have a set of application images that are tested and known to be good. The images exist only on the build server, so the next step is to push them to the local registry.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.189.171.153