NUnit: TestCaseSource assigns tests to specific test methods - c#

I'm planning to store all test cases in a excel file with columns indicate test method names, parameters and expected results; however, I found TestCaseSource simply assigns all test cases to every test method. I'm wondering that is there any way I can make NUnit select test cases for methods base on method names I put in the spreadsheet?
Thanks.

There is a way to do this.
For example, as you mentioned, you can create a custom attribute.
The idea is to pass name of test to TestCaseSource.
You can do it by creating TestCaseSource as separate class.
First, TestCaseSource class:
public class SpreadSheetTestCaseSource
{
[ThreadStatic]
public static string TestName = String.Empty;
public static IEnumerable TestCases
{
get
{
SpreadSheetTestCaseProvider.GetTestCases()
.Where(testCase => testCase.TestName == TestName);
}
}
}
Then attribute:
public class MyTestCaseSourceAttribute : TestCaseSourceAttribute
{
public MyTestCaseSourceAttribute(Type sourceType, string sourceName,
[CallerMemberName] string name = null)
: base(sourceType, sourceName)
{
SpreadSheetTestCaseSource.TestName = name;
}
//Another two members impl.
}
And test:
[TestFixture]
public class TestClass
{
[MyTestCaseSource(typeof(SpreadSheetTestCaseSource), "TestCases")]
public void TestMethod()
{
//Test logic
}
}
SpeadSheetTestCaseSource.TestName is thread static. So you can run tests parallel.

This isn't a feature that NUnit supports directly. The various TestCaseSource type attributes have no ability to feed a test method based on the input.
An option would be to create a TestCaseSource for each of your test methods. Each of these would be a simple wrapper that passes in the method name to a single internal method. That internal method would read in the Excel file and only return the rows for the given method name.
PseudoCode;
[TestCaseSource(nameof(TestMethodOneSource))]
public void TestMethodOne(int x, int y, int expected)
{
Assert.That(x + y, Is.EqualTo(expected));
}
public static IEnumerable<object[]> TestMethodOneSource() =>
ReadExcel(nameof(TestMethodOne));
private static IEnumerable<object[]> ReadExcel(string method)
{
// Open and start reading Excel
for(var row in rows)
{
if(row[0] == method)
{
// Return objects minus the method
yield return new [] {row[1], ..., row[n]};
}
}
}

Related

Share variable value between tests in Xunit test [duplicate]

I have written the xUnit test cases in C#. That test class contains so many methods. I need to run the whole test cases in a sequence. How can I set the test case sequence in xUnit?
In xUnit 2.* this can be achieved using the TestCaseOrderer attribute to designate an ordering strategy, which can be used to reference an attribute that is annotated on each test to denote an order.
For example:
Ordering Strategy
[assembly: CollectionBehavior(DisableTestParallelization = true)]
public class PriorityOrderer : ITestCaseOrderer
{
public IEnumerable<TTestCase> OrderTestCases<TTestCase>(IEnumerable<TTestCase> testCases) where TTestCase : ITestCase
{
var sortedMethods = new SortedDictionary<int, List<TTestCase>>();
foreach (TTestCase testCase in testCases)
{
int priority = 0;
foreach (IAttributeInfo attr in testCase.TestMethod.Method.GetCustomAttributes((typeof(TestPriorityAttribute).AssemblyQualifiedName)))
priority = attr.GetNamedArgument<int>("Priority");
GetOrCreate(sortedMethods, priority).Add(testCase);
}
foreach (var list in sortedMethods.Keys.Select(priority => sortedMethods[priority]))
{
list.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name));
foreach (TTestCase testCase in list)
yield return testCase;
}
}
static TValue GetOrCreate<TKey, TValue>(IDictionary<TKey, TValue> dictionary, TKey key) where TValue : new()
{
TValue result;
if (dictionary.TryGetValue(key, out result)) return result;
result = new TValue();
dictionary[key] = result;
return result;
}
}
Attribute
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class TestPriorityAttribute : Attribute
{
public TestPriorityAttribute(int priority)
{
Priority = priority;
}
public int Priority { get; private set; }
}
Test Cases
[TestCaseOrderer("FullNameOfOrderStrategyHere", "OrderStrategyAssemblyName")]
public class PriorityOrderExamples
{
[Fact, TestPriority(5)]
public void Test3()
{
// called third
}
[Fact, TestPriority(0)]
public void Test2()
{
// called second
}
[Fact, TestPriority(-5)]
public void Test1()
{
// called first
}
}
xUnit 2.* ordering samples here
Testpriority: at the bottom of this page.
[PrioritizedFixture]
public class MyTests
{
[Fact, TestPriority(1)]
public void FirstTest()
{
// Test code here is always run first
}
[Fact, TestPriority(2)]
public void SeccondTest()
{
// Test code here is run second
}
}
BTW, I have the same problem right now. And yes, it is not the clean art.. but QA wanted a manual test.. so an automated test with a specific order already is a big leap for them.. (cough) and yes, it is not really unit testing..
If you really have the need to prioritize your tests (probably not your unit tests) you can use Xunit.Priority.
I have used it for some integration testing and works really well and simple without the overhead of having to write your prioritization classes, for simple case scenarios
For some reason, XUnit.Priority didn't work for me. In my test cases, it wasn't running the tests in the priority order specified.
So I tried XUnitPriorityOrderer, which is similar to use but was working (To quickly test it, save the following code in a text editor as OrderedXUnitTests.linq, then open it with LinqPad 6 and execute it. Alternatively, you can also copy the TestClass to Visual Studio and add XUnit, XUnit.Runner.VisualStudio and XUnitPriorityOrderer):
<Query Kind="Program">
<NuGetReference>XUnitPriorityOrderer</NuGetReference>
<Namespace>Xunit</Namespace>
<Namespace>XUnitPriorityOrderer</Namespace>
</Query>
#load "xunit"
// using XUnitPriorityOrderer
// see: https://github.com/frederic-prusse/XUnitPriorityOrderer
void Main()
{
RunTests(); // Call RunTests() or press Alt+Shift+T to initiate testing.
}
#region private::Tests
[TestCaseOrderer(CasePriorityOrderer.TypeName, CasePriorityOrderer.AssembyName)]
public class TestClass
{
static List<string> Order { get; set; }
public TestClass()
{
Order = Order ?? new List<string>();
}
[Fact, Order(2)]
void Test_Xunit_AnotherTest()
{
Order.Add("Test_Xunit_AnotherTest");
Assert.True(3 + 1 == 4);
}
[Fact, Order(1)]
void Test_Xunit()
{
Order.Add("Test_XUnit");
Assert.True(1 + 1 == 2);
}
[Fact, Order(99)]
void Print_Order()
{
Order.Add("Print_Order");
var strOrder = string.Join(", ", Order.ToArray());
strOrder.Dump("Execution Order");
Assert.True(true);
}
}
#endregion
This will run the tests in given order (Order(1), Order(2) and then Order(99)) and will dump the executed tests finally (test method Print_Order()).
You can't, by design. It's deliberately random in order to prevent anyone getting one of those either by desire or by accident.
The randomness is only for a given Test class, so you may be able to achieve your goals by wrapping items you want to control the order of inside a nested class - but in that case, you'll still end up with random order whenever you have more than two Test Methods in a class.
If you're trying to manage the building up of fixtures or context, the built-in IUseFixture<T> mechanism may be appropriate. See the xUnit Cheat Sheet for examples.
But you really need to tell us more about what you're trying to do or we'll just have to get speculative.

