Configuring Specflow+XUnit Tests to run on multiple environments - c#

I have to migrate my existing tests from Specflow+Runner to Specflow+xUnit and for the same I'have been stuck on converting the .runsettings and .srprofile files so that they can be used with Specflow+xUnit.
Has anyone done this conversion or can help me with this ?
Existing .runsettings file :
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Configurations for SpecRun -->
<SpecRun>
<Profile>DEV.srprofile</Profile>
<!-- SpecRun uses VisualStudo.srprofile or TFS.srprofile by default, or the Default.srprofile if these don't exist.
<Profile>MyProfile.srprofile</Profile> -->
<!-- SpecRun generates a report file based on the project name and the current timestamp by default.
<ReportFile>CustomReport.html</ReportFile>-->
<GenerateSpecRunTrait>false</GenerateSpecRunTrait> <!-- Set this to "true" to generate a "SpecRun" trait for all tests discovered by SpecRun (useful when the solution contains other tests too) -->
<GenerateFeatureTrait>false</GenerateFeatureTrait> <!-- Set this to "true" to generate a feature trait for all scenarios (othervise the feature goruping can be used as "class") -->
</SpecRun>
</RunSettings>
Existing .srprofile file :
<?xml version="1.0" encoding="utf-8"?>
<TestProfile xmlns="http://www.specflow.org/schemas/plus/TestProfile/1.5">
<Settings projectName="example" />
<Execution stopAfterFailures="3" testThreadCount="1" testSchedulingMode="Sequential" />
<!-- For collecting by a SpecRun server update and enable the following element. For using the
collected statistics, set testSchedulingMode="Adaptive" attribute on the <Execution> element.
<Server serverUrl="http://specrunserver:6365" publishResults="true" />
-->
<TestAssemblyPaths>
<TestAssemblyPath>example.dll</TestAssemblyPath>
</TestAssemblyPaths>
<DeploymentTransformation>
<Steps>
<ConfigFileTransformation configFile="App.config">
<Transformation>
<![CDATA[<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="baseUrl" value="<sample URL>" xdt:Locator="Match(key)" xdt:Transform="SetAttributes" />
<add key="shortWait" value="15" xdt:Locator="Match(key)" xdt:Transform="SetAttributes" />
<add key="longWait" value="25" xdt:Locator="Match(key)" xdt:Transform="SetAttributes" />
</appSettings>
</configuration>
]]>
</Transformation>
</ConfigFileTransformation>
</Steps>
</DeploymentTransformation>
</TestProfile>

Related

Multiple level web.config transform

