For those that attended my session at techorama, you can find the slide deck and the demos I used here
Slides:
https://xpir.it/testautomation
Demos:
Enjoy!
The only source of knowledge is experience
For those that attended my session at techorama, you can find the slide deck and the demos I used here
Slides:
https://xpir.it/testautomation
Demos:
Enjoy!
TLDR; Make sure all your async methods return a type of Task<something> and not just Task or Void! this will cause sporadic crashes of your application. Only use asyn void or async Task on event handlers.
Longer version:
Recently I worked on an app build in Xamarin and found myself in a nasty situation. My app would crash in the debugger and leave no trace what was going on. In the device Log I could find the following message:
Time Device Name Type PID Tag Message
04-08 18:22:28.908 nexus_api_27 Error 4058 DEBUG Abort message: ‘* Assertion at /Users/builder/jenkins/workspace/xamarin-android-d16-0/xamarin-android/external/mono/mono/mini/debugger-agent.c:4407, condition is_ok (error)' not met, function:set_set_notification_for_wait_completion_flag, <strong>Could not execute the method because the containing type 'System.Runtime.CompilerServices.AsyncTaskMethodBuilder
1[System.Collections.Generic.IEnumerable`1[T_REF]]’, is not fully instantiated. assembly: type: member:(null)
The nasty part was that when you step through the code in the debugger the application would just crash under your fingers and you could not step through the code that was causing this. And this message is useless as well since it does not show where things go wrong. Only stepping through the debugger revealed a part of the code where the debugger would exit without any message and the app crashed as well.
You can see at various placed more developers experience this issue. e.g.:
https://github.com/xamarin/xamarin-macios/issues/4380
The code that was causing the crash looked as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public override async Task<IEnumerable<Session>> GetItemsAsync(bool forceRefresh = false) { await InitializeStore().ConfigureAwait (false); if (forceRefresh) { await PullLatestAsync().ConfigureAwait(false); } var sessions = await Table.OrderBy(s => s.StartTime).ToListAsync().ConfigureAwait(false); await AnnotateFavorites(sessions).ConfigureAwait(false); var dataShare = Locator.Get<IPlatformSpecificDataHandler<Session>>(); if (dataShare != null) { dataShare.UpdateMultipleEntities(sessions).IgnoreResultBackgroundThread(); } return sessions; } |
The issue lies in the method calls that have await, but don’t expect a result.
The signatures of the methods InitializeStore(), PullLatestAsync() and AnnotateFavorites() all returned a Task, but not a Task<T>. This results in the fact that the method call is more or less fire and forget method and you don’t really have to wait for the result to be returned.
It is important that you change the method signatures to e.g. return a Task<bool> where the boolean is only signaling success or failure of the method call.
I was able to rewrite those methods to all return a boolean value and this resolved the issue of the method exiting without any results.
You can find more on best practices of using async and await here: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx
Hope this helps you resolve this issue as well.
One of the challenges with ASP.NET in combination with containers, is the fact that you configure all your settings in the web.config. when using containers, we want to provide different settings for different environments we run our containers. E.g. you have a dev, test, acceptance and production environment, for which you want other connection strings and appsettings for your application.
Containers bring us the concept of immutability, meaning that once we bake our container, it is fixed. This implies that when we want to change settings in the web config per environment we are more or less stuck.
In ASP.NET 4.7.1 Microsoft added some awesome new capabilities to override your web.config settings using other mechanisms like environment variables.
The way this works is that you can now add configuration builders to your web.config file. You can build your own configuration builders, or use some of the pre-cooked configuration builders that Microsoft provides. One of them is particularly handy, since it helps us to override values in the web.config based on environment variables. And that exactly matches what we need to run in containers!
Let me show you how to make this work for an legacy application we all know and love: The MVC Music Store.
First of all you need to set your target framework to .NET framework 4.7.1. or higher.
If you don’t find this target in your dropdown, you can install the developer packages here and install them, so they show up in Visual Studio.
In your web.config file you can now add a new configuration section handler, that will enable you to add attributes to various sections where you want to have an override of the configuration.
Here is the way you add configuration builders to your config:
1 2 3 4 5 6 7 8 9 |
<configuration> <configSections> <section name="configBuilders" type="System.Configuration.ConfigurationBuildersSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false" /> </configSections> </configuration> |
After we added the configuration section, we can now specify which configuration builders we want to use. You can build your own, but you can also use the one provided by Microsoft. they have a couple of them, I am using the one to use environment variables.
1 2 3 4 5 6 7 8 9 10 |
<configuration> <configBuilders> <builders> <add name="Environment" type="Microsoft.Configuration.ConfigurationBuilders.EnvironmentConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Environment, Version=1.0.0.0, Culture=neutral" /> </builders> </configBuilders> </configuration> |
Before this will work, you need to ad two nuget packages to your application, otherwise it is not able to find the assemblies mentioned in the config file.
You need the following packages:
Microsoft.Configuration.ConfigurationBuilders.Base is the infrastructure to intercept any calls to web.config to read configuration and it provides the option to have a configuration builder override the values in the current file.
Microsoft.Configuration.Configurationbuilders.Environment is the implementation to read from environment variables and override specific sections of the web.config file. The sections supported at the momen are: Connectionstrings, where you can replace the connectionstring value (not the providerName!) and the appsettings section in your config file.
The way to let a part of the configuration to be overridden is by adding an attribute to the section. For appsettings this looks as follows:
1 2 3 4 5 |
<appSettings configBuilders="Environment"> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <add key="ApplicationInsightsKey" value="<yourkeyhere>" /> </appSettings> |
For your connection string it looks like follows:
1 2 3 4 5 6 7 8 9 |
<connectionStrings configBuilders="Environment"> <clear /> <add name="MusicStoreEntities" connectionString="Data Source=azuresqldbname.database.windows.net;Initial catalog=musicstore;user id=MusicStoreLogin;password=<secret>" providerName="System.Data.SqlClient" /> <add name="LocalSqlServer" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|ASPNETDB.MDF;Integrated Security=True;Connect Timeout=30" providerName="System.Data.SqlServerCe.4.0" /> </connectionStrings> |
You see in both sections we added an attribute that tells the configuration builder, which configuration builder to use to override the values. You can use multiple configuration builders that you configure for different sections. One builder is used per section.
The syntaxt to override your app settings is quite straight forward. You can set an environment variable with the name of the app setting and provide it a value. E.g. overriding your ApplicationInsightsKey would be done by setting an environment variable with the name ApplicationInsightsKey and give it a new value.
For connection strings you also provide the name of the connection string and the value will then override the current connectionstring attribute. Overriding the connection string for MusicStoreEntities you provide an environment variable with the name MusicStoreEntities and give it the value of the connectionstring you want to use.
1 |
set MusicStoreEntities = “newconnectionstring” |
At the moment there is no solution yet for more complex settings, but you can build your own configuration builder to take care of this. How to build a configuration builder is described here:Writing a configuration builder
If you have build your container with a docker file, you can now very easily override your settings from the commandline.
I have created a docker image you can pull from docker hub to show you that it works. If you just pull the image : marcelv/mvcmusicstore-configbuilder and you provide it a connectionstring for a database you want to connect to it will show you the mvc musicstore using configuration builders.
You can run it as follows:
1 |
docker run –d –p 808:80 -e MusicStoreEntities=<yourconnectionstring> marcelv/mvcmusicstore-configbuilder |
If you don’t have a database available, just use an docker container for that.
To start a sql server to be used with the music store, use the image : microsoft/mssql-server-windows-developer
To make this work together (without creating a compose file), first start your SQL server eg. like follows:
1 |
docker run -d -p 1433:1433 -e sa_password=mycoolPassword123!@# -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer |
This will return you an id for the container that runs.
Now run the command:
1 |
docker ps |
Now the id you find for the sql server is what you can use as the host name of the sql server in the connectionstring.
Let’s assume it returned the number : 8bf45f8935c6
Now you can start the mvc music store container as follows:
1 |
docker run -d -p:80:80 -e MusicStoreEntities="Data Source=8bf45f8935c6;Initial catalog=mvcmusicstore;user id=sa;password=mycoolPassword123!@#" marcelv/mvcmusicstore-configbuilder |
Now you can browse to localhost with your browser of choice and you should see the MVC music store there.
(assuming you are on docker for windows 17.12.0-ce or higher, otherwise you need to browse to the ip address of the container. You can get this info by either running ipconfig in your container with docker exec command or by using the docker inspect command on the container id)
By using the new configuration builders you can override the values you normally have in your web.config file. This enables us to use containers in a very simple way with our classic ASP.NET applications. No need to move your site to .NET core, just to get environment variable support for your configuration. This should enable you to leverage the immutability of containers even for your existing classic ASP.NET applications!
In this new course, I teach you how to use Docker to deliver solutions to the Windows platform. First, you’ll explore the options and capabilities Docker offers on the Windows platform. Next, you’ll delve into how Visual Studio 2017 simplifies the use of Docker in the development cycle. Finally, you’ll learn how to implement a delivery pipeline with Visual Studio Team Services (VSTST) or TFS to deploy to any of the target platforms, ranging from single windows server to a cluster of machines managed by cluster managers like Kubernetes or Service Fabric. By the end of this course, you’ll be able to explain how containers work on windows, how to build Docker containers to run new or existing workloads, and how to deploy your applications to different container hosting solutions on premise or in the cloud.
Here is a brief video introduction that gives you an idea of the course.
Here is the outline of the course:
Module 1: Introduction to Docker on Windows with Visual Studio 2017
Module 2: Docker and Visual Studio
Module 3: Handling Data in Containers & Testing
Module 4: Docker and Your Continuous Delivery Pipeline in VSTS
Module 5: Deploying to Azure Container Services (ACS)
Module 6: Deploying to Azure Service Fabric
You can find the course here at the PluralSight website: https://app.pluralsight.com/library/courses/docker-visual-studio-2017-windows
Not yet a PluralSight subscriber? No worries, you can still watch the course for free with a trial subscription.
Hope it helps to get you up to speed with Docker on Windows!
Last week I presented a session at Techorama in Belgium with the title “Architecting systems for continuous delivery”. It was a fully packed room and was great to do.
I got multiple requests to share the slides, so here goes
Enjoy !
Last week I visited Docker con 2017 where Docker announced a whole lot of new features, under which a new feature in the docker build command, called multi staged builds.
These multi staged builds are extremely convenient to create images that are of minimum size. I am mostly using Docker on Windows, but this feature works on any version of Docker. When using Windows images, you might have noticed they are pretty large in size. Making your image as small as possible makes a big difference. So I will show you, based on the example I have used multiple times, how to create an optimized image to run an existing ASP.NET MVC 4.x on Windows Server Core.
When you create a new docker image that is part of a container composition that you want to run on one and the same host, you can run into the issue that the independent containers are not able to reach each other via DNS resolving.
So lets assume you have the following compose file where you want the web tier to be able to reach the database tier given the following compose file:
The past few days I worked quite a lot with docker-compose on my windows machine and after something strange happened to my machine that crashed it, I was not able to start any containers anymore that had connectivity over the network with each other.
Every time I used the command-line docker-compose up, I would get a message telling me it failed to start the container. the full message I got was:
“ERROR: for web Cannot start service web: failed to create endpoint aspnetblogapplication_web_1 on network nat: HNS failed with error : Unspecified error”
Recently Microsoft added the capability to CodedUI to test on the Edge browser. For this they extended the cross browser playback capability. This uses Selenium under the hood. So the steps to make this work are as follows:
And finally in the code you need to switch the browser you want to launch. You need to provide the following name to start edge:”MicrosoftEdge”
BrowserWindow.CurrentBrowser = “MicrosoftEdge”;
1 |
var browserWindow = <br> BrowserWindow.Launch(new Uri("<your URl here>")); |
And that is it!
Happy testing on Edge
If you attended one of my sessions, I hope you enjoyed them. I had a great time.
For your reference you can find the PDF’s here and the accompanying demo code.
Continuous delivery on azure: A/B testing, Canary releasing and Dark launching
If you are more interested in Continuous delivery, you also might like my just published course at Pluralsight called “Building a Continuous Delivery Pipeline with TFS and Visual Studio 2015” which you can find here: https://www.pluralsight.com/courses/tfs-visual-studio-2015-implementing-continuous-delivery
My second session was on Micro Services and you can find the PDF here:
VSH11 Exploring Microservices in a Microsoft Landscape
And the final session was on building maintainable cross browser UI tests with either selenium or codedUI. The PDF can be found here:
VSH16 Writing Maintainable X-Browser Automated Tests
and you can find the demo’s here: Search google
Also if you want to learn more about CodedUI, you can also watch one of my two courses I build for Pluralsight here:Test Automation with CodedUI Pluralsight which explains in detail all that can be done with CodedUI and Testing Web Applications with CodedUI Pluralsight which is focused on testing web applications.
if you don’t have a subscription yet, you can watch it for free with the free trial
Hope you enjoyed it, if you have comments or feedback let me know!
Cheers,
Marcel
© 2023 Fluentbytes
Theme by Anders Noren — Up ↑