How to execute parameterized testcase if I dont want to specify the parameters using TestCase Attribute?

How to execute the below code from the Nunit Console if I doesnt know the Parameters which will be passed during execution.
[TestCase]
public void ExecuteString(string someValue)
{
Console.WriteLine(someValue);
}
I know that we should pass the parameters in this format [TestCase("Values")]. But If I'm not sure about what the parameters will be ?
You can not use the TestCase attribute this way, but there is the TestCaseSource attribute that can work with variables and runtime values.
It works as shown below. Might this be what you are looking for?
[Test, TestCaseSource(typeof(string), nameof(SomeClass.someCases))]
public void Test(string someValue)
{
Console.WriteLine(someValue);
}
private class someClass
{
public static IEnumerable someCases
{
get
{
yield return
new TestCaseData("valuefornow");
yield return
new TestCaseData("valueforlater");
}
}
}

Testing member assignment using mocks in c#

I am writing a testing framework for my system, which allows users to create mocked inputs to the system. The system manipulates that input, and updates some of its members for later post processing.
In order to allow users to mock the input, I need to be able to update a mocked input's members. Furthermore, the input may not be a mock, so I would prefer a solution oblivious to the type of element received.
Simply put, I have a function which receives an object and attempts to set one of its properties:
func(object a)
a.m = 5;
Which I want to test by mocking its input a, using the Moq library. Unfortunately, my test failed, since mocked objects' members need to be set using Mock.SetUpGet, instead of standard member assignment.
What would be a good way to test such a function, without changing it?
In order to be able to mock and test it, the property must be virtual, but if that's the case you can use the SetupSet method, rather than SetupGet:
public class A
{
public virtual int m { get; set; }
}
[TestFixture]
public class Tests
{
public static void SetProperty(A a)
{
a.m = 5;
}
[Test]
public void IsThePropertySet()
{
var x = new Mock<A>();
x.SetupSet<int>(a => a.m = 5).Verifiable();
SetProperty(x.Object);
x.Verify();
}
}
Your function should have getters and setters anyway.
And a good way of testing whether your functions work is to do a small-scale test. Initialize an object and send that in to your method, seeing whether it does what you want.
public class myClass
{
public int number;
public void setNumber(int nNum)
{
number = nNum;
}
public int getNumber()
{
return number;
}
}
class Program
{
static void myMethod(myClass obj, int nNumb)
{
//obj.setNumber(nNumb);
obj.number = nNumb;
}
static void Main(string[] args)
{
myClass myObj = new myClass();
myMethod(myObj, 3);
//Console.WriteLine(myObj.getNumber());
Console.WriteLine(myObj.number);
Console.ReadLine();
}
}
}
Output: 3

