Create Xunit Test Methods dynamicaly based on Excel data - c#

Testing team will create test cases in XLS (100+ cases)
I have to create the Test Methods for the each cases dynamically at run time.
I can write the logical part to validate whether the test case is pass or fail, but the only thing I want is how to create the test methods at run time. I am using the Xunit Test project in C#.
Suggest a solution to overcome the problem.

I would try to do some kind of row-testing:
Each line would be a different test run.
[Theory,
InlineData("1", "Description 1", ...),
InlineData("2", "Description 2", ...),
InlineData("3", "Description 3", ...)]
public void Can_get_correct_age_for_date(string sno, string description, ...)
{
// you can access the paramaters here
Console.WriteLine(sno);
Console.WriteLine(description);
// Assert Logic
Assert.Equal(...);
}
In your scenario i think you need to rearrange your Excel file or write yourself some kind of "custom excel parser".
Do you get the idea?

Related

Using Test displayname with DynamicDataDisplayName in MSTest

[TestMethod("My Test Name")] can be use to change the name of a test in MSTest.
DynamicData attribute can be used to run the test on a collection of object where you can customize the datadisplayname for each run.
Unfortunately, when you try to use both for the same test like below, the test is not affected by the display name set.
Any idea if it's possible to get the two attributes working at the same time.
[TestMethod("My Test")]
[DynamicData(nameof(MyTestObject), DynamicDataSourceType.Property, DynamicDataDisplayName = nameof(GetTestDisplayName))]
Thanks

How to write a Theory Test while using source generators?

I'm having some trouble writing a Theory Test in XUnit because I'm using generators and passing them into the function as arguments.
I have these generators
Arb.Register<CustomerGenerator>();
Arb.Register<OptionsGenerator>();
And I'm passing them into my unit tests as such:
public async Task CallOrderServiceTest(List<Options> options, Customer customer)
I want to write a Theory test that takes in a DateTime and a List<DateTime> into this function to lower the amount of code I've written (lots of unit tests are the same, just with different input data).
I've been trying with the examples here but no luck getting what I want.
Ultimately I want to be able to pass in the generated Customer and List<Options> and use 1 test to test multiple inputs of DateTime and List<DateTime>.

Unit Testing for VS2017 project

I have an ASP.NET application (a basic form where I capture some input) in VS2017.
One of the fields on the form is Mark, which is an integer.
I have the following block of code for the Mark, in my .cs file.
[Display(Name = "Mark")]
[Range(1, 10, ErrorMessage = "Mark must be between 1 and 10")]
public int Mark{ get; set; }
I've created a MSTest project for this application to write Unit Tests.
My question is, do you write Test Cases for this block to verify the input value is in the expected range?
If yes, how you write that?
I've started with this.
[DataRow(0, "Mark must be between 1 and 10")]
[DataRow(11, "Mark must be between 1 and 10")]
[DataTestMethod]
public void TestMark_IsMarkValid_NotValid(int mark, string expectedMsg)
{
//Arrange
Student testStudent = new Student();
testStudent.Mark = mark; //this does not throw any error, although the assigned value is outside of the defined range. But it looks like the range validation only applies to the webform.
//Act
string actualMsg = "Mark must be between 1 and 10"; //this is not correct. I was thinking to capture in the actual result the error message yield by the Range validation, but assigning a value outside range doesn't yield any error message.
//Assert
Assert.AreEqual(expectedMsg, actualMsg);
}
Now, not sure if that block should be in scope for unit testing. If it should be, I have a feeling the approach I've taken is not correct.
Any thoughts, please?
Many thanks,
Cosmin
Interesting question. I'm not certain that there is a definitively correct answer. But here are my thoughts :
1) "Mark" is a property. We don't need to unit test a property because Microsoft have already tested that properties work.
2) The attributes do not affect the property, but provide information about the property that others can use. That is why your unit test passes the test for the value. The form uses the attributes, your unit test does not. That is why your unit test can assign any value.
3) If you really want to limit the value of the variable then limit it in the Student class - either by a setter or else explicit get/set and a backing variable - you can never trust any data submitted by the browser.
4) Testing a UI is not easy. We have a test team that tests by hand. We have tried several tools but none is outstanding. Keep your business logic out of your UI and put it in business classes where it can be easily tested.
So, to answer your question, I personally would not test that the attribute functions in a unit test.
I hope that helps.

