Unit Testing: Prepared By: Priya Sharma Trivedi
Unit Testing: Prepared By: Priya Sharma Trivedi
Prepared by:
Priya Sharma Trivedi
Agenda
Introduction
The need of testing and it’s Terminology
Unit Testing
Right B.I.C.E.P.s.?
Benefits of Unit Testing
Naming standards for unit tests
The Problem
A vicious cycle – the more pressure a you (Developer) feel, the fewer
tests you writes. The fewer tests you write, the less productive you are
and the less stable your code becomes. The less productive and
accurate you are, the more pressure you feel.
With unit tests we can find defects much sooner and easier, continuously
removing them before adding new features
Software
developer
Unit-test Component
What we propose:
JUnit
NUnit
SimpleTest
A framework is missing
Designing unit tests
It runs quickly. Part of the point is to make it so that you’re able to run them
regularly, so speed plays into that.
It’s much easier to fix a bug you introduced five minutes ago than one
you did five weeks ago…
Test Case Test Case TC Input Expected Actual Result Pass / Remarks
Purpose Procedure Data Result Fail
ID which can What to How to Input What What actually Pass / Comment
be referred to Test Test Data should happens. This Fail if any
in other docs happen? column can
like “TM” be omitted
“Root Cause when defect
Analysis of recording tool
defects etc is used.
Documentation: Early on document all the Test Cases needed to test your
code. Document the Test Cases, actual Results when executing the Test
Cases, Response Time of the code for each test case.
Important advantages if the test cases and the actual execution of test
cases are well documented.
Documenting Test Cases prevents oversight.
Documentation clearly indicates the quality of test cases.
If the code needs to be retested we can be sure that we did not
miss anything.
It provides a level of transparency of what was really tested during
unit testing. This is one of the most important aspects.
It helps in knowledge transfer in case of employee attrition.
Sometimes Unit Test Cases can be used to develop test cases for
other levels of testing
What should be tested when Unit Testing
It could be a screen or a component or a web
service
Test Cases to verify all the screen Test cases to verify the
elements that need to appear on the spelling/font/size of all the “labels” or
screens. text that appears on the screen.
Test Cases such that every line of code Test Cases such that every condition in
in the unit is tested at least once in a case of “conditional statements” is
test cycle. tested once.
Never write
a test that Use mock
succeeds the Objects
1st time
Charles'
Six Rules
of Unit
Testing
Start with
Loose
null case, or
coupling &
something
testability go
that doesn’t
hand in hand
work
Try
something
trivial to
make the test
work
Unit Testing Guidelines
If you don’t know what “right” would be, then how can you test?
How do you know if your code works?
Perhaps requirements not known or stable
Unexpected orderings
inverse
E.g. square and square-root. Insertion then deletion.
Beware errors that are common to both your operations
If e.g. you are devising a square root for an embedded system without float capability,
you could test it (in the host environment) using the standard implementation, like
so:
public void testSquarerootUsingStd( ) {
double number=3830900.0;
double root1= mySquareRoot ( number ) ;
double root2= Math.sqrt ( number ) ;
assertEquals ( root2 , root1 , 0.0001 ) ;
}
Right-BICEP
Performance
A normal unit test should test for the functional requirements. But if the
non-functional requirement performance or speeds depend on the size of
the data, you should test that too.
Perhaps absolute performance, or
It provides a strict, written contract that It find problems early in the development
the piece of code must satisfy. cycle.
It allows the programmer to refactor code It may reduce uncertainty in the units
at a later date, and make sure the module themselves and can be used in a bottom-up
still works correctly (i.e. regression testing). testing style approach.
It provides a sort of living documentation of By testing the parts of a program first and
the system. Developers looking to learn
what functionality is provided by a unit and then testing the sum of its parts, integration
how to use it. testing becomes much easier.
Result
# of Test Cases (Test Development Phase)
# of Test Cases Executed (Test Execution Phase)
# of Test Cases Passed (Test Execution Phase)
# of Test Cases Failed (Test Execution Phase)
# of Test Cases Under Investigation (Test Development Phase)
# of Test Cases Blocked (Test dev/execution Phase)
# of Test Cases Re-executed (Regression Phase)
# of First Run Failures (Test Execution Phase)
Total Executions (Test Reporting Phase)
Total Passes (Test Reporting Phase)
Total Failures (Test Reporting Phase)
Test Case Execution Time ((Test Reporting Phase)
Test Execution Time (Test Reporting Phase)
Result…Cont……
% Complete
% Defects Corrected
% Test Coverage
% Rework
% Test Cases Passed
% Test Effectiveness
% Test Cases Blocked
% Test Efficiency
1st Run Fail Rate
Defect Discovery Rate
Overall Fail Rate
Naming standards for unit tests
Test name should include the expected input or state and Public int Sum(params int[]
the expected result for that input or state values), Public int
Sum_NumberIsIgnored()
Test name should be presented as a statement or fact of Public void
life that expresses workflows and outputs SumNegativeNumber2()
Test name should include name of tested method or class. Public void
[MethodName_StateUnderTest_ExpectedBehavior] Sum_NegativeNumAs1stParam_E
xcepThrown()
Variable names should express the expected input and BAD_DATA or EMPTY_ARRAY or
state NON_INITIALIZED_PERSON
Naming standards for unit tests- Cont……
CONSIDER: Separating your Tests If you have a requirement where you want to test in
from your Production Code. production or verify at the client's side, you can
accomplish this simply by bundling the test library with
your release.
CONSIDER: Deriving common Fixtures In scenarios where you are testing sets of common
from a base Fixture classes or when tests share a great deal of duplication,
consider creating a base TestFixture that your Fixtures
can inherit.
CONSIDER: Using Categories instead Suites represent significant developer overhead and
of Suites or Specialized Tests maintenance. Categories offer a unique advantage in the
For example, you could execute only UI and at the command-line that allows you to specify
"Stateful" tests against an environment to which categories should be included or excluded from
validate a database deployment. execution.
CONSIDER: Splitting Test Libraries (You can always go back)
into Multiple Assemblies
AVOID: Empty Setup methods you should only write the methods that you need today.
Adding methods for future purposes only adds visual
noise for maintenance purposes
Naming standards for unit tests- Cont……
DO: Name Tests after Functionality The test name should match a specific unit of
For example, a test with the name functionality for the target type being tested.
CanDetermineAuthenticatedState provides more Some key questions you may want to ask
direction about how authentication states are yourself: "what is the responsibility of this class?"
examined than Login. "What does this class need to do?" Think in terms
of action words.
DO: Document your Tests Most tests require special knowledge about the
A few comments here and there are often just the functionality your testing, so a little
right amount to help the next person understand documentation to explain what the test is doing is
what you need to test and how your test helpful.
approaches demonstrates that functionality.
CONSIDER: Use "Cannot" Prefix for Expected Since Exceptions are typically thrown when your
Exceptions application is a performing something it wasn't
Examples: CannotAcceptNullArguments, designed to do, prefix "Cannot" to tests that are
CannotRetrieveInvalidRecord. decorated with the [ExpectedException] attribute.
CONSIDER: Using prefixes for Different If your application has features that differ slightly
Scenarios for application roles, it's likely that your test
Some have adopted a For<Scenario> syntax names will overlap.
(CanGetPreferencesForAnonymousUser). Other
have adopted an underscore prefix _<Scenario>
(AnonymousUser_CanGetPreferences).
Naming standards for unit tests- Cont……
AVOID: Ignore Attributes with no Tests that are marked with the Ignore attribute
explanation should include a reason for why this test has been
disabled.
AVOID: Naming Tests after If you find that your tests are named after the
Implementation methods within your classes, that's a code smell
If you changed your method name, would that you're testing your implementation instead of
the test name still make sense? your functionality.
AVOID: Using underscores as word- PascalCase should suffice. Imagine all the time you
separators save not holding down the shift key.
use_underscores_as_word_separators_fo
r_readability,
AVOID: Unclear Test Names Sometimes we create tests for bugs that are caught
it's important to avoid giving them vague late in the development cycle, or tests to
test names that represent a some external demonstrate requirements based on lengthy
requirement like FixForBug133 or requirements documentation. As these are usually
TestCase21. pretty important tests (especially for bugs that
creep back in).
Naming standards for unit tests- Cont……
CONSIDER: Defining Custom Category As Categories are sensitive to case and spelling,
Attributes you might want to consider creating your own
Category attributes by deriving from
CategoryAttribute.
“Unit Testing” is the most important one. Detecting and fixing bugs early
on in the Software Lifecycle helps reduce costly fixes later on. The Above
article explains how Unit Testing should be done and the important points that
should be considered when doing Unit Testing.