-
1.
A Brief Introduction to Test-
Driven Development
Shawn M. Jones
-
2.
Who am I?
• Graduated ODU in 1999 with BS in Computer
Science
• Currently working on Master’s Degree in
Computer Science
• Worked for Department of Navy since 1997:
– Web Development
– System Administration
– Information Assurance (Computer Security)
– Requirements Analysis
– Application Development/Build Management
– Never worked in QA or IV&V
-
3.
Sources for this Presentation
• Beck, K. (2003). Test-Driven Development By Example. Boston:
Addison-Wesley.
• Fowler, Martin. Refactoring. http://martinfowler.com/refactoring/
• Osherove, R. (2012). “Write Maintainable Unit Tests That Will Save
You Time and Tears”. MSDN Magazine.
http://msdn.microsoft.com/en-us/magazine/cc163665.aspx
• (2012) Cunningham & Cunningham.
http://c2.com/cgi/wiki?TestDrivenDevelopment
• Personal Experience
-
4.
What do you know about automated
testing?
-
5.
Why You Should Care About
Automated Testing
• Automated testing allows you to check quickly
if you have changed how the code behaves.
• Automated testing provides other developers
an idea of how your functions/classes/libraries
are intended to be used.
• Without automated tests, how do you know
your code actually does what you intended?
How much confidence do you have in it?
-
6.
What do you know about TDD?
• TDD = Test Driven Development
• What else do you know?
-
7.
Tools for TDD
• Testing framework:
– JUnit (for Java)
– NUnit (for .NET)
– Unittest (for Python)
– Roll your own, if necessary
• To-Do List
• Software Project
-
8.
The Rhythm of Test-Driven
Development (TDD)
1. Quickly add a test.
2. Run all tests and see the new one fail.
3. Make a little change.
4. Run all tests and see them all succeed.
5. Refactor to remove duplication.
-
9.
The Rhythm of Test-Driven
Development (TDD)
Quickly add
a test
Run all tests
and see the
new one fail
Make a
little change
Run all tests
and see
them all
succeed
Refactor to
remove
duplication
-
10.
1. Quickly add a test
• Write the test before you write the code.
• This is hard for most of us, because we want
to solve the functionality problem now.
• Think about how to best use the target code.
How do you want to call that code?
-
11.
2. Run all tests and see the new one
fail
• Run the test, even if there is no target code for
it yet.
• Failure is the expected behavior, it provides a
known good starting point.
• What do you do if it passes when it shouldn’t?
– There’s no target code yet, why is it passing?
– Look at the test, is it a good test?
-
12.
3. Make a little change
• Now you can write the target code to pass the
test.
• We’re just focusing on the target code for this
existing automated test.
• Anything else you can think of should be
added to your to-do list.
-
13.
4. Run all tests and see them all
succeed
• Now you know that your code does what you
wanted and you have a way to prove it in the
future.
• If the code doesn’t pass the test, go fix it and
come back to this step.
• Once it works, you have confidence in the
code that you wrote.
-
14.
5. Refactor to remove duplication
• Refactoring – “a disciplined technique for
restructuring an existing body of code, altering its
internal structure without changing its external
behavior”
– Martin Fowler
• Removing duplication ensures that future tests
require fewer changes in the code, limiting
dependency between modules (loosely coupled).
-
15.
Why You Should Care About TDD
• TDD is not really just a testing strategy, it is a
design strategy.
• Code with well-written tests tends to be more
modular, loosely coupled, and easier to
incorporate into the application.
– This makes the code easier to maintain
– It also makes the code more understandable to
others
-
16.
Why You Should Care About Better
Code
• Remember, you will have to live with your
code
• Six months from now you will remember far
less about how it works, but you are still the
expert for your code
• Your coworkers will appreciate you more;
they have to live with your code, too
-
17.
Excuses for not using TDD
• “No automated testing framework exists for the
language/API/etc. in use”
• “Our application is mostly configuration files,
with no real code.”
• “We’re just writing scripts, not real code”
• “TDD is only for classes. My code has no classes.”
• “I’m a developer, not a tester.”
• “Do you want us to produce functionality or tests?”
• “The existing application has no automated tests.”
-
18.
When not to use TDD?
• Research for a new language/API/framework
where you will throw away all of your research
code.
• The language/OS has some construct that
cannot be evaluated by an automated test
(e.g. Console object in Java)
• You don’t have the hardware for testing the
given requirement.
-
19.
Issues with TDD
• Tests are additional code that must be
maintained with the code
• User interfaces can be tested, but change
often (use patterns such as MVC in order to
limit how much code ends up in the UI)
• TDD requires management support;
management may not believe testing is
worthwhile
-
20.
Other issues with TDD
• Use of TDD may cause the organization to
believe other testing (functional, user
experience, etc.) is not necessary
• The tests are only as good as the developer
who wrote them (e.g. a developer unaware of
SQL injection attacks will not check for them)
-
21.
Questions?
We are not writing functions to calculate powers of ten.
Applications have complicated requirements and rules that need to be coded into behavior.
I printed up some handouts.
When I was a frontline developer, I had this posted in my cubicle at work to remind me of the process.
I wanted to stress here that this is a cycle, not just a one-time process.
It can be slow to get started, but as you proceed through this cycle, you end up producing code at a faster rate, largely because you have more confidence in it.
The point here is to have a baseline behavior to start from.
Without this, there is little confidence that your tests are doing anything.
Without automated tests, how would you know that you actually refactored?
Remember, you are not going to be writing a small command-line application.
You will have a piece of a much larger application to work on.
You need to know that your code works in isolation before it can be added to the whole.
“No automated testing framework exists for the language/API/etc. in use”
All you need are functions to evaluate that the behavior matches what is expected
“We’re just writing scripts, not real code”
Scripting languages have testing frameworks (if not, see above)
What makes Python/PERL so special over Java/C++/C#?
Even BASH has shunit2
“TDD is only for classes. My code has no classes.”
What makes classes so special?
Testing frameworks check for behavior and don’t care whether they are used against classes, functions, databases, sockets, etc.
“I’m a developer, not a tester.”
Only you know how you expect your code to work, so you are the most qualified to test it.
“Do you want us to produce functionality or tests?”
This is a false dichotomy. We obviously want code that works. We show it works with tests.
“The existing application has no automated tests.”
Sometimes you have to work on an application with few to no automated tests
Don’t let that stop you from creating them
Write automated tests for the observed behavior to ensure you know when you’ve changed the behavior of the existing code
For new functionality, start with TDD
The goal is to segment the code into old and new
The more of the code you change, the more tests are added
For more information: see Software Exorcism
I do actually have a demo, if we have time.