Is there any way to apply a web.config transform on more than one level? E.g:
web.config
- web.release.config
- web.prod1.config
- web.prod2.config
When targeting prod1, I would like to do a 3 way merge web.config < web.release.config < web.prod1.config. Is this possible?
There is a way to accomplish this. As you don't specify too much, I'm not sure this will satisfy your requirements though. The following is how it could be accomplished from scratch, but you could just pull the bits that you need directly into the csproj you already have.
Create a .csproj file:
Transform.csproj
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="Web.config" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Prod.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll"/>
<Target Name="TransformRelease">
<TransformXml Source="Web.config"
Transform="Web.Release.config"
Destination="Web.New.config"/>
</Target>
<Target Name="TransformProd">
<TransformXml Source="Web.New.config"
Transform="Web.Prod.config"
Destination="Web.New.config"/>
</Target>
</Project>
Then you can execute your two transforms through invoking an msbuild command from the command line. I used the following powershell commands.
.\msbuild.exe "PATH_TO_YOUR_CSPROJ\Transform.csproj" /t:TransformRelease
.\msbuild.exe "PATH_TO_YOUR_CSPROJ\Transform.csproj" /t:TransformProd
This will transform your web.config using the transforms in the web.release.config and create a new file with the result of that transform web.new.config. Then the second command will transform the web.new.config using the transforms in web.prod.config and update the web.new.config with that transformed value.
Web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="web" value="web" />
<add key="release" value="web" />
<add key="prod" value="web" />
<add key="release:prod" value="web" />
</appSettings>
</configuration>
Web.Release.config
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="release" value="release" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
<add key="release:prod" value="release" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
</configuration>
Web.Prod.config
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="prod" value="prod" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
<add key="release:prod" value="prod" xdt:Transform="SetAttributes" xdt:Locator="Match(key)" />
</appSettings>
</configuration>
Running the above commands produced Web.New.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="web" value="web" />
<add key="release" value="release" />
<add key="prod" value="prod" />
<add key="release:prod" value="prod" />
</appSettings>
</configuration>
UPDATE
While the above works, I wouldn't want to use it in that manner. After tinkering around with the .csproj a bit, I came up with this which will do the transformation for you in the BeforeBuild task.
<Target Name="TransformRelease">
<TransformXml Source="Web.config" Transform="Web.Release.config" Destination="Web.New.config" />
</Target>
<Target Name="TransformProd" Condition="'$(Configuration)' == 'Release'">
<TransformXml Source="Web.New.config" Transform="Web.Prod.config" Destination="Web.New.config" />
</Target>
<Target Name="BeforeBuild">
<MSBuild Projects="WebApplication1.csproj" Targets="TransformRelease;TransformProd"/>
</Target>
With these defined in your .csproj file, when you build the project as is, it will apply the Release transform alone. When you build the project in the Release configuration, it will apply both the Release and Prod transformations. Obviously you will need to tweak it for your needs given prod1, prod2, etc.
Is not possible out of the box with simple commands, but you can do custom transformation and string replacement using build tasks
A while ago I asked a similar questions and I got a really nice answer using build tasks transformation. Instead of copying it here, take a look in the solution and adapt to your needs.:
Service Fabric Default Publish Profile other than Local.xml

MSTest - Running tests using visual studio services (TFS and Continous Integration )

I am following up the below link and setting a CI set up.
https://blogs.msdn.microsoft.com/visualstudioalm/2015/05/29/testing-in-continuous-integration-and-continuous-deployment-workflows/
The issue I am facing here is with respect to the test settings file. The test are running fine locally. But not remotely when running it, I am getting all test failures.
I believe this is because of the spreadsheet ( where the test data resides ) and the test settings file.
My test settings file is below
<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="UITestSettings" id="1623gdcf4-f2af-496f-b65h4-fe25w6c4e49cb" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
<Description>These are default test settings for a remote test run.</Description>
<Deployment>
<DeploymentItem filename="XXX\TestData\LocationData.xls" />
<DeploymentItem filename="XXX\TestData\UITestData.xls" />
</Deployment>
<Execution parallelTestCount="0">
<Timeouts runTimeout="36610000" testTimeout="36610000" />
<TestTypeSpecific>
<UnitTestRunConfig testTypeId="13cdcs9d9-ddb5-4fa4-a97d-d965ccdfc6d4b">
<AssemblyResolution>
<TestDirectory useLoadContext="true" />
</AssemblyResolution>
</UnitTestRunConfig>
<WebTestRunConfiguration testTypeId="4ess7599fa-5ecb-43e9-a887-cd63cfdf72d207">
<Browser name="Internet Explorer 9.0" MaxConnections="6">
<Headers>
<Header name="User-Agent" value="Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)" />
<Header name="Accept" value="*/*" />
<Header name="Accept-Language" value="{{$IEAcceptLanguage}}" />
<Header name="Accept-Encoding" value="GZIP" />
</Headers>
</Browser>
</WebTestRunConfiguration>
</TestTypeSpecific>
<AgentRule name="LocalMachineDefaultRole">
</AgentRule>
</Execution>
<Properties>
<Property name="TestSettingsUIType" value="UnitTest" />
</Properties>
</TestSettings>
All test failed with this error
Data source 'XXX.YYY.aboutThemRecommendationFirstQuarterFlows' cannot be found in the test configuration settings
But I have the settings file in the build steps ( in Run functional Step )
Is there anything I am missing. Any help would be great as I am struggling to find a solutions.
Thanks
According to the error message, it seems that you are referring to a data source named as "XXX.YYY.aboutThemRecommendationFirstQuarterFlows" which does not exist in "App.config" file test configuration settings.
For example, I have a test method use "MyExcelDataSourceTTT" data source:
[TestMethod]
[DataSource("MyExcelDataSourceTTT")]
public void TestMethod1()
{
Assert.AreEqual(TestContext.DataRow["1"].ToString(),"1");
}
But in the App.config file, I only have "MyExcelDataSource" data source. "MyExcelDataSourceTTT" data source does not exist:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="microsoft.visualstudio.testtools" type="Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection, Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
</configSections>
<connectionStrings>
<add name="ExcelConnection" connectionString="Dsn=Excel Files;dbq=.\testdata.xlsx;defaultdir=.; driverid=790;maxbuffersize=2048;pagetimeout=5" providerName="System.Data.Odbc" />
</connectionStrings>
<microsoft.visualstudio.testtools>
<dataSources>
<add name="MyExcelDataSource" connectionString="ExcelConnection" dataTableName="Sheet1$" dataAccessMethod="Sequential"/>
</dataSources>
</microsoft.visualstudio.testtools>
</configuration>
Now, when run the testing, you will get "Data source 'MyExcelDataSourceTTT' cannot be found in the test configuration settings.." error message.

