Skip to content

Commit

Permalink
Merge pull request #2 from Thwaitesy/New-File-Per-Datasource
Browse files Browse the repository at this point in the history
New file per datasource
  • Loading branch information
cjwarner committed Sep 30, 2013
2 parents b9cea0c + 2a7e2b6 commit 3c3bc68
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 46 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Overview
Just a bunch of hacks to get around the deficiencies of MSTest.

Hopefully for those of us that have to work inside the constrainsts of MSTest, this library should ease our pain. (Just a little)

Check out the tests project for samples

Features
==========================================================================
***RuntimeDataSource***
Expand Down Expand Up @@ -45,9 +48,9 @@ public class UnitTest1 : TestBase
}
```

**3)** Add the `DataSource` attribute to your test method, pointing back to the IEnumerable<T> name above.
**3)** Add the `DataSource` attribute to your test method, pointing back to the IEnumerable<T> name above. This needs to be fully qualified to create uniqueness.
```csharp
[DataSource("Stuff")]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Expand All @@ -64,6 +67,10 @@ Roadmap

Changelog
==========================================================================
*1.1.0 - (BREAKING CHANGE)*
- Creating a datasource file per datasource, simplifies life
- All datasources now have to be fully qualified, pointing to the IEnumerable<T>. This creates a unique datasource that was required in some instances.

*1.0.2*
- Inject the ConnectionString automatically
- Add a couple more tests
Expand All @@ -81,6 +88,11 @@ Changelog
*0.0.1*
- Initial release

Contributors
==========================================================================
Sam Thwaites
Corey Warner

