"In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use."
In simple words, we can say that unit testing is a function that tests a unit of work.
For example, a divide function is a unit of work.
- namespace Calculators
- {
- public class Divides
- {
- public static int divide(int numerator ,int denominator)
- {
- int result = numerator / denominator;
- return result;
- }
- }
- }
Popular Unit Testing frameworks
MSTest is by default integrated with Visual Studio.
There are three steps to create a UNIT Test
- Add a unit test project by your solution
- Decorate the class the contains test methods with TestClass attribute
- Decorate the test method with TestMathod attribute
That function which uses for testing we decorate with TestMethod attribute and Test class is decorated with TestClass attribute.
Step 1 - How to add Unit Test project in project solution?
- Right-click on the solution on Add New Project.
- Under the Visual C# click on Test option
- Seen in the screenshot I have selected unit test project (.net Framework)
After the add Unit test project in the solution. Create a test class which contains all test methods, class decorate with TestClass Attribute and methods decorate with TestMethod Attribute.
Add reference of the calculators class library project into the Calculator.Test project see below screenshot,
Test case defined in three sections,
- Arrange: initializes objects and set the value of the data that is passed to the method being tested
- Act: invokes the method being tested
- Asset: verifies that the method being tested behaves as expected
- namespace Calculator.Test
- {
- [TestClass]
- public class CalculatorTest
- {
- [TestMethod]
- public void Test_Divide()
- {
-
- int expected = 10;
- int numerator = 100;
- int denominator = 10;
-
- int actual= Calculators.Divides.divide(numerator, denominator);
-
- Assert.AreEqual(expected, actual);
- }
- }
- }
Assert class has many static method currently I have used AreEqual() this is use for check expected value is equal to actual value.
Naming Conventions is an important part for the unit test case, so I have changes name above test method name as per Roy Osherove’s naming strategy.
[UnitOfWork_StateUndertTest_ExpectedBehavior]
We got three method in the test class,
- Divide positive number (Divide_PositiveNumbers_ReturnsPositiveQuotient)
- Divide positive numerator with denominator (Divide_PositiveNumeratorAndNegativeDenominator_ReturnsNegativeQuotient)
- Divide negative number (Divide_NegativeNumber_ReturnsPositiveQuotient)
- namespace Calculator.Test
- {
- [TestClass]
- public class CalculatorTest
- {
- [TestMethod]
- public void Divide_PositiveNumbers_ReturnsPositiveQuotient()
- {
-
- int expected = 10;
- int numerator = 100;
- int denominator = 10;
-
- int actual= Calculators.Divides.divide(numerator, denominator);
-
- Assert.AreEqual(expected, actual);
- }
- [TestMethod]
- public void Divide_PositiveNumeratorAndNegativeDenominator_ReturnsNegativeQuotient()
- {
-
- int expected =-10;
- int numerator = 100;
- int denominator = -10;
-
- int actual = Calculators.Divides.divide(numerator, denominator);
-
- Assert.AreEqual(expected, actual);
- }
- [TestMethod]
- public void Divide_NegativeNumber_ReturnsPositiveQuotient()
- {
-
- int expected = 10;
- int numerator = -100;
- int denominator = -10;
-
- int actual = Calculators.Divides.divide(numerator, denominator);
-
- Assert.AreEqual(expected, actual);
- }
-
- [TestMethod]
- [ExpectedException(typeof (DivideByZeroException))]
- public void Divide_DenominatorIsZero_ThrowDivideByZeroException()
- {
-
-
- int numerator = 100;
- int denominator = 0;
-
- try
- {
-
- Calculators.Divides.divide(numerator, denominator);
- }catch(Exception ex)
- {
- Assert.AreEqual("denominator is zero", ex.Message);
- throw;
- }
-
- }
- }
- }
Run the Unit Test Case
We can run the unit test in several ways,
- Run all test
- Run single test
- Run all test for the only selected test class
See below in the explorer window,
Right-click on the selected test class and select Run selected unit tests option as the same way we run a single unit test select particular Test Method to go to the same option which using in the above line.
Grouping Unit Tests
Grouping Unit test in test Explorer
- OutCome
- Duration
- Class
- Project
- Traits
Code Coverage in the Unit Test
Definition as per Wikipedia,
Test coverage is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs. A program with high test coverage, measured as a percentage, has had more of its source code executed during testing, which suggests it has a lower chance of containing undetected software bugs compared to a program with low test coverage.
URL:
In the simple term, Code coverage is finding out how much of our application code is being tested by automated unit tests
Now, I am using AxoCover For check Code coverage scope. The Code coverage scope is three-level
- Assembly level
- Class level
- Method level
Below screenshot display the report of coverages. Code coverage report show percentage of the code coverage at the assembly level, class and method level.
Having good code coverage does not mean the code is being tested well.
Testing Exceptions
Testing exceptions with showing specific messages. Check in the below code screenshot
The method name is decorate with [ExpectedException(typeof (DivideByZeroException))] attribute
In the code snippet, I have use try-catch block for specific message Asserting.
If we do not require to check any specific exception message then we can remove a try-catch block.
- [TestMethod]
- [ExpectedException(typeof (DivideByZeroException))]
- public void Divide_DenominatorIsZero_ThrowDivideByZeroException()
- {
-
-
- int numerator = 100;
- int denominator = 0;
-
- try
- {
-
- Calculators.Divides.divide(numerator, denominator);
- }catch(Exception ex)
- {
- Assert.AreEqual("denominator is zero", ex.Message);
- throw;
- }
Assert
An Assertion is using to verifying the expected value to actual value.
Mstest provides three different class for the assertion
- Assert
- collectionAssert
- StringAssert
In this article, I have used reference of Wikipedia and kudvenkat unit testing lecture series.