TestStack / TestStack.Seleno

Seleno helps you write automated UI tests in the right way by implementing Page Objects and Page Components and by reading from and writing to web pages using strongly typed view models.
http://teststack.github.com/TestStack.Seleno/
MIT License
180 stars 60 forks source link

Seleno - TypeInitializationException #218

Open fletchcodes opened 9 years ago

fletchcodes commented 9 years ago

Hello All, I've run across an odd exception in working with TestStack.Seleno. Full disclosure, this is my first real run using the utility. I'm working on a functional acceptance test using Seleno, and the application configuration in SelenoHost.Run() is failing with a System.TypeInitializationException, not the DirectoryNotFound exception I'm expecting.

Before I get too far ahead of myself. I'm using Seleno in an xUnit.NET test project targeting .Net 4.5, and using the latest releases of Seleno, the Selenium helper libraries, and xUnit.NET from NuGet.

Here's the host configuration, it's essentially borrowed from the getting started documentation.

public static class Host
    {
        public static readonly SelenoHost Instance = new SelenoHost();

        static Host()
        {
            Instance.Run("GroundControl.Mvc.AcceptanceTests", 12346, c => c
                .WithRouteConfig(RouteConfig.RegisterRoutes)
                );
       }
}

I call Host() from a NavigateToInitialPage() call, shown below

var experimentIndex = Host.Instance
                .NavigateToInitialPage<ExperimentIndexPage>();

And receive the following exception

System.TypeInitializationException was unhandled by user code HResult=-2146233036 Message=The type initializer for 'GroundControl.Mvc.AcceptanceTests.Host' threw an exception. Source=GroundControl.Mvc.AcceptanceTests TypeName=GroundControl.Mvc.AcceptanceTests.Host StackTrace: at GroundControl.Mvc.AcceptanceTests.UserCreatesSimpleExperiment.ShouldCreateExperimentAndShowStatus() in C:\Users\Steven\Workbench\BCSL Ground Control Service\Tests\GroundControl.Mvc.AcceptanceTests\UserCreatesSimpleExperiment.cs:line 23 InnerException: HResult=-2147467261 Message=Object reference not set to an instance of an object. Source=TestStack.Seleno StackTrace: at TestStack.Seleno.Configuration.WebServers.ProjectLocation.GetSolutionFolderPath() in c:\ConsoleBuildAgent\work\6625a30e8ee728ba\src\TestStack.Seleno\Configuration\WebServers\ProjectLocation.cs:line 42 at TestStack.Seleno.Configuration.WebServers.ProjectLocation.FromFolder(String webProjectFolderName) in c:\ConsoleBuildAgent\work\6625a30e8ee728ba\src\TestStack.Seleno\Configuration\WebServers\ProjectLocation.cs:line 33 at TestStack.Seleno.Configuration.SelenoHost.Run(String webProjectFolder, Int32 portNumber, Action`1 configure) in c:\ConsoleBuildAgent\work\6625a30e8ee728ba\src\TestStack.Seleno\Configuration\SelenoHost.cs:line 51 at GroundControl.Mvc.AcceptanceTests.Host..cctor() in C:\Users\Steven\Workbench\BCSL Ground Control Service\Tests\GroundControl.Mvc.AcceptanceTests\Host.cs:line 12 InnerException:

I'm a bit at a loss for how to resolve this issue, or even really where the problem is. Any help you can offer would be appreciated.

Thanks,

robdmoore commented 9 years ago

I think there is two things happening here.

First one is some poor error handling in Seleno that bubbles up a null reference exception when it fails to find a website to spin up in IIS Express. We should out in a fix for that (although feel free to submit a PR for it yourself too :)). Based on the stack trace its on line 42 of ProjectLocation.cs.

The second problem is I suspect you are putting the wrong project name in your host configuration, you had:

Instance.Run("GroundControl.Mvc.AcceptanceTests", ...)

That doesn't look like the name of a web project to me?

fletchcodes commented 9 years ago

Rob,

Thanks for getting back so quickly.

Yes, I'm using an intentionally bad project name to throw the expected DirectoryNotFound exception. I was getting the same error using the web project in my solution: GroundControl.Mvc.

The solution is laid out as shown below:

Service\
     GroundControl.sln
     GroundControl.Mvc\

When calling the run method, I used this host configuration

 public static class Host
    {
        public static readonly SelenoHost Instance = new SelenoHost();

        static Host()
        {
            Instance.Run("GroundControl.Mvc", 12346, c => c
                .WithRouteConfig(RouteConfig.RegisterRoutes)
                );

        }
    }

I'm experiencing, essentially, the same System.TypeInitializationException here. My assumption is that I'm pointing Seleno at the wrong directory, but shouldn't I be getting the DirectoryNotFound exception, rather than the stacktrace I provided earlier?

Thank you so much for the help.

fletchcodes commented 9 years ago

Rob,

I'm doing some digging on my own, and forcing creation of the web application using the instructions TestStack provides here: http://seleno.teststack.net/docs/configuring-the-web-application. This forces the directory location before acting on .Run().

I'm finding a null reference exception here, and I believe it's triggering in the GetSolutionFolderPath method in ProjectLocation.cs.

private static string GetSolutionFolderPath() 
39         { 
40             var directory = new DirectoryInfo(Environment.CurrentDirectory); 
41 

42             while (directory.GetFiles("*.sln").Length == 0) 
43             { 
44                 directory = directory.Parent; 
45             } 
46             return directory.FullName; 
47         } 

This path doesn't return a DirectoryNotFound exception, so it would make sense to get a null reference exception here.

The previous question, I guess, still stands. If the solution is laid out in a fairly typical way, what is causing Seleno to throw an exception?

fletchcodes commented 9 years ago

Rob,

Figured it out. It turns out, my solution structure broke the method used to locate the solution directory. If you have a solution structured like:

Service
     MySolution.sln
     MyWebProject
Test
     MyTestProject

And you run SelenoHost.Run() from inside the TestProject, it will iterate backward up through parent directories until the directory.Parent variable is null..

To fix this, move the solution file to

MySolution.sln
     Service\
      Test\

After doing that, Seleno is functioning as expected. Consider this issue resolved.

robdmoore commented 9 years ago

Cool. Thanks for reporting back.

I'll leave the issue open so we can make the error a bit more obvious

robdmoore commented 9 years ago

(Again - if you have time feel free to submit a PR for it :))