Licence
==========================================================================
See [LICENCE](https://github.com/Thwaitesy/MSTestHacks/blob/master/LICENCE)
2 changes: 1 addition & 1 deletion src/MSTestHacks.Tests/MSTestHacks.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<ItemGroup>
<Compile Include="RuntimeDataSource\ComplexObjects.cs" />
<Compile Include="RuntimeDataSource\BaseClass.cs" />
<Compile Include="RuntimeDataSource\SimpleObjects2.cs" />
<Compile Include="RuntimeDataSource\InheritedTests.cs" />
<Compile Include="RuntimeDataSource\SimpleObjects.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand All @@ -65,7 +66,6 @@
<Name>MSTestHacks</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup />
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
<ItemGroup>
Expand Down
8 changes: 5 additions & 3 deletions src/MSTestHacks.Tests/RuntimeDataSource/ComplexObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace MSTestHacks.Tests.RuntimeDataSource
[AttachRuntimeDataSources(typeof(ComplexObjects))]
public class ComplexObjects : TestBase
{
const string PREFIX = "MSTestHacks.Tests.RuntimeDataSource.ComplexObjects.";

public IEnumerable<XYZ> ComplexField = new List<XYZ>
{
new XYZ(1, "test 1"),
Expand Down Expand Up @@ -40,7 +42,7 @@ public IEnumerable<XYZ> ComplexMethod()
}

[TestMethod]
[DataSource("ComplexField")]
[DataSource(PREFIX + "ComplexField")]
public void Complete_Object_Can_Be_Injected_From_Field()
{
var x = this.TestContext.GetRuntimeDataSourceObject<XYZ>();
Expand All @@ -49,7 +51,7 @@ public void Complete_Object_Can_Be_Injected_From_Field()
}

[TestMethod]
[DataSource("ComplexProperty")]
[DataSource(PREFIX + "ComplexProperty")]
public void Complete_Object_Can_Be_Injected_From_Property()
{
var x = this.TestContext.GetRuntimeDataSourceObject<XYZ>();
Expand All @@ -58,7 +60,7 @@ public void Complete_Object_Can_Be_Injected_From_Property()
}

[TestMethod]
[DataSource("ComplexMethod")]
[DataSource(PREFIX + "ComplexMethod")]
public void Complete_Object_Can_Be_Injected_From_Method()
{
var x = this.TestContext.GetRuntimeDataSourceObject<XYZ>();
Expand Down
4 changes: 3 additions & 1 deletion src/MSTestHacks.Tests/RuntimeDataSource/InheritedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace MSTestHacks.Tests.RuntimeDataSource
[AttachRuntimeDataSources(typeof(InheritedTests))]
public class InheritedTests : BaseClass
{
const string PREFIX = "MSTestHacks.Tests.RuntimeDataSource.InheritedTests.";

public InheritedTests()
{

Expand All @@ -26,7 +28,7 @@ public IEnumerable<int> Simple2
}

[TestMethod]
[DataSource("Simple2")]
[DataSource(PREFIX + "Simple2")]
public void MyTestMethod()
{
Testa();
Expand Down
12 changes: 7 additions & 5 deletions src/MSTestHacks.Tests/RuntimeDataSource/SimpleObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ namespace MSTestHacks.Tests.RuntimeDataSource
[AttachRuntimeDataSources(typeof(SimpleObjects))]
public class SimpleObjects : TestBase
{
const string PREFIX = "MSTestHacks.Tests.RuntimeDataSource.SimpleObjects.";

private int _publicFieldCount = 221;
public IEnumerable<int> PublicField = Enumerable.Range(0, 221);

Expand Down Expand Up @@ -47,7 +49,7 @@ private IEnumerable<string> PrivateMethod()

#region Field Tests
[TestMethod]
[DataSource("PublicField")]
[DataSource(PREFIX + "PublicField")]
public void Test_Simple_Objects_Injected_From_PublicField()
{
//Make sure the object can be retrieved.
Expand All @@ -59,7 +61,7 @@ public void Test_Simple_Objects_Injected_From_PublicField()

#region Property Tests
[TestMethod]
[DataSource("PublicProperty")]
[DataSource(PREFIX + "PublicProperty")]
public void Test_Simple_Objects_Injected_From_PublicProperty()
{
//Make sure the object can be retrieved.
Expand All @@ -69,7 +71,7 @@ public void Test_Simple_Objects_Injected_From_PublicProperty()
}

[TestMethod]
[DataSource("PrivateProperty")]
[DataSource(PREFIX + "PrivateProperty")]
public void Test_Simple_Objects_Injected_From_PrivateProperty()
{
//Make sure the object can be retrieved.
Expand All @@ -81,7 +83,7 @@ public void Test_Simple_Objects_Injected_From_PrivateProperty()

#region Method Tests
[TestMethod]
[DataSource("PublicMethod")]
[DataSource(PREFIX + "PublicMethod")]
public void Test_Simple_Objects_Injected_From_PublicMethod()
{
//Make sure the object can be retrieved.
Expand All @@ -93,7 +95,7 @@ public void Test_Simple_Objects_Injected_From_PublicMethod()
}

[TestMethod]
[DataSource("PrivateMethod")]
[DataSource(PREFIX + "PrivateMethod")]
public void Test_Simple_Objects_Injected_From_PrivateMethod()
{
//Make sure the object can be retrieved.
Expand Down
36 changes: 36 additions & 0 deletions src/MSTestHacks.Tests/RuntimeDataSource/SimpleObjects2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MSTestHacks.RuntimeDataSource;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Xml;
using System.Linq;

namespace MSTestHacks.Tests.RuntimeDataSource
{
[TestClass]
[AttachRuntimeDataSources(typeof(SimpleObjects2))]
public class SimpleObjects2 : TestBase
{
const string PREFIX = "MSTestHacks.Tests.RuntimeDataSource.SimpleObjects2.";

private int _publicPropertyCount = 14;
public IEnumerable<int> PublicProperty
{
get
{
return Enumerable.Range(0, this._publicPropertyCount);
}
}

[TestMethod]
[DataSource(PREFIX + "PublicProperty")]
public void Test_Simple_Objects_Injected_From_PublicProperty()
{
//Make sure the object can be retrieved.
var x = this.TestContext.GetRuntimeDataSourceObject<int>();

Assert.AreEqual(this._publicPropertyCount, this.TestContext.DataRow.Table.Rows.Count);
}
}
}
79 changes: 48 additions & 31 deletions src/MSTestHacks/RuntimeDataSource/AttachRuntimeDataSources.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,33 @@ namespace MSTestHacks.RuntimeDataSource
[AttributeUsage(AttributeTargets.Class)]
public sealed class AttachRuntimeDataSources : ContextAttribute
{
private string DATASOURCES_PATH = Path.Combine(Path.GetDirectoryName(new UriBuilder(Assembly.GetExecutingAssembly().GetName().CodeBase).Uri.LocalPath), "RuntimeDataSources");
private static HashSet<Type> typesInitalized = new HashSet<Type>();

public AttachRuntimeDataSources(Type type)
: base("AttachRuntimeDataSources")
{
if (!typesInitalized.Contains(type))
{
typesInitalized.Add(type);
var appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

var appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
//If the connectionStrings section doest exist, add it.
if (!appConfig.Sections.Cast<ConfigurationSection>().Any(x => x.SectionInformation.Name == "connectionStrings"))
appConfig.Sections.Add("connectionStrings", new ConnectionStringsSection());

//If the connectionStrings section doest exist, add it.
if (!appConfig.Sections.Cast<ConfigurationSection>().Any(x => x.SectionInformation.Name == "connectionStrings"))
{
appConfig.Sections.Add("connectionStrings", new ConnectionStringsSection());
}
//If the test tools section doest exist, add it.
if (!appConfig.Sections.Cast<ConfigurationSection>().Any(x => x.SectionInformation.Name == "microsoft.visualstudio.testtools"))
appConfig.Sections.Add("microsoft.visualstudio.testtools", new Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection());

//Add in the runtimeDataSource connection string.
var connectionStringsSection = (ConnectionStringsSection)appConfig.Sections["connectionStrings"];
connectionStringsSection.ConnectionStrings.Add(new ConnectionStringSettings("RuntimeDataSource", "RuntimeDataSources.xml", "Microsoft.VisualStudio.TestTools.DataSource.XML"));
var connectionStringsSection = (ConnectionStringsSection)appConfig.Sections["connectionStrings"];
var testConfigurationSection = (TestConfigurationSection)appConfig.Sections["microsoft.visualstudio.testtools"];

//If the test tools section doest exist, add it.
if (!appConfig.Sections.Cast<ConfigurationSection>().Any(x => x.SectionInformation.Name == "microsoft.visualstudio.testtools"))
{
appConfig.Sections.Add("microsoft.visualstudio.testtools", new Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection());
}
if (!Directory.Exists(DATASOURCES_PATH))
Directory.CreateDirectory(DATASOURCES_PATH);

var testConfigurationSection = (TestConfigurationSection)appConfig.Sections["microsoft.visualstudio.testtools"];
var configChanged = false;
var configChanged = false;

if (!typesInitalized.Contains(type))
{
typesInitalized.Add(type);

//Go through all the methods
foreach (var method in type.GetMethods())
Expand All @@ -55,52 +53,71 @@ public AttachRuntimeDataSources(Type type)
var attribute = method.GetCustomAttribute<DataSourceAttribute>();
if (attribute != null && !string.IsNullOrWhiteSpace(attribute.DataSourceSettingName))
{
//Note: This may remove a datasource that was wanted....
testConfigurationSection.DataSources.Remove(attribute.DataSourceSettingName);
var dataSourceName = attribute.DataSourceSettingName;
var connectionStringName = attribute.DataSourceSettingName + "_RuntimeDataSource";
var dataSourceFilePath = Path.Combine(DATASOURCES_PATH, dataSourceName + ".xml");
var lastIndexOfDot = dataSourceName.LastIndexOf(".");
if (lastIndexOfDot == -1)
throw new Exception("Please specify the fully qualified type + property.");

var refernceName = dataSourceName.Substring(lastIndexOfDot + 1);
var typeName = dataSourceName.Substring(0, lastIndexOfDot);

if (typeName != type.FullName)
continue;

//Add connection string
connectionStringsSection.ConnectionStrings.Add(new ConnectionStringSettings(connectionStringName, dataSourceFilePath, "Microsoft.VisualStudio.TestTools.DataSource.XML"));

//Add datasource
var dataSource = new DataSourceElement()
{
Name = attribute.DataSourceSettingName,
ConnectionString = "RuntimeDataSource",
DataTableName = type.FullName + "." + method.Name,
Name = dataSourceName,
ConnectionString = connectionStringName,
DataTableName = "Row",
DataAccessMethod = "Sequential"
};
testConfigurationSection.DataSources.Add(dataSource);
configChanged = true;

//Get the source data
var sourceData = new List<object>();
foreach (var x in new ProviderReference(type, dataSource.Name).GetInstance())

//var lastIndexOfDot = dataSourceName.LastIndexOf(".");
//var refernceName = dataSourceName.Substring(lastIndexOfDot);
//var typeName = dataSourceName.Substring(0, lastIndexOfDot);
//var typex = Type.GetType(typeName);
foreach (var x in new ProviderReference(type, refernceName).GetInstance())
{
sourceData.Add(x);
}

//Create the file (if not there)
var fileName = "RuntimeDataSources.xml";
var fileName = dataSourceFilePath;
if (!File.Exists(fileName))
File.WriteAllText(fileName, new XDocument(new XDeclaration("1.0", "utf-8", "true"), new XElement("DataSources")).ToString());
File.WriteAllText(fileName, new XDocument(new XDeclaration("1.0", "utf-8", "true"), new XElement("Rows")).ToString());

//Load the file
var doc = XDocument.Load(fileName);

//Remove all elements with the same name
doc.Element("DataSources").Elements(dataSource.DataTableName).Remove();
doc.Element("Rows").Elements(dataSource.DataTableName).Remove();

//Add the iterations
doc.Element("DataSources").Add(
doc.Element("Rows").Add(

from data in sourceData
select new XElement(dataSource.DataTableName,
new XElement("Payload", JsonConvert.SerializeObject(data))));
new XElement("Data", JsonConvert.SerializeObject(data))));

//Save the file
doc.Save(fileName);
}

if (configChanged)
{
appConfig.Save(ConfigurationSaveMode.Modified, true);
appConfig.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection("connectionStrings");
ConfigurationManager.RefreshSection("microsoft.visualstudio.testtools");
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/MSTestHacks/RuntimeDataSource/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class Extensions
{
public static T GetRuntimeDataSourceObject<T>(this TestContext testContext)
{
return JsonConvert.DeserializeObject<T>(testContext.DataRow["payload"].ToString());
return JsonConvert.DeserializeObject<T>(testContext.DataRow["Data"].ToString());
}
}
}
4 changes: 2 additions & 2 deletions src/NuGet/Package.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>MSTestHacks</id>
<version>1.0.2</version>
<version>1.1.0</version>
<title>MSTest Hacks</title>
<authors>Sam Thwaites</authors>
<authors>Sam Thwaites, Corey Warner</authors>
<owners>Sam Thwaites</owners>
<licenseUrl>https://github.com/Thwaitesy/MSTestHacks/blob/master/LICENCE</licenseUrl>
<projectUrl>https://github.com/Thwaitesy/MSTestHacks</projectUrl>
Expand Down

0 comments on commit 3c3bc68

Please sign in to comment.