How to Run a Test Method with Multiple Parameters in Mstest

How can we run a test method with multiple parameters in MSTest?

It is unfortunately not supported in older versions of MSTest. Apparently there is an extensibility model and you can implement it yourself. Another option would be to use data-driven tests.

My personal opinion would be to just stick with NUnit though...

As of Visual Studio 2012, update 1, MSTest has a similar feature. See McAden's answer.

MSTest Equivalent for NUnit's Parameterized Tests?

Would this help?

This week I was adding some unit tests
to a project that is managed by TFS,
so I decided to use the "core" unit
testing framework available with
VS2008, and unfortunately it doesn't
support RowTests. But it has a similar
feature called Data-Driven Unit Test.
With this approach it's a bit more
complicate to implement the "simple"
RowTest scenario, but it allows also
to implement more complicate ones.

Set Up Test Method with different inputs

You can use XML, Database, or CSV datasources MS Test. Create FooTestData.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Rows>
<Row><Data>1</Data></Row>
<Row><Data>2</Data></Row>
</Rows>

And set it as datasource for your test:

[TestMethod]
[DeploymentItem("ProjectName\\FooTestData.xml")]
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
"|DataDirectory|\\FooTestData.xml", "Row",
DataAccessMethod.Sequential)]
public void FooTest()
{
int x = Int32.Parse((string)TestContext.DataRow["Data"]);
// some assert
}

BTW with NUnit framework it's match easier - you can use TestCase attribute to provide test data:

[TestCase(1)]
[TestCase(2)]
public void FooTest(int x)
{
// some assert
}

Passing object in MSTest method parameters

You are comparing reference types, that doesn't work as you are comparing the reference in memory, and those will not equal. You should override the Equals() function, then use that in your tests.

.Net Equals Function

The Equals function takes in a type, and then you just do comparisons, for example, add this to your Ship class:

   public override bool Equals(Ship obj) 
{
if (this.Width != obj.Width)
{
return false;
}

return true;
}

Then you just do this in your tests:

Assert.IsTrue(expectedShip.Equals(resultShip))

How do test all combinations of parameters in DataRows

Best I could come up with is this:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;

namespace UnitTestProject
{
[TestClass]
public class TestThing
{
[CombinatorialTestMethod]
[DataRow( 0 , 9 )]
[DataRow( 1 , 2 )]
[DataRow( 3 , 4 , 5 , 7)]
public void TestMe( int a , int b , int c )
{
if ( b * 2 == c )
throw new Exception( "blah!" );
}
}

public class CombinatorialTestMethodAttribute : TestMethodAttribute
{
private object[][] argsArrays = new object[][] { };

private List<object[]> argumentsList = new( );

public override TestResult[] Execute( ITestMethod testMethod )
{
// Get arrays of arguments, then construct arguments list
List<object[]> argsArraysList = new( );
foreach ( DataRowAttribute parameters in testMethod.GetAttributes<DataRowAttribute>( false ) )
{
argsArraysList.Add( parameters.Data );
}
this.argsArrays = argsArraysList.ToArray( );
this.ConstructArgumentsList( );

// Invoke the test
List<TestResult> results = new( );
foreach ( object[] args in this.argumentsList )
{
try
{
TestResult result = testMethod.Invoke( args );
results.Add( result );
}
catch ( Exception e )
{
results.Add( new TestResult( )
{
Outcome = UnitTestOutcome.Failed ,
TestFailureException = e ,
} );
}
}

return results.ToArray( );
}

private void ConstructArgumentsList( )
{
int num_params = this.argsArrays.Length;

int[] indices = new int[num_params];

bool done = num_params == 0;
while ( !done )
{
// Get next arguemnt combination
object[] args = new object[num_params];
for ( int i = 0 ; i < num_params ; i += 1 )
{
args[i] = this.argsArrays[i][indices[i]];
}
this.argumentsList.Add( args );

// increment indices
for ( int i = num_params - 1 ; i >= 0 ; i -= 1 )
{
indices[i] += 1;
if ( indices[i] >= this.argsArrays[i].Length )
{
indices[i] = 0;

if ( i == 0 )
{
done = true;
break;
}
}
else
{
break;
}
}
}
}
}
}

I'm not going to use it because I'm not 100% happy with it yet, but I may fiddle some more and publish something later.

Moq: multiple tests through params, one test method

Moq is mocking framework for .NET.

This functionality is not related to Moq, it depends of unit testing tool. So,
if you're using xUnit then

[Theory]
[InlineData("john", "mike", "sheila")]
[InlineData("jake", "bleh", "donny")]
public void Test(string param1, string param2, string param3)
{
}

If you are using MSTest then add the packages MsTest.TestAdapter and MsTest.TestFramework

[DataTestMethod]
[DataRow("john", "mike", "sheila")]
[DataRow("jake", "bleh", "donny")]
public void Test(string param1, string param2, string param3)
{
}

MSTest repeat unit test with different runtime parameter

Good news! You should find that the new-ish [DynamicData] attribute in MsTestV2 can solve your case:

[DynamicData(nameof(AllNotificationTypes))]
[DataTestMethod]
public async Task TestNotification(Type type)
{

}

public static Type[] AllNotificationTypes
=> typeof(INotification).Assembly.GetTypes()
.Where(t => typeof(INotification).IsAssignableFrom(t) && !t.IsAbstract)
.ToArray();

https://dev.to/frannsoft/mstest-v2---new-old-kid-on-the-block is a good brief intro to the new features, but there are more gory details in posts starting at https://blogs.msdn.microsoft.com/devops/2017/07/18/extending-mstest-v2/

How would I achieve a range based test in MSTest

Maybe that's what you're looking for. Some years ago, Microsoft made ​​available an extension for visual studio called PEX.

PEX generate unit tests from a single parametric test, Pex finds
interesting input-output values of your methods, which you can save as
a small test suite with high code coverage.

You can use assumption and precondition for the parameters of your test, which ensure the best control of the tests generation.

Pex is no longer available(it was a research project), but is now available instead Intellitest, which still uses the same static analysis engine.

Intellitest generates a parameterized test that is modifiable and
general/global assertions can be added there. It also generates the
minimum number of inputs that maximize the code coverage; stores the
inputs as individual unit tests, each one calling the parameterized
test with a crafted input.

[PexMethod]
public void Test(int i)
{
PexAssume.IsTrue(i >= 0);
PexAssume.IsTrue(i < 10);
// Test stuff
}


Related Topics



Leave a reply



Submit