How to use custom configuration file or app.config in .NET application

I have MVC5 .NET 4.6.1 C# web application
I want to create a custom config file separate from web.config to store some settings my application uses.
I tried to follow this article https://support.microsoft.com/en-us/kb/815786
however the items I set in app.config:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
</system.web>
<appSettings>
<add key="Key0" value="0" />
<add key="Key1" value="1" />
<add key="Key2" value="2" />
</appSettings>
</configuration>
are not seen in my application see , eg. they come as null:
string attr = ConfigurationManager.AppSettings["Key0"];
Why isn't it working? Am I missing something?
Alternatively I would like to create a custom config file eg. mycustom.config to define my global app settings.
EDIT
Solution I used
Follwing this post https://social.msdn.microsoft.com/Forums/vstudio/en-US/11e6d326-c32c-46b1-a9a2-1fbef96f33ee/howto-custom-configuration-files?forum=netfxbcl
In web.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="newAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</configSections>
<newAppSettings file="C:\mycustom.config"/>
</configuration>
Then mycustom.config
<?xml version="1.0" encoding="utf-8" ?>
<newAppSettings>
<add key="OurKey" value="OurValue"/>
</newAppSettings>
And reading the value:
System.Collections.Specialized.NameValueCollection newAppSettings = (System.Collections.Specialized.NameValueCollection)System.Configuration.ConfigurationManager.GetSection("newAppSettings");
string key = Convert.ToDateTime(newAppSettings["OurKey"]);
You can use separate config file for connection strings and app settings:
<appSettings configSource="appSettings.config" />
<connectionStrings configSource="connectionStrings.config"/>
appSettings.config file
<?xml version="1.0" encoding="utf-8" ?>
<appSettings>
<add key="Setting1" value="App setting 1" />
</appSettings>
connectionStrings.config file
<?xml version="1.0" encoding="utf-8"?>
<connectionStrings>
<add name="MyConnStr1" connectionString="My connection string" />
</connectionStrings>
Usage is same as it was before:
var setting1 = ConfigurationManager.AppSettings["Setting1"];
var connString1 = ConfigurationManager.ConnectionStrings["MyConnStr1"].ConnectionString;
//Helps to open the Root level web.config file.
Configuration webConfigApp = WebConfigurationManager.OpenWebConfiguration("~");
//Modifying the AppKey from AppValue to AppValue1
webConfigApp.AppSettings.Settings["AppKey"].Value = "AppValue1";
<appSettings>
<add key="AppKey" value="AppValue"/>
</appSettings>

How to use ConfigurationManager.AppSettings with a custom section?

