Duplicate the behaviour of a data driven test - visual-studio-2010

Right now, if you have a test that looks like this:
[TestMethod]
[DeploymentItem("DataSource.csv")]
[DataSource(
Microsoft.VisualStudio.TestTools.DataSource.CSV,
"DataSource.csv",
"DataSource#csv",
DataAccessMethod.Sequential)]
public void TestSomething()
{
string data = TestContext.DataRow["ColumnHeader"].ToString();
/*
do something with the data
*/
}
You'll get as many tests runs as you have data values when you execute this test.
What I'd like to do is duplicate this kind of behaviour in code while still having a datasource. For instance: let's say that I want to run this test against multiple deployed versions of a web service (this is a functional test, so nothing is being mocked - ie. it could very well be a codedui test against a web site deployed to multiple hosts).
[TestMethod]
[DeploymentItem("DataSource.csv")]
[DataSource(
Microsoft.VisualStudio.TestTools.DataSource.CSV,
"DataSource.csv",
"DataSource#csv",
DataAccessMethod.Sequential)]
public void TestSomething()
{
var svc = helper.GetService(/* external file - NOT a datasource */);
string data = TestContext.DataRow["ColumnHeader"].ToString();
/*
do something with the data
*/
}
Now, if I have 2 deployment locations listed in the external file, and 2 values in the datasource for the testmethod, I should get 4 tests.
You might be asking why I don't just add the values to the datasource. The data in the external file will be pulled in via the deployment items in the .testsettings for the test run, because they can and will be defined differently for each person running the tests and I don't want to force a rebuild of the test code in order to run the tests, or explode the number of data files for tests. Each test might/should be able to specify which locations it would like to test against (the types are known at compile-time, not the physical locations).
Likewise, creating a test for each deployment location isn't possible because the deployment locations can and will be dynamic in location, and in quantity.
Can anyone point me to some info that might help me solve this problem of mine?

UPDATE! This works for Visual Studio 2010 but does not seem to work on 2012 and 2013.
I had a similar problem where I had a bunch of files I wanted to use as test data in a data driven test. I solved it by generating a CSV file before executing the data driven test. The generation occurs in a static method decorated with the ClassInitialize attribute.
I guess you could basically do something similar and merge your current data source with your "external file" and output a new CSV data source that your data driven test use.
public TestContext TestContext { get; set; }
const string NameColumn = "NAME";
const string BaseResourceName = "MyAssembly.UnitTests.Regression.Source";
[ClassInitialize()]
public static void Initialize(TestContext context)
{
var path = Path.Combine(context.TestDeploymentDir, "TestCases.csv");
using (var writer = new StreamWriter(path, false))
{
// Write column headers
writer.WriteLine(NameColumn);
string[] resourceNames = typeof(RegressionTests).Assembly.GetManifestResourceNames();
foreach (string resourceName in resourceNames)
{
if (resourceName.StartsWith(BaseResourceName))
{
writer.WriteLine(resourceName);
}
}
}
}
[TestMethod]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\TestCases.csv", "TestCases#csv", DataAccessMethod.Random)]
public void RegressionTest()
{
var resourceName = TestContext.DataRow[NameColumn].ToString();
// Get testdata from resource and perform test.
}

Related

Debug WCF service in IIS with object as input

I want to debug a WCF service locally in Visual Studio. The called function looks like this:
public void PerformAction(Directory[] dirs) {
....
}
Directory is a class with some properties. In the WCF test client I want to test the function but how can I set the input values for the Directory array?
Taking the default WCF template as an example, I made the following definition.
[OperationContract]
//[WebGet(RequestFormat =WebMessageFormat.Json,ResponseFormat =WebMessageFormat.Json)]
string GetData(CompositeType[] value);
public string GetData(CompositeType[] value)
{
return string.Format("You entered: {0},{1}", value[0].StringValue,value[1].StringValue);
}
First enter the length of the array, then select the array type, and finally enter the values of the individual elements one by one.
Wish it is useful to you, feel free to let me know if there is anything I can help with.

testng specify different Users

I am running our automated tests using TestNG. The reason we picked TestNG is because we can send variables inputs into the test methods example public void testXX( String userId ) and the userId can change for each test.
The code below shows three different userIds I can use to execute my tests. So my exact same test will run three times for each of the three different users. This feature is awesome and really enables me to have multiple tests under different scenarios because each of our users carry different profiles.
// All valid Pricing Leads
#DataProvider(name = "userIds")
public Object[][] createPricingLeadUsersParameters() {
return new Object[][] {
{ "TestUser001" },
{ "TestUser002" },
{ "TestUser003" }
};
}
#Test( dataProvider = "userIds" )
public void createGroup( String userIds) {
............
}
The problem I am having right now is during certain conditions I can only have one userId used or else all of my tests will fail. I would like to keep my exact same test but only pass in on userId not the three shown above. It there a way to configure TestNG to make this variable on the command line so at times I would use the three defined, but under another condition it would only be one of the three or a new userId?
Sure, there are plenty of ways to do this. How about passing a system property when you run TestNG?
java -Dfoo=bar org.testng.TestNG...
and then your data provider can test the value of foo with System.getProperty() and adjust what it returns accordingly.

