Sunday, March 6, 2016

In this post I will try to demonstrate how you can set-up a starting point to use Selenium in Visual Studio 2015 and IISExpress to perform UI tests for different JavaScript and Testing frameworks.


1. Get Selenium IE Driver Server

To start you need to download the IE Driver Server from here
Which is going to have a .exe file which is an application that will run & drive IE. Let's assume we put the exe file in 'C:\Temp'

2. Create an ASP.NET project in VS2015. 

I usually remove the Authentication (Select no Authentication) and also ask VS to create a test project. I called my project Sandbox and the test project is Sandbox.Tests. 

3. Add References using NuGet

Open the Nuget manager and add Selenium.WebDriver and NUnit packages to your Sandbox.Tests project. 

4. Set the project to publish after each build. 

To do so you can add the following to your .csproj file. By default this 'Target' element is commented out 

 <Target Name="AfterBuild"> 
<CallTarget Targets="Publish" /> 
</Target> 
<Target Name="Publish"> <RemoveDir Directories="$(SolutionDir)Sandbox\obj\publish\" ContinueOnError="true" /> 
<MSBuild Projects="Sandbox.csproj" Targets="ResolveReferences;_CopyWebApplication" Properties="WebProjectOutputDir=$(SolutionDir)Sandbox\obj\publish\;OutDir=$(SolutionDir)Sandbox\obj\publish\bin\" /> 
</Target>

5. Ensure Roslyn is copied to output

I faced a problem where CSC was not found by IIS Express to use. If the MS Build does not copy the Roslyn directory to Sandbox\obj\publish\bin\roslyn and browsing to your site in IIS results in an error saying CSC was not found,then you can fix this by adding this post-build step to your project file

    <PropertyGroup> 
     <PostBuildEvent> 
       if not exist "$(WebProjectOutputDir)\bin\Roslyn" md "$(WebProjectOutputDir)\bin\Roslyn" 
       start /MIN xcopy /s /y /R "$(OutDir)\roslyn\*.*" "$(WebProjectOutputDir)\bin\Roslyn" 
     </PostBuildEvent> 
   </PropertyGroup> 

this is added just before 'Project' tag close. 

6. Have IIS Express run before your tests start. 

That is an easy thing to do with a class like this. The important bit where new Process object is created and the path to IISExpress is passed to it and Start() method is called. 


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Sandbox.Tests.IISEAutomation
{
    public static class IISExpressRunner

    {
        private static Process _iisProcess;
        public static void StartIis()
        {
            if (_iisProcess == null) { var thread = new Thread(StartIisExpress) { IsBackground = true }; thread.Start(); }
        }
        private static void StartIisExpress()
        {
            var startInfo = new ProcessStartInfo
            {
                WindowStyle = ProcessWindowStyle.Normal,
                ErrorDialog = true,
                LoadUserProfile = true,
                CreateNoWindow = false,
                UseShellExecute = false,

                Arguments = string.Format("/path:\"{0}\" /port:{1}", @"C:\Users\Administrator\Documents\Visual Studio 2015\Projects\Playground\Sandbox\obj\publish", "65001")
            };

            var programfiles = string.IsNullOrEmpty(startInfo.EnvironmentVariables["programfiles"]) ? startInfo.EnvironmentVariables["programfiles(x86)"] : startInfo.EnvironmentVariables["programfiles"];

            startInfo.FileName = programfiles + "\\IIS Express\\iisexpress.exe";
            try
            {
                _iisProcess = new Process { StartInfo = startInfo }; _iisProcess.Start(); _iisProcess.WaitForExit();
            }
            catch(System.Exception ex)
            {
                _iisProcess.CloseMainWindow(); _iisProcess.Dispose();
            }
        }
        public static void StopIis()
        {
            if (_iisProcess != null) { _iisProcess.CloseMainWindow(); _iisProcess.Dispose(); }
        }
    }
}


7. Start/Stop IIS Express as part of testing (MSTest)

Now you can use the above class to control your IIS Express. For MSTest you can use [AssemblyInit] attribute

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.IE;

namespace Sandbox.Tests.CodedUI
{
    [TestClass]
    public class HomePageMSTest
    {
        [AssemblyInitialize]
        public static void AssemblyInit(TestContext context)
        {
            IISEAutomation.IISExpressRunner.StartIis();
        }
        [AssemblyCleanup]
        public static void AssemblyCleanup()
        {
            IISEAutomation.IISExpressRunner.StopIis();
        }


8. Start/Stop IIS Express (NUnit)

for NUnit you use [TextFixture] attribute. The following class is stopping and starting IIS using our helper class

using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sandbox.Tests.CodedUI
{

    [SetUpFixture]
    public class NUnitSetupFixture
    {
        [SetUp]
        public void RunBeforeAnyTests()
        {
            IISEAutomation.IISExpressRunner.StartIis();
        }

        [TearDown]
        public void RunAfterAnyTests()
        {
            IISEAutomation.IISExpressRunner.StopIis();
        }
    }
}

9. Add Awesome-font 

Use NuGet manager to add Awesome-font reference. the  '~/Content/css' bundle will include that automatically to your page. 
to test you can put this to see the icon is coming up correctly
    <i class="fa fa-refresh fa-spin"></i>


10. Add RequireJS to your project

Here is a good read how you you can set up RequireJS with MVC.
http://volaresystems.com/blog/post/2014/05/27/Adding-RequireJS-to-an-ASPNET-MVC-project

The summary is that you add require to your bundle.

Homepage
Homepage