Detecting that a .NET Core app is running in a Docker Container and SkippableFacts in XUnit
I have moved my podcast site over to ASP.NET Core 2.1 and I've got it running in a Docker container. Take a moment a check out some of the blog posts, as I've been blogging as I've been learning.
I've added Unit Tests as well as Selenium Tests that are also run with the XUnit Unit Test Runner. However, I don't want those Selenium Tests that automate Google Chrome to run within the context of Docker.
I tried to add an Environment Variable within my Dockerfile like this:
ENV INDOCKER=1
I figured I'd check for that variable and conditionally skip tests. Simple, right? Well, I decided to actually READ the Dockerfiles that my ASP.NET Core 2.1 app uses. Remember, Dockerfiles (and the resulting images) are layered, and with all things .NET, are Open Source.
Looking at my own layers and exploring the source on Github, I see I'm using:
- microsoft/dotnet:2.1-aspnetcore-runtime on Alpine - .NET Core and ASP.NET Core
- Within there I see they are setting "ASPNETCORE_VERSION" as an Environment Variable, which is useful to know.
ENV ASPNETCORE_VERSION 2.1.1 - microsoft/dotnet:2.1-runtime-deps-alpine3.7 - Necessary dependencies for .NET Core
- I can see it's listening on Port 80, but it also sets a useful Environment Variable!
ENV DOTNET_RUNNING_IN_CONTAINER=true
Nice, so I don't need to set anything to know I'm running .NET in a Container! I wouldn't have known any of this if I hadn't taken 15 minutes and exploring/asserted/confirmed my stack. Just because I'm running Docker containers doesn't mean it's not useful to take the time to KNOW what I'm running! Assert your assumptions and all that, right?
I added a little helper in my Tests:
private bool InDocker { get { return Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true";} }
Since I'm using XUnit, I decided to bring in the very useful helper Xunit.SkippableFact!
For example:
[SkippableFact] public void LoadTheMainPageAndCheckTitle() { Skip.If(InDocker, "We are in Docker, y'all!"); Browser.Navigate().GoToUrl(Server.RootUri); Assert.StartsWith("Hanselminutes Technology Podcast - Fresh Air and Fresh Perspectives for Developers", Browser.Title); }
SkippableFact lets me skip tests for basically any reason. I could help if I'm in Docker, as I'm doing here. Or, given that Selenium Tests will throw an "OpenQA.Selenium.WebDriverException" when it can't find the Selenium Web Driver, I could also do this, skipping because a specific Exception was through. Note this means it's a SKIP not a FAIL.
[SkippableFact(typeof(OpenQA.Selenium.WebDriverException))] public void KevinScottTestThenGoHome() { Browser.Navigate().GoToUrl(Server.RootUri + "/631/how-do-you-become-a-cto-with-microsofts-cto-kevin-scott"); var headerSelector = By.TagName("h1"); var link = Browser.FindElement(headerSelector); link.Click(); }
The results look like this:
Total tests: 22. Passed: 18. Failed: 0. Skipped: 4. Test Run Successful. Test execution time: 8.7878 Seconds
You could choose to Skip Tests if a backend, 3rd party API, or DB was down, but you still wanted to test as much as possible. I'm pretty happy with the results!
New Sponsor! Never type an invoice again! With DocSight OCR by ActivePDF, you’ll extract data from bills, invoices, PO’s & other documents using zonal data capture technology. Achieve Digital Transformation today!
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
Comments are closed.
Then for the test run, you do:
Running selective unit tests
SkippableFact looks like a cool project though, and has some extra functionality that you can't get from a pure filter by trait.