Entity Framework 4.3.1 add-migration error: "model backing the context has changed"

I'm getting an error when trying to run the EF 4.3.1 add-migrations command:
"The model backing the ... context has changed since the database was created".
Here's one sequence that gets the error (although I've tried probably a dozen variants which also all fail)...
1) Start with a database that was created by EF Code First (ie, already contains a _MigrationHistory table with only the InitialCreate row).
2) The app's code data model and database are in-sync at this point (the database was created by CF when the app was started).
3) Because I have four DBContexts in my "Services" project, I didn't run 'enable-migrations' command (it doesn't handle multipe contexts). Instead, I manually created the Migrations folder in the Services project and the Configuration.cs file (included at end of this post). [I think I read this in a post somewhere]
4) With the database not yet changed, and the app stopped, I use the VS EDM editor to make a trivial change to my data model (add one property to an existing entity), and have it generate the new classes (but not modify the database, obviously). I then rebuild the solution and all looks OK (but don't delete the database or restart the app, of course).
5) I run the following PMC command (where "App" is the name of one of the classes in Configuration.cs):
PM> add-migration App_AddTrivial -conf App -project Services -startup Services -verbose
... which fails with the "The model ... has changed. Consider using Code First Migrations..." error.
What am I doing wrong? And does anyone else see the irony in the tool telling me to use what I'm already trying to use ;-)
What are the correct steps for setting-up a solution starting with a database that was created by EF CF? I've seen posts saying to run an initial migration with -ignorechanges, but I've tried that and it doesn't help. Actually, I've spent all DAY testing various permutations, and nothing works!
I must be doing something really stupid, but I don't know what!
Thanks,
DadCat
Configuration.cs:
namespace mynamespace
{
internal sealed class App : DbMigrationsConfiguration
{
public App()
{
AutomaticMigrationsEnabled = false;
MigrationsNamespace = "Services.App.Repository.Migrations";
}
protected override void Seed(.Services.App.Repository.ModelContainer context)
{
}
}
internal sealed class Catalog : DbMigrationsConfiguration<Services.Catalog.Repository.ModelContainer>
{
public Catalog()
{
AutomaticMigrationsEnabled = false;
MigrationsNamespace = "Services.Catalog.Repository.Migrations";
}
protected override void Seed(Services.Catalog.Repository.ModelContainer context)
{
}
}
internal sealed class Portfolio : DbMigrationsConfiguration<Services.PortfolioManagement.Repository.ModelContainer>
{
public Portfolio()
{
AutomaticMigrationsEnabled = false;
MigrationsNamespace = "Services.PortfolioManagement.Repository.Migrations";
}
protected override void Seed(Services.PortfolioManagement.Repository.ModelContainer context)
{
}
}
internal sealed class Scheduler : DbMigrationsConfiguration<.Services.Scheduler.Repository.ModelContainer>
{
public Scheduler()
{
AutomaticMigrationsEnabled = false;
MigrationsNamespace = "Services.Scheduler.Repository.Migrations";
}
protected override void Seed(Services.Scheduler.Repository.ModelContainer context)
{
}
}
}
When using EF Migrations you should have one data context per database. I know that it can grow really large, but by trying to split it you will run into several problems. One is the migration issue that you are experiencing. Later on you will probably be facing problems when trying to make queries joining tables from the different contexts. Don't go that way, it's against how EF is designed.

OpenCover showing 0 lines covered with mstest

