Invoking browsers with Baseclass.Contrib.Specflow in C# using Browser.Current - c#

I'm currently trying to use Selenium Grid 2 to run automation tests on multiple browsers. During my research I came across using Baseclass.Contrib.Specflow which enables me to use the browsers as tags in the feature files without having to declare it in my main driver class. The problem I have is that one of the blogs I read had the following as the set up code
[SetUp]
public void Test_Setup(){
CurrentDriver = Browser.Current;}
My app config file looks contains the following:
<components>
<!-- <component name="Firefox" type="OpenQA.Selenium.Firefox.FirefoxDriver, WebDriver" service="OpenQA.Selenium.IWebDriver, WebDriver" instance-scope="per-dependency">
</component>-->
<component name="Firefox"
type="Baseclass.Contrib.SpecFlow.Selenium.NUnit.RemoteWebDriver, Baseclass.Contrib.SpecFlow.Selenium.NUnit.SpecFlowPlugin"
service="OpenQA.Selenium.IWebDriver, WebDriver"
instance-scope="per-dependency">
<parameters>
<parameter name="url" value=" http://localhost/wd/hub" />
<parameter name="browser" value="Firefox" />
</parameters>
</component>
<component name="Safari" type="Baseclass.Contrib.SpecFlow.Selenium.NUnit.RemoteWebDriver, Baseclass.Contrib.SpecFlow.Selenium.NUnit.SpecFlowPlugin" service="OpenQA.Selenium.IWebDriver, WebDriver" instance-scope="per-dependency">
<parameters>
<parameter name="url" value=" http://localhost/wd/hub" />
<parameter name="desiredCapabilities" value="Chrome" />
</parameters>
</component>
I get an error when I try to run the script using the above Setup method.
Error:
System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary
The blog I got this solution from doesn't seem to answer questions regarding to this so I'm a bit desperate. This will basically allow me to to the following on the feature file and get tests to run based on the tag
#Browser:Firefox
#Browser:Chrome
Hope this is enough information to give me advice.

The mistake you are making here is that you are annotating your entire feature file with the tag #Browser.
Baseclass.Contrib.Specflow allows you to annotate scenarios with scenario supporting Browsers. Therefore, you have to annotate each scenario.
If you don't do that, there is no Current Browser set for that test and trying to access Browser.Current will throw System.Collections.Generic.KeyNotFoundException.
You know you're doing it right when the generated Unit Tests will include the Browser name as part of the unit test name like
<Test Name> on <Browser> with: <parameters>
Example:
#Browser:IE
#Browser:Chrome
#Browser:Firefox
Scenario Outline: Add Two Numbers
>Given I navigated to / using
And I have entered <summandOne> into summandOne calculator
And I have entered <summandTwo> into summandTwo calculator
When I press add
Then the result should be <result> on the screen
Scenarios:
| summandOne| summandTwo|result|
| 10 | 20 | 30 |
| 3 | 4 | 7 |

Related

Is it possible to configure a .net runsettings file to include complex objects?