How to call public static methods in Unit Test

Hi I have a simple method as following and need to know how I can call it in Unit Test in Visual Studio
public class myClass
{
public static bool Test(string value, string regex)
{
if (Regex.IsMatch(value, regex, RegexOptions.IgnoreCase))
return true;
return false;
}
}
here is what I have sofar
[TestMethod]
public void TestMethod_Test()
{
string value = "myValue";
string regex = "&##<>\s\\\$\(\)";
PrivateType pt = new PrivateType(typeof(myClass));
bool actualresult = (bool)pt.InvokeStatic("Test", new object[] { value, regex });
bool expectedResult = false;
Assert.AreEqual(actualresult, expectedResult);
}
You do not want to be using reflection. Just call the method directly:
[TestMethod]
public void TestMethod_Test()
{
string value = "myValue";
string regex = "&##<>\s\\\$\(\)";
var result = ClassContainingTest.Test(value, regex);
Assert.AreEqual(false, result);
}
If ClassContainingTest isn't public, then it isn't sensible to be trying to unit test Test. Only test publicly accessible functionality.
If both the method and the class are public, then you could simply call
myClass.Test(value, regex);
If myClass is protected you could do:
public myClassWrapper : myChild
{
public static bool Test(string text, string regex)
{
return myClass.Test(text, regex);
}
}
If myClass is internal or 'default' (no visibility specified, which seems to be your case) you can make make the assembly that contains myClass friendly towards the test library by adding an InternalsVisisbleTo attribute to it:
[assembly:InternalsVisibleTo("myClassLibrary")]
That way your test project should be able to just invoke the Test Method directly as if it were public.
If the class is not public or you cannot alter the definition of the class, consider finding a method that internally uses the method you want to test and use that to verify the behavior. (e.g. test that the method that uses the Test method works correctly, thereby you test that the Test method works correctly.

How can I assert that a particular method was called using NUnit?

How can I test that a particular method was called with the right parameters as a result of a test? I am using NUnit.
The method doesn't return anything. it just writes on a file. I am using a mock object for System.IO.File. So I want to test that the function was called or not.
More context is needed. So I'll put one here adding Moq to the mix:
pubilc class Calc {
public int DoubleIt(string a) {
return ToInt(a)*2;
}
public virtual int ToInt(string s) {
return int.Parse(s);
}
}
// The test:
var mock = new Mock<Calc>();
string parameterPassed = null;
mock.Setup(c => x.ToInt(It.Is.Any<int>())).Returns(3).Callback(s => parameterPassed = s);
mock.Object.DoubleIt("3");
Assert.AreEqual("3", parameterPassed);
You have to use some mocking framework, such as Typemock or Rhino Mocks, or NMocks2.
NUnit also has a Nunit.Mock, but it is not well-known.
The syntax for moq can be found here:
var mock = new Mock<ILoveThisFramework>();
// WOW! No record/reply weirdness?! :)
mock.Setup(framework => framework.DownloadExists("2.0.0.0"))
.Returns(true)
.AtMostOnce();
// Hand mock.Object as a collaborator and exercise it,
// like calling methods on it...
ILoveThisFramework lovable = mock.Object;
bool download = lovable.DownloadExists("2.0.0.0");
// Verify that the given method was indeed called with the expected value
mock.Verify(framework => framework.DownloadExists("2.0.0.0"));
Also, note that you can only mock interface, so if your object from System.IO.File doesn't have an interface, then probably you can't do. You have to wrap your call to System.IO.File inside your own custom class for the job.
By using a mock for an interface.
Say you have your class ImplClass which uses the interface Finder and you want to make sure the Search function gets called with the argument "hello";
so we have:
public interface Finder
{
public string Search(string arg);
}
and
public class ImplClass
{
public ImplClass(Finder finder)
{
...
}
public void doStuff();
}
Then you can write a mock for your test code
private class FinderMock : Finder
{
public int numTimesCalled = 0;
string expected;
public FinderMock(string expected)
{
this.expected = expected;
}
public string Search(string arg)
{
numTimesCalled++;
Assert.AreEqual(expected, arg);
}
}
then the test code:
FinderMock mock = new FinderMock("hello");
ImplClass impl = new ImplClass(mock);
impl.doStuff();
Assert.AreEqual(1, mock.numTimesCalled);
In Rhino Mocks where is a method called AssertWasCalled
Here is a way to use it
var mailDeliveryManager = MockRepository.GenerateMock<IMailDeliveryManager>();
var mailHandler = new PlannedSending.Business.Handlers.MailHandler(mailDeliveryManager);
mailHandler.NotifyPrinting(User, Info);
mailDeliveryManager.AssertWasCalled(x => x.SendMailMessage(null, null, null), o => o.IgnoreArguments());

Categories

Resources