how to organize test data in integration tests

I am working on a large test project consisting of thousands of integration tests.
It is a bit messy with lots of code duplication. Most tests are composed of several steps, and a lot of "dummy" objects are created. With dummy I mean something like this:
new Address {
Name = "fake address",
Email = "some#email.com",
... and so on
}
where it often really doesn't matter what the data is. This kind of code is spread out and duplicated in tests, test base classes, and helpers.
What I want is to have a single "test data builder", having a single responsibility, generate test data which is consumed by the tests.
One approach is to have a class with a bunch of static methods like following:
Something CreateSomething(){
return new Something {
// set default dummy values
}
and an overload:
Something CreateSomething(params){
return new Something {
// create the Something from the params
}
Another approach is to have xml files containing the data but i am afraid then it would be too far away from the tests.
The goal is to move this kind of code out of the tests because right now the tests are big and not readable. In a typical case, of 50 lines of test code, 20-30 is of this kind of code.
Are there any patterns for accomplishing this? Or any example of big open source codebase with something similar that I can have a look at?
For code, use a simple method chaining builder pattern:
public class TestOrderBuilder
{
private order = new Order();
// These methods represent sentances / grammar that describe the sort
// of test data you are building
public AnObjectBuilder AddHighQuantityOrderLine()
{
//... code to add a high quantity order line
return this; // for method chaining
}
// These methods represent sentances / grammar that describe the sort
// of test data you are building
public AnObjectBuilder MakeDescriptionInvalid()
{
//... code to set descriptions etc...
return this; // for method chaining
}
public Order Order
{
get { return this.order; }
}
}
// then using it:
var order = new TestOrderBuilder()
.AddHighQuantityOrderLine()
.MakeDescriptionInvalid()
.Order
I would shy away from xml files that specify test dependencies.
My thought process stems from a lack of refactoring tools that these xml files cannot take advantage of within the Visual Studio ecosystem.
Instead, I would create a TestAPI.
This API will be responsible for serving dependency data to test clients.
Note that the dependency data that is being requested will already be initialized with general data and ready to go for the clients that are requesting the dependencies.
Any values that serve as required test inputs for a particular test would be assigned within the test itself. This is because I want the test to self document its intent or objective and abstract away the dependencies that are not being tested.
XUnit Test Patterns provided me a lot of insight for writing tests.

Unit Testing Methods With File IO

I'm trying to get into the habit of writing unit tests, I've written a few before but they've usually been quite basic...I'd like to start making a move to TDD as i want to improve the quality of my code (design and structure) - reducing coupling, while at the same time hopefully reduce number of regressions which slip through to a testable build.
I have taken a relatively simple project i work on to begin with. The resultant program watches a folder and then acts on files within this folder.
Here is a typical example of some code extracted from the project:
private string RestoreExtension(String file)
{
var unknownFile = Path.GetFileName(file);
var ignoreDir = Path.GetDirectoryName(file) + "\\Unknown";
string newFile;
//We need this library for determining mime
if (CheckLibrary("urlmon.dll"))
{
AddLogLine("Attempting to restore file extension");
var mime = GetMimeType(BufferFile(file, 256));
var extension = FileExtensions.FindExtension(mime);
if (!String.IsNullOrEmpty(extension))
{
AddLogLine("Found extension: " + extension);
newFile = file + "." + extension;
File.Move(file, newFile);
return newFile;
}
}
else
{
AddLogLine("Unable to load urlmon.dll");
}
AddLogLine("Unable to restore file extension");
if (!Directory.Exists(ignoreDir))
{
Directory.CreateDirectory(ignoreDir);
}
var time = DateTime.Now;
const string format = "dd-MM-yyyy HH-mm-ss";
newFile = ignoreDir + "\\" + unknownFile + "-" + time.ToString(format);
File.Move(file, newFile);
return String.Empty;
}
Questions :
How can i test a method using IO?
I don't really want to be using a real file as this would be slow (and more of an integration test?), but i cant really see another way. I could add a switchable IO abstraction layer, but this sounds to me like it may unnecessarily complicate code...
Is a project like this worth unit testing?
By that i mean, is it too simple. Once you strip out .Net and 3rd party library calls there is not much left...So is it a case that the amount of work to make it testable means its not a good candidate to test?
A lot of the methods in this project are private, as this project happens to be a windows service. I've read you should only really test methods which are externally visible (public or exposed through an interface), it is unlikely in this case however that i want to expose any of my own methods. So is this project worth testing (as id probably need to either change method access modifiers to public or add some attributes so that NUnit can see them)?
Regarding how to test File I/O:
A common way of doing this is encapsulating File I/O in a wrapper class. For example:
public class FileHandler : IFileHandler
{
public string GetFilename(string name)
{
return System.IO.GetFileName(name);
}
public string GetDirectoryName(string directory)
{
return System.IO.GetDirectoryName(directory);
}
}
public interface IFileHandler
{
string GetFilename(string name);
string GetDirectoryName(string directory);
}
In your method under test, you only program against the interface. When you run your unit test, you would use a mock object which returns predefined values. For this, you could use Moq.
This is a bit work to do but then you do not need to test File I/O as well.
Best
Jan
How can i test a method using IO?
By introducing abstraction over the .NET's IO libraries and then using real implementation (BCL) in application, and fake (mocked) one in unit test. Such abstraction is fairly simple to write on your own, but those projects already exist (eg. System.IO.Abstraction) so reinventing wheel is pointless, especialy in such trivial matter.
I don't really want to be using a real file as this would be slow
This is correct, in test you want to use fake (mock) objects.
Is a project like this worth unit testing?
Every project is worth testing and you will test it in one way or another (in most extreme case, by manually executing application and doing good, old click-and-wait testing).
Note that almost always it is too time consuming to manually test 10 edge cases of complex parser method which everytime requires you to load large file and wait for results. This is where automated tests in isolated environment help greatly. It is the same with your code - file system, web service, they all introduce large overhead before you can get to actual business logic. Must isolate.
A lot of the methods in this project are private (...) I've read you should only really test methods which are externally visible
Correct again, you should be testing public contract. However, if private stuff gets big enough to test it, most of the times it's a good indicator it is also big enough to put it in its own class. Note that changing members access modifiers only for the unit test usage is not the best idea. Almost always it's better to extract-class/method refactor.
You can do that using Microsoft Fakes. First generate a fake assembly for System.dll - or any other package and then mock expected returns as in:
using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
System.IO.Fakes.ShimDirectory.ExistsString = (p) => true;
System.IO.Fakes.ShimFile.MoveStringString = (p,n) => {};
// .. and other methods you'd like to test
var result = RestoreExtension("C:\myfile.ext");
// then you can assert with this result
}
I'm pretty new with TDD too, but I think I can get some suggestion to you:
About IO testing. You can use mock objects. Create a mock for the method you want to test and compare it with real passed in value. In Moq Framework it looks like that:
var mock = new Mock<IRepository<PersonalCabinetAccount>>();
mock.Setup(m => m.RemoveByID(expectedID))
.Callback((Int32 a) => Assert.AreEqual(expectedID, a));
var account = new PersonalCabinetAccount {ID = myID};
var repository = mock.Object;
repository.RemoveByID(account.myId);
Absolutely, yes. If you want to get a habit, you need to test everything, i suppose. That way knowledge comes ;)
You can use InternalsVisibleTo attribute to avoid visibility issues.
test methods which are externally visible
I think this one about enterprise programming. just a spare of time with your own trusted code.
Hope my point can help you.

Categories