Testing Framework
Now, let's talk about MSTest, its a unit testing framework that allows us to create and run the tests
We can use MSTest testing framework for writing our unit/integration/e2e(UI tests)
Before we jump into details of MSTest, we will talk about different types of tests and the testing pyramid
Types of tests
Unit
Integration
E2E
Above image is self-explanatory, so one should write as many unit tests as he can for testing application
As you climb the pyramid, test execution time increases that is unit tests are faster than UI
Also, the brittleness of test increases that is UI test is most brittle compared to the unit test.
I have created a simple project to calculate tax based on the price of an item, we will walk through the code and then write some unit tests wherein I will explain some functionalities of MSTest framework
Check below code
Here we have a TaxManager class which calculates the tax based on the price of an item.
If the price is less than 10000 then price/100 is the tax amount else price/1000 is the tax amount.
Self-explanatory code, now we will add unit tests for CalculateTax method, to do so right click anywhere from the method and click "create unit tests"
This will open the below window
Here you can see the Test framework is MSTest
It will create a new project for our tests
Click ok and it created below test template for us to start writing our tests
Here TestClass and TestMethod are attributes used by MSTest framework to identify tests
Now we will add a test for calculating the tax when the amount is less than 10000, we expect the tax to be amount/100
Every test you write should follow Arrange Act Assert Pattern (AAA)
Arrange- Prepare the test data
Act- Perform the action
Assert- Verify the expected outcome
Here in our tests above we calculated our expected tax and called the calculate tax method and finally we asserted that the actual and expected tax values match
To run the tests open the test explorer and right click the test and click "run selected tests"
You can run all the test for the class by right click on the class and click "run selected tests"
We will add another test for calculating the tax when the amount is greater than 10000, we expect the tax to be amount/1000
Run the test and you can see results are green(Passing).
Now, we will add a failing test case.
Suppose we set price as negative then we expect the code to throw Argument Exception, currently, we have not handled this case.
We will write the test case first which will fail
So if the code return ArgumentException then the test will pass else it will fail.
After running the test, we can see it fails with below error message
Message: Test method did not throw expected exception System.ArgumentException.
Now we will handle this case in our code to fix this issue, check below
So before calculating the tax now we check if the value is less than zero if that's the case then we throw ArgumentException.
Re-run our failing test, now you would find that it is passing.
Now we will talk about some attributes of the MSTest framework
Test Initialize - This method will run before each test , you can add code to prepare for testing here.
Test Cleanup - This method will run after each test case, you can add code to release resources here.
When you run all of your tests, you can see Test initialize and Test cleanup methods are called before and after each test method.
This is enough to get us started 😊
We can use MSTest testing framework for writing our unit/integration/e2e(UI tests)
Before we jump into details of MSTest, we will talk about different types of tests and the testing pyramid
Types of tests
Testing smallest units of code
Integration
Units of code are integrated with each other and tested
E2E
Verify system meets requirements, testing the entire system from end to end
Test Pyramid
Above image is self-explanatory, so one should write as many unit tests as he can for testing application
As you climb the pyramid, test execution time increases that is unit tests are faster than UI
Also, the brittleness of test increases that is UI test is most brittle compared to the unit test.
I have created a simple project to calculate tax based on the price of an item, we will walk through the code and then write some unit tests wherein I will explain some functionalities of MSTest framework
Check below code
namespace MSTestDemo { public class TaxManager { private int price; public TaxManager(int price) { this.price = price; } public int CalcualteTax() { if (price < 10000) return price / 100; else return price / 1000; } } class Program { static void Main(string[] args) { TaxManager taxManager = new TaxManager(1000); int tax = taxManager.CalcualteTax(); Console.WriteLine("Calculated Tax: " + tax.ToString()); Console.Read(); } } }
Here we have a TaxManager class which calculates the tax based on the price of an item.
If the price is less than 10000 then price/100 is the tax amount else price/1000 is the tax amount.
Self-explanatory code, now we will add unit tests for CalculateTax method, to do so right click anywhere from the method and click "create unit tests"
This will open the below window
Here you can see the Test framework is MSTest
It will create a new project for our tests
Click ok and it created below test template for us to start writing our tests
namespace MSTestDemo.Tests { [TestClass()] public class TaxManagerTests { [TestMethod()] public void CalcualteTaxTest() { Assert.Fail(); } } }
Here TestClass and TestMethod are attributes used by MSTest framework to identify tests
Now we will add a test for calculating the tax when the amount is less than 10000, we expect the tax to be amount/100
namespace MSTestDemo.Tests { [TestClass()] public class TaxManagerTests { [TestMethod()] public void CalcualteTaxTest_When_Price_Less_Than_10000() { //Arrange int price = 5000; TaxManager taxManager = new TaxManager(price); int expectedTax = price/ 100; //Act int actualTax = taxManager.CalcualteTax(); //Assert Assert.AreEqual(expectedTax, actualTax); } } }
Every test you write should follow Arrange Act Assert Pattern (AAA)
Arrange- Prepare the test data
Act- Perform the action
Assert- Verify the expected outcome
Here in our tests above we calculated our expected tax and called the calculate tax method and finally we asserted that the actual and expected tax values match
To run the tests open the test explorer and right click the test and click "run selected tests"
You can run all the test for the class by right click on the class and click "run selected tests"
We will add another test for calculating the tax when the amount is greater than 10000, we expect the tax to be amount/1000
[TestMethod()] public void CalcualteTaxTest_When_Price_greater_Than_10000() { //Arrange int price = 50000; TaxManager taxManager = new TaxManager(price); int expectedTax = price / 1000; //Act int actualTax = taxManager.CalcualteTax(); //Assert Assert.AreEqual(expectedTax, actualTax); }
Run the test and you can see results are green(Passing).
Now, we will add a failing test case.
Suppose we set price as negative then we expect the code to throw Argument Exception, currently, we have not handled this case.
We will write the test case first which will fail
[TestMethod()] [ExpectedException(typeof(ArgumentException))] public void CalcualteTaxTest_When_Price_is_negative() { //Arrange int price = -1; TaxManager taxManager = new TaxManager(price); int expectedTax = price / 100; var expectedTaxNew = Math.Round (Convert.ToDecimal(expectedTax)); //Act decimal actualTax = taxManager.CalcualteTax(); }Here you can notice that we do not have an assertion. We are using ExpectedException attribute to specify which type of exception we are expecting.
So if the code return ArgumentException then the test will pass else it will fail.
After running the test, we can see it fails with below error message
Message: Test method did not throw expected exception System.ArgumentException.
Now we will handle this case in our code to fix this issue, check below
namespace MSTestDemo { public class TaxManager { private int price; public TaxManager(int price) { this.price = price; } public decimal CalcualteTax() { if (price < 0) throw new ArgumentException("Price not valid"); if (price < 10000) return price / 100; else return price / 1000; } } class Program { static void Main(string[] args) { TaxManager taxManager = new TaxManager(1000); decimal tax = taxManager.CalcualteTax(); Console.WriteLine("Calculated Tax: " + tax.ToString()); Console.Read(); } } }
So before calculating the tax now we check if the value is less than zero if that's the case then we throw ArgumentException.
Re-run our failing test, now you would find that it is passing.
Now we will talk about some attributes of the MSTest framework
Test Initialize - This method will run before each test , you can add code to prepare for testing here.
Test Cleanup - This method will run after each test case, you can add code to release resources here.
[TestInitialize] public void testInitialize() { Console.WriteLine("Test Started"); } [TestCleanup] public void testCleanUp() { Console.WriteLine("Test Ended"); }
When you run all of your tests, you can see Test initialize and Test cleanup methods are called before and after each test method.
This is enough to get us started 😊
Comments
Post a Comment