2. ◦ Is testing only a QA job?
◦ Why should we bother?
◦ What if I don't have tests?
3. Testing is more of a Developer Job than QA
It’s my responsibility towards others
Another developer can quick start
Another developer will not spend time debugging your issues
Losing time on Debugging Production Issues
No tests during development, will lead to more debug time on a production bug day.
You will not be there all the time.
4. Test Driven Design
Enforces Design for Testability
◦ Programming to Interfaces
◦ Modularization
◦ Avoiding Statics when possible
Test First Approach
◦ May lead to minor changes in design
Finally TDD is a personal choice, no one can force you to use or not use
it!!
5. It puts you into the customer's shoe.
It gives you an insight on completeness.
Feature wise development.
Identification of newer scenarios.
It helps identifying & solidifying requirements.
Once well written, it serves you for the life time of an
application.
6. People are not much aware of its benefits
Of course it is time consuming, both writing and reviewing tests.
Maintainability is an issue if not done properly
7. Unit Test - A small piece of code to check another small piece of code.
Few criteria
◦ Must be very Simple.
◦ Must test only one thing
◦ Must help in understanding the production code
Our Aim from Unit Testing
◦ Make it Fail
◦ Make it Work
◦ Make it Better (better here means Simple)
8. Write a Test
Run a Test
Review Results
REPEAT
9. Making Unit Tests Trustworthy
◦ Code coverage
◦ Must test valid logic
◦ Introduce bugs and re run
◦ Start with Failing Test
◦ Don’t use production code in test
◦ Do not change production code if no failing tests
◦ Never change or remove a test (Of course there are exceptions to this rule)
◦ Must Not contain logic
◦ Know the difference between UT and IT
10. Creating Maintainable Unit Test
◦ Test only public methods
◦ Enforce Test Isolation
◦ Avoid Multiple Asserts in one test
Creating Maintainable Unit Test
◦ Follow Naming Conventions Test_Scenario_ExpectedBehavior
◦ If testing with multiple parameters still use the same name with number
suffix
11. Runs in memory
Uses no external systems
Should be fast
Easily Repeatable
Consistent irrespective of where they run.
Should not be dependent on the third party services or resources
12. Write a Test
◦ @Test methods, no arguments, no returns
◦ Biggest impact is Naming Conventions
◦ Unit Testing is about Arrange, Act and Assert
Arrange - create an instance of the class on which you want to act.
Act - invoking the method which is to be tested
Assert - most important part, validating the result
◦ Write tests for Valid data first
** If you do not assert it, then there is no point of this unit test. expected value to actual value.
people tend to swap them which must be taken into account.
13. Run a Test (Using JUnit)
◦ Use Runners from the Frameworks
Runners are used for running test classes
@Runwith specifies the runner - For e.g. @RunWith(SpringJUnit4ClassRunner.class)
JUnit tests are started using the JUnitCore class (JUnitCore.runClasses(MyTestClass.class);)
◦ You can use Suite Runners
Suite are collection of tests
@Suite invokes the Suite Runner
@SuiteClasses (to specify all the classes this suite will run)
Review Results
◦ Verification and Improvements happen here.
Frameworks like Mockito provide MockitoJUnitRunner for automated mock initialization.
14. What should be the first step after checking out the code?
How many Unit Test Cases one should have?
◦ Consider a simple method with two arguments and a Boolean return
15. Mock vs Stubs
Subject of Assertion is called a Mock Object –
◦ We can have multiple stubs for a test. But may want to have just one mock
object.
Everything else is a Stub.
Why do we need Mocks?
◦ We cannot simulate all possible situations, downtimes, network error,
Exceptions
Mock Frameworks are actually Isolation Frameworks. Mockito,
JMock, EasyMock, MockServer (http://www.mock-server.com/)
Is testing only a QA job?
We are creative people and we have important code to write, why should we bother wasting our precious time in writing test code which doesn't even run in production ?
What if I don't have tests?
The development process is the one where you can make a significant impact. TDD is a fancy term and many of us interpret it in our own fancy ways. Many of us also consider writing the Unit Tests first is TDD.
TDD means Test Driven Development
Test Driven Design is one way of doing it. Few experts start with a test, they have a design somewhere in their mind and they start writing tests and then implement the design if the test fails.
Test First Approach - Most of us follow this, there is a well drafted design, everyone starts writing test code and then test against the design, fix failures and re test and so on. This may force us to change our designs some time. We must always design for Testability (for e.g. programming to interfaces, using public method and not having too many static variables.)
Far or less TDD is a personal choice, if you say that my team is not allowing me, or they do not prefer following TDD, it just means that you don't want to implement or follow TDD.
How is TDD beneficial?
It puts you into the customer's shoe. When you test your code, you re actually consuming your code.
It gives you an insight on how much is complete and working fine.
It helps you finish one feature first and then jump on another, following this you will always have something to show.
If someone reviews your tests, they might help you with more scenarios
It helps identifying hazy requirements because you are the customer of your API
Once well written, it serves you for the life time of an application.
Unit Tests have to be very very simple.
A Unit Test must test one thing, hence there has to be just one assert per test method.
Understandability of code should come inherently from a nicely written test, Naming your tests like loginSuccess1 , loginFailure3 etc wont help. You will end up debugging the tests which is an overhead.
Making Unit Tests Trustworthy –
Covers most of the code.
Review Tests (they must test valid things).
Introduce obvious bug and run tests again.
Start with a Failing Test - The Test should eventually pass when you change the production code.
Do not re create the bug by reusing the production code logic.
You cannot change code if there is no test which fails.
In no normal scenarios a Test should be changed or removed.
Exceptions are:
When Tests become invalid - adding a new test questions the existence of some old test. These two are meant to work in opposite directions.
If you do not change the functionality of the tests, for e.g. renaming the tests, re factoring the tests etc.
There should be no logic in Unit Tests. If there is some, you are testing more than the capacity of the test method.
Separate the Unit Test from Integration Test . For e.g:
Oh! the third test failed, but if the fifth one passed its ok we can live with third failing.
The third Billing Test is supposed to fail because Webservice is down.
I know its failing, don't test around this there is a maintenance going on to the Open ID server
Creating Maintainable Unit Test
Only public things must be tested - because that is the contract between the API developer and the world. I can always change the protected and private, if a test is written against the private or protected, it might start failing if I change the name, or re factored it.
If you are forced to write a test for such a method, you may consider changing it to public.
Use a Setup Method method for Arrange Step and Tear Down method for Clean Up.
The block will be called once per test method. Helps in avoiding pollution of the instance state which is used by many other tests.
Enforce Test Isolation
Each Test should setup its own data and rollback
Ensure that tests can be run in any order, any number of times and still give the same result
Avoiding Multiple Asserts. Why ?
If a previous assert failed, the others are not even evaluated and we do not get a fair picture.
If you are testing multiple properties of the same object, you can use multiple assert, or may be you can create the mock for the same object and check equality.
Making Unit Tests Readable
By following a better naming conventions and following other best practices. The biggest Impact is brought due to - Naming Conventions like
Test_Scenario_ExpectedBehavior -
This will help us understand, exactly what happens in the test (no need to check the code of the test).
You don't even need to debug code, test will automatically tell what scenario failed and you know where it broke.
So, you can directly go and fix the code :)
If you want to test with different parameters, you will use the same name with a number at the end.