'here is output...'
Loading C:\TEMP\BankDemo_mstest\Test_BankDemo\bin\Debug\Test_BankDemo.dll...
Starting execution...
Results Top Level Tests
------- ---------------
Error Test.BankDemo.AccountTest.CreditTest
Error Test.BankDemo.AccountTest.DebitTest
Error Test.BankDemo.AccountTest.FreezeTest
0/3 test(s) Passed, 3 Error
Summary
-------
Test Run Error.
Error 3
--------
Total 3
This is the command I used
OpenCover\OpenCover.Console.exe -register:user
-output:"Codecoverage.xml"
-mergebyhash
-target:"C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe"
targetargs:"/testcontainer:
"C:\TEMP\BankDemo_mstest\Test_BankDemo\bin\Debug\Test_BankDemo.dll"
/noisolation"
-filter:"-[Bank.*]* +[Bank*]* +[Bank.Accounts*]* -[Test.BankDemo*]*"
ReportGenerator\bin\ReportGenerator.exe Codecoverage.xml Coverage HTML
(I have even tried regsvr32 to register the profile and I am using XP)
actually I am beginner to Nunit,mstest and opencoverage and I found sample Unit test case at http://www.nunit.org/index.php?p=quickStart&r=2.4 so
** Nunit test class is as below**
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
private int store;
[TestInitialize()]
public void TestFixtureSetUp()
{
store = 1;
}
the above class works fine with Nunit and Opencoverage also showing accurate data but same class after replacing mstest specific attributes didn't worked so after posting this questin I figured it that this method has to be static and added TestContext argument. so I made code changes(in bold) as below and above command worked fine.
MSTest class
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
[ClassInitialize()]
public **static** void ClassInit(**TestContext context**)
{
}
Your tests aren't failing -- they're erroring, meaning there appears to be a problem compiling the test project. It stands to reason that you'll get no coverage if the tests cannot be built and executed.
2 reasons could be for this however I suspect your filters are wrong, as described in the usage the filters are
(+/-)[assembly/module filter]namespace.typefilter
and exclusion filters take precedence over inclusion filters
So your -[Bank.*]* is excluding types before the +[Bank.Accounts*]* (and probably +[Bank*]*) can take effect. As the default filter +[*]* is only added if you have no other extra filters, other than the default ones, then you should only need to add filters for the modules you wish to profile i.e. +[Bank.*]*
If you open up the XML output then if a class is filtered out then a reason is supplied via the skippedDueTo attribute.
The other reason could be due to missing PDB files not in the folder of the assembly (some test harnesses copy assemblies to other folders - but I see you are using the /noisolation switch - so this shouldn't be it)
Please feel free to discuss or if you think there is a big raise the issue on the OpenCover GitHub site

What's the easiest way to write a unit test that sends Request.Form data to my controller?

Basically I want to set 20 or so Request.Form values, send a POST to my controller, and then check the result.
I found a couple articles such as this one which describe how you can do this with a combination of NUnit, MVCContrib, and Rhino Mocks. But I don't know if this is truly necessary.
It would seem that Visual Studio 2010 and ASP.NET MVC 2 should be able to do this natively and display the results in the little "Test Results" window. In fact, when I create a new unit test with the wizard, it comes up with this...
[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("G:\\Webs\\MyWebsite.com\\MyWebsite", "/")]
[UrlToTest("http://localhost:43383/")]
public void PaypalIPNTest()
{
BuyController target = new BuyController(); // TODO: Initialize to an appropriate value
ActionResult expected = new EmptyResult(); // TODO: Initialize to an appropriate value
ActionResult actual;
actual = target.PaypalIPN();
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
Is it possible to feed target.PaypalIPN() my Request.Form variables based on the above code? Or do I need to rely on 3rd party libraries to get this done?
In fact, when I create a new unit test with the wizard, it comes up with this
Yes, and all that you can keep from this is the method signature. The method body is useless.
So let's start by looking at this:
Is it possible to feed target.PaypalIPN() my Request.Form variables
By reading this sentence I assume that your controller action looks something like this:
[HttpPost]
public ActionResult PaypalIPN()
{
string foo = Request["foo"];
string bar = Request["bar"];
... do something with foo and bar
}
So the first is to improve this code by introducing view models:
public class MyViewModel
{
public string Foo { get; set; }
public string Bar { get; set; }
}
and then modify your method signature to:
[HttpPost]
public ActionResult PaypalIPN(MyViewModel model)
{
... do something with model.Foo and model.Bar
}
Now your controller is abstracted from any HttpContext infrastructure code (which really should be left to the framework, it is not your controller actions responsibility to read request parameters => that's plumbing code) and unit testing it is really a simple matter:
[TestMethod()]
public void PaypalIPNTest()
{
// arrange
var sut = new BuyController();
var model = new MyViewModel
{
Foo = "some foo",
Bar = "some bar",
};
// act
var actual = sut.PaypalIPN(model);
// assert
// TODO:
}
OK, this being said, here we dealt with some really simple controller action. For more advanced scenarios you really should consider using a mocking framework. Personally I use MvcContrib.TestHelper with Rhino Mocks to unit test my ASP.NET MVC applications.
I have another approach to test my MVC application, first I used Dev Magic Fake to fake any underline layer under the controller until the application is running and the business is approved and then I replace the fake code with TDD approach based on approved requirements
See Dev Magic Fake on CodePlex:
http://devmagicfake.codeplex.com/
Thanks
M.Radwan

Resources