I need to get "http://example.com" from using App.config file.
But at the moment I am using:
string peopleXMLPath = ConfigurationManager.AppSettings["server"];
I cannot get the value.
Could you point out what I am doing wrong?
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configSections>
<section name="device" type="System.Configuration.SingleTagSectionHandler" />
<section name="server" type="System.Configuration.SingleTagSectionHandler" />
</configSections>
<device id="1" description="petras room" location="" mall="" />
<server url="http://example.com" />
</configuration>
I think you need to get the config section, and access that:
var section = ConfigurationManager.GetSection("server") as NameValueCollection;
var value = section["url"];
And you also need to update your config file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<configSections>
<section name="device" type="System.Configuration.NameValueSectionHandler" />
<section name="server" type="System.Configuration.NameValueSectionHandler" />
</configSections>
<device>
<add key="id" value="1" />
<add key="description" value="petras room" />
<add key="location" value="" />
<add key="mall" value="" />
</device>
<server>
<add key="url" value="http://example.com" />
</server>
</configuration>
Edit: As CodeCaster mentioned in his answer, SingleTagSectionHandler is for internal use only. I think NameValueSectionHandler is the preferred way to define config sections.
The SingleTagSectionHandler documentation says:
This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
You can retrieve it as a HashTable and access its entries using Configuration.GetSection():
Hashtable serverTag = (Hashtable)ConfigurationManager.GetSection("server");
string serverUrl = (string)serverTag["url"];
string peopleXMLPath = ConfigurationManager.AppSettings["server"];
gets the value from the appSettings part of the app.config file but you are storing your value in
<server url="http://example.com" />
Either put the value in the appSettings section as below or retrieve the value from its current location.
You need to add a key value pair to your config's appSettings section. As below:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="server" value="http://example.com" />
</appSettings>
</configuration>
Your reading code is correct but you should probably check for null. If the code fails to read the config value the string variable will be null.
You're defining a configuration section instead of a value in AppSettings. You can simply add your setting to AppSettings:
<appSettings>
... may be some settings here already
<add key="server" value="http://example.com" />
</appSettings>
Custom config sections are typically used for more complicated configurations (e.g. multiple values per key, non-string values, etc.
If you want to get the value from the app settings your appsetting element in configuration file must have a key.
define your sever value as mentioned below under configuration section:
<configuration>
<appSettings>
<add key="server" value="http://example.com" />
</appSettings>
...
...
...
</configuration>
Now execute below code line to get the server url:
string peopleXMLPath = ConfigurationManager.AppSettings["server"].ToString();

The configuration element is not declared

I'm doing some work in Visual Studio 2012 Express Edition. I have added an App.config XML file as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
</configuration>
The first thing that happens is a warning comes up that says "The 'configuration' element is not declared". Does anyone know why this is happening? It looks like elements can not be declared inside of until this is resolved.
Thanks!
This is the entire XML:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Version" value="779" />
<add key="TimeOut" value="60000" />
<add key="LogFileName" value="Log.txt" />
<!-- your Developer Id with eBay -->
<add key="Environment.DevId" value="" />
<!-- your Application Id with eBay -->
<add key="Environment.AppId" value="" />
<!-- your Application Certificate with eBay -->
<add key="Environment.CertId" value="" />
<!-- API Server URL -->
<!-- For production site use: https://api.ebay.com/wsapi -->
<!-- For Sandbox use: https://api.sandbox.ebay.com/wsapi -->
<add key="Environment.ApiServerUrl" value="https://api.sandbox.ebay.com/wsapi" />
<!-- EPS Server URL -->
<!-- For production site use: https://api.ebay.com/ws/api.dll"/-->
<add key="Environment.EpsServerUrl" value="https://api.sandbox.ebay.com/ws/api.dll" />
<!-- eBay Signin URL -->
<!-- For production site use: https://signin.ebay.com/ws/eBayISAPI.dll?SignIn -->
<!-- https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn -->
<add key="Environment.SignInUrl" value="https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn" />
<!-- ViewItem URL -->
<!-- For production site use: http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item={0} -->
<add key="Environment.ViewItemUrl" value="http://cgi.sandbox.ebay.com/ws/eBayISAPI.dll?ViewItem&item={0}" />
<!-- token is for both API server and EPS server -->
<add key="UserAccount.ApiToken" value="" />
<!-- eBay site ID -->
<add key="UserAccount.eBayUserSiteId" value="0" />
<add key="logexception" value="true"/>
<add key="logmessages" value="true"/>
<add key="logsdkmessages" value="true"/>
<add key="logsdk" value="true"/>
<add key="logfile" value="Log.txt"/>
<!-- Rule Name-->
<add key="RuName" value=""/>
<!-- Set this if you access eBay API server behind a proxy server-->
<add key="Proxy.Host" value =""/>
<add key="Proxy.Port" value =""/>
<!-- set proxy server username/password if necessary-->
<add key="Proxy.Username" value=""/>
<add key="Proxy.Password" value=""/>
Go to XML menu (visual studio top menu item) choose schemas and find for DotNetConfig.xsd and choose Use this schema.
Your problem will resolve for sure
<configuration xmlns="schema URL">
<!-- configuration settings -->
</configuration>
do changes,like above & try
I had the same issue. It is not an error, it is simply a warning; so your application should still compile. I used the following simple config file and the warning is still produced.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime
version="v4.0"sku=".NETFramework,
Version=v4.5"/>
</startup>
</configuration>
It is an issue that has been raised on the MSDN website, but it does not seem to have been satisfactorily resolved. See link below:
http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvcs/thread/18a1074f-668f-4fe3-a8d9-4440db797439
I had to
-> Go to XML menu (visual studio top menu item) choose schemas and select DotNetConfig.xsd AND RazorCustomSchema.xsd AND EntityFrameworkConfig_6_1_0.xsd
I just had this warning popup inside an autogenerated xml file while working on a xaml project.
Using Debug->Clean Solution and Debug->Rebuild Solution fixed it. Might want to try that before getting fancy with the schemas.
Visual Studio 2013 Express Edition is missing the DotNetConfig.xsd (https://connect.microsoft.com/VisualStudio/feedback/details/817322/dotnetconfig-xsd-files-not-present-in-vs-2013-express-for-desktop).
So to get rid of the warning in VS 2013 Express:
get a copy of DotNetConfig.xsd from another system or from the web (I used https://gist.github.com/eed3si9n/5dd7dd98ad2b3f668928b23477de35a3)
download to C:\Program Files (x86)\Microsoft Visual Studio 12.0\Xml\Schemas
add the schema following Ramakrishna's answer
The warning should be gone.
Choose use this schema. DotNetConfig.xsd
XLM Menu..... Visual Studio
Works perfectly.
I was having less space on my drive which might have resulted in incomplete loading of my application solution. This "the-configuration-element-is-not-declared" problem got solved after i created some space on my drive.
I also got the same warning. After thinking about for some time I realized my error working with SQL (MS SQL).
Warning: the 'configuration' element is not declared
Using C#
App.Config code:
<connectionStrings>
<add name="dbx" connectionString="Data Source=ServerNameHere;Initial Catalog=DatabaseNameHere;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
*this calls out the database name in the connectionStrings, when I plugged in my SQL code as a practice I always use the database name, schema, then table. This practice didn't carry over well in Visual Studio as I am a beginner. I removed the db name from my SQL syntax and only called from the schema, data table. This resolved the issue for me.
Form.CS:
using (SqlCommand cmd = new SqlCommand("SELECT * FROM [DatabaseName].[Schema].[TableName] WHERE [MEPeriod] = '2020-06-01'", con))
Updated to:
using (SqlCommand cmd = new SqlCommand("SELECT * FROM [Schema].[TableName] WHERE [MEPeriod] = '2020-06-01'", con))
This worked for me, I hope this is found as useful.

Categories

Resources