I'm looking at implementing a runsettings file for automated testing. Thing is, my variables are complex objects, and all I can find in the documentation about runsettings has simple key/value options, like so.
<TestRunParameters>
<Parameter name="webAppUrl" value="http://localhost" />
<Parameter name="docsUrl" value="https://learn.microsoft.com" />
</TestRunParameters>
I'm wondering if it's possible to specify a complex object like you might specify below (especially since TextContext.Properties returns an object, so I assume it's polymorphic in some sense?) and cast it to a given defined class
<TestRunParameters>
<Parameter name="AdminUser" UserID="Admin" Password="P#55w0rd!" />
<Parameter name="User" UserID="User" Password="P#55w0rd!" />
</TestRunParameters>
I realize I can do the below and manually create my object instances, but I'd really really like to avoid it if at all possible
<TestRunParameters>
<Parameter name="AdminUserID" value="Admin"/>
<Parameter name="AdminUserPW" value="P#55w0rd!" />
<Parameter name="UserID" value="User"/>
<Parameter name="UserPW" value="P#55w0rd!" />
</TestRunParameters>

dotnet test runsettings passing testrun parameters with multiple values at runtime

I need to pass multiple values like browser type, headless mode, device name at runtime via command line.
Attached the run settings file below. In command line, I need to modify these browser values, headless mode and device name at run time
<?xml version="1.0" encoding="UTF-8" ?>
<RunSettings>
<!-- configuration elements -->
<TestRunParameters>
<Parameter name="Browser" value="Chrome" />
<Parameter name="Headless" value="True" />
<Parameter name="Mobile" value=iPhone 6" />
</TestRunParameters>
</RunSettings>
dotnet test --filter TestCategory=Components Traffk.eApp.Web.Tests.csproj -s config.runsettings -- TestRunParameters.Parameter(name=\"Browser\",\ value=\"Chrome\")
How to pass the other values here in the above command.

How to set a parameter value based on the app settings key value inside a web.config

I have the following code inside a web.config and I'd like some way of setting the Parameter "NoHeader" to the value of the app settings key "ShowHeader" such that the former would be set to true. The best guess I have is that I use code to read the value from the ConfigurationManager and somehow write it back to NoHeader but I don't know how to do that if that's the case.
<Telerik.Reporting>
<Extensions>
<Render>
<Extension name="CSV">
<Parameters>
<Parameter name="NoHeader" value="false" />
</Parameters>
</Extension>
</Render>
</Extensions>
</Telerik.Reporting>
<appSettings>
<add key="ShowHeader" value="true" />
</appSettings>
We use a method that changes the showHeader key on deployment, but I'm not able to modify the NoHeader portion directly. I'm using C# for my code, any clues would be appreciated.

Weird NLog behavior across threads with MDLC and NDLC

I'm trying to setup a CorrelationID across threads to establish a link between calls to my server, and the corresponding calls that I make to external web services. The correlation ID is a GUID which I'm saving in Logical Context structures of NLog (logical contexts work fine across threads, supposedly).
The idea is to have a GUID that is shared between any request to my server, and the corresponding requests that I issue to various web services due to this request. I tried using both MDLC and NDLC.
The problem is that the value is getting stored correctly only for the first request, and it's saving blank values for all subsequent ones, even though a GUID is correctly generated for each new request to my server.
I tried logging either to a database or in a file. The problem seems to solve itself if I add a breakpoint within the code, or if I add a System.Threading.Sleep anywhere around the logging method. What's also weird is that I can add the Sleep either before or after the method that sets the value in the logical context, and it still works either way. Removing the Sleep/breakpoint would cause it to break again.
I am using NLog v4.5.2.
Logging module:
using System;
using System.Web;
using NLog;
namespace Shift.Stardust.Engine.Modules
{
public class LoggingHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += HandleBeginRequest;
}
public void Dispose()
{
}
private void HandleBeginRequest(object sender, EventArgs e)
{
System.Threading.Thread.Sleep(500);
var guid = Guid.NewGuid().ToString();
NestedDiagnosticsLogicalContext.Push(guid);
}
}
}
Placing a breakpoint anywhere in HandleBeginRequest produces correct output. Similarly for adding System.Threading.Thread.Sleep(500). Naturally, I wouldn't want to add such a line in my code just to resolve this issue.
NLog config:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" internalLogFile="c:\temp\nlog-internal.txt" internalLogLevel="Trace">
<variable name="logDirectory" value="${basedir}/logs"/>
<targets>
<target name="asyncdatabase"
xsi:type="AsyncWrapper"
queueLimit="5000"
overflowAction="Block">
<target xsi:type="Database"
connectionStringName="ConnectionStringHere"
keepConnection="true">
<commandText>[db].[P_Log_Insert] #CreateDate, #ApplicationName, #MachineName, #LoggerName, #LogLevel, #Message, #Exception, NULL, #EngineSessionId, #CorrelationId</commandText>
<parameter name="#CreateDate" layout="${date}"/>
<parameter name="#ApplicationName" layout="${appsetting:name=Shift.Stardust.ApplicationName}"/>
<parameter name="#MachineName" layout="${machinename}"/>
<parameter name="#LoggerName" layout="${logger}"/>
<parameter name="#LogLevel" layout="${level}"/>
<parameter name="#Message" layout="${message}"/>
<parameter name="#Exception" layout="${exception:format=tostring}"/>
<parameter name="#EngineSessionId" layout="${aspnet-sessionid}"/>
<parameter name="#CorrelationId" layout="${ndlc}"/>
</target>
</target>
</targets>
<rules>
<logger name="Http.*" minlevel="Info" writeTo="asyncdatabase" final="true" />
</rules>
</nlog>
I expect to have a different CorrelationID for each incoming request, but this is only true for the first one. All of the subsequent ones have an empty string as value.
I think it's better to write to the HTTP context for this case.
e.g.
HttpContext.Current.Items["myvariable"] = 123;
and usage:
${aspnet-item:variable=myvariable} - produces "123"
See docs
You need the package NLog.Web (ASP.NET non-core) for that.
Note: ASP.NET Core uses should use NLog.Web.AspNetCore instead of NLog.Web

Resharper External Attributes with MSTest's [DeploymentItem]

In certain cases (like when writing URIs in XAML), ReSharper magically figures out I am writing out a relative path to a file in the current project and offers very useful smart-completion for it, and a warning if I misspell something and get it wrong, and even goes to the file if I ctrl+click it.
Can I somehow tell ReSharper to do the same when I'm typing in the parameter to MSTest's DeploymentItem attribute?
This should work through an external annotation. Open the following file:
C:\Program Files (x86)\JetBrains\ReSharper\v7.1\Bin\ExternalAnnotations\Visual Studio\Microsoft.VisualStudio.QualityTools.UnitTestFramework.xml
(Or whatever version of Resharper you're using.)
Add these lines inside the assembly tag:
<member name="M:Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute.#ctor(System.String)">
<parameter name="path">
<attribute ctor="M:JetBrains.Annotations.PathReferenceAttribute.#ctor" />
</parameter>
</member>
<member name="M:Microsoft.VisualStudio.TestTools.UnitTesting.DeploymentItemAttribute.#ctor(System.String,System.String)">
<parameter name="path">
<attribute ctor="M:JetBrains.Annotations.PathReferenceAttribute.#ctor" />
</parameter>
</member>
That tells Resharper to throw the PathReference attribute on the path parameter of both constructors of DeploymentItem.
However, after testing for some time now I cannot see this attribute working on anything that I try within the C# text editor. It could be that it doesn't work for my version (7.1), but I'm a bit stumped. Perhaps someone can add to this?

Categories

Resources