Last saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E        1©Manning Publications Co. Please pos...
Download at WoweBook.Com2   Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E        Last saved: 7/7/2009          ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E        3   Part I JU...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E              1      ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E        1            ...
Download at WoweBook.Com2 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E            Last saved: 7/7/2009Never in...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E               3     ...
Download at WoweBook.Com4 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E             Last saved: 7/7/2009    DEF...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                     ...
Download at WoweBook.Com6 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E          Last saved: 7/7/2009          ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                7Work...
Download at WoweBook.Com8 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E           Last saved: 7/7/20091.4 Setti...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E               9Fig 1...
Download at WoweBook.Com10 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                          Last saved: 7...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E           11calculat...
Download at WoweBook.Com12 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                       Last saved: 7/7/...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E        1            ...
Download at WoweBook.Com2 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E          Last saved: 7/7/2009   Mistake...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                     ...
Download at WoweBook.Com4 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                   Last saved: 7/7/2009 ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                   5m...
Download at WoweBook.Com6 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E            Last saved: 7/7/20092.2.2 Se...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                     ...
Download at WoweBook.Com8 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E             Last saved: 7/7/2009passing...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E             9   The ...
Download at WoweBook.Com10 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                       Last saved: 7/7/...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E            11Request...
Download at WoweBook.Com12 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                Last saved: 7/7/2009   ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E           13        ...
Download at WoweBook.Com14 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E              Last saved: 7/7/2009     ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                15   ...
Download at WoweBook.Com16 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E               Last saved: 7/7/20092.5....
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                     ...
Download at WoweBook.Com18 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E             Last saved: 7/7/2009(1) Se...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                19   ...
Download at WoweBook.Com20 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                  Last saved: 7/7/2009i...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E                     ...
Download at WoweBook.Com22 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E               Last saved: 7/7/2009    ...
Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E             23To see...
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
J.unit.action.2
Upcoming SlideShare
Loading in...5
×

J.unit.action.2

24,742

Published on

junit examples

Published in: Education, Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
24,742
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
50
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "J.unit.action.2"

  1. 1. Last saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 1©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502
  2. 2. Download at WoweBook.Com2 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 MEAP Edition Manning Early Access Program Copyright 2009 Manning Publications For more information on this and other Manning titles go to www.manning.com©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  3. 3. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 3 Part I JUnit 1. JUnit jumpstart 2. Exploring JUnit 3. Software testing principles 4. Software tests at their best Part II Testing strategies 5. Course-grained testing with stubs 6. Mock objects 7. In-container testing Part III JUnit and the build process 8. Running JUnit tests from Ant 9. Running JUnit tests from Maven2 10. Continuous integration tools Part IV JUnit extensions 11. Presentation layer testing 12. Ajax testing 13. Server-side testing with Cactus 14. Testing JSF applications with JSFUnit 15. Testing OSGi components 16. Database testing with DBUnit 17. Testing JPA-based applications 18. JUnit on steroids Appendices A. Differences between JUnit 3.x and JUnit 4.x B. Extending JUnit API with custom runners and matchers C. The source code for the book D. JUnit integration with different IDEs E. Installing software©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  4. 4. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 1 Part I JUnitWelcome to JUnit in Action. JUnit is a framework that was started by Kent Beck and ErichGamma in the late 1995. Ever since then the popularity of the framework has been growingand is now the de-fact standard for unit-testing Java applications. This book is actually a second edition. The first edition was a best-seller, written byVincent Massol and Ted Husted in 2003, and was dedicated in version 3.x of JUnit We will try to cover the newest version of JUnit - 4.5, and will talk about lots of featuresthat were included after the first edition of the book. At the same time we will try to focus onsome other interesting techniques in testing your code - mock objects, JUnit extensions,testing different layers of your application and so forth. This part will start by exploring JUnit itself. We will focus on the other tools andtechniques further in the book. The first chapter will give you a very quick introduction to the concepts of testing. Youneed this knowledge to get you jumpstarted. You will get straight to the code and see how towrite a very simple test and how to execute it and see the results from it. The second chapter introduces a JUnit at its most. We build a bigger project and walkingover the code we will let you know not only of the JUnit concepts, widgets and guts, but alsowe will show you the best-practices in writing a test-case and will demonstrate them with theproject we have. The third chapter is dedicated on tests as a whole. We describe different kinds of tests,and the different scenarios to which they apply. We will also get to know the differentplatforms (development, production, etc.) and will show you which tests and which scenariosare best to execute there. The last chapter in this part of the book is dedicated on improving your testing skills. Wewill show you how to measure your test-coverage and how to improve it. How to producetestable code before you write your tests and how to write the tests before you write a singleline of code.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  5. 5. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 1 01 JUnit jump-startThis chapter covers What JUnit is Installing JUnit Writing your first test Running tests©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  6. 6. Download at WoweBook.Com2 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009Never in the field of software development was so much owed by so many to so fewlines of code. —Martin FowlerAll code is tested. During development, the first thing we do is run our own programmer’s “acceptancetest.” We code, compile, and run. When we run, we test. The “test” may just be clicking abutton to see if it brings up the expected menu. Nevertheless, every day, we code, wecompile, we run…, and we test. When we test, we often find issues—especially on the first run. Therefore, we code,compile, run, and test again. Most of us will quickly develop a pattern for our informal tests: We add a record, view arecord, edit a record, and delete a record. Running a little test suite like this by hand is easyenough to do; so we do it. Over and over again. Some programmers like doing this type of repetitive testing. It can be a pleasant breakfrom deep thought and hard coding. When our little click-through tests finally succeed, thereis a real feeling of accomplishment: Eureka! I found it! Other programmers dislike this type of repetitive work. Rather than run the test by hand,they prefer to create a small program that runs the test automatically. Play-testing code isone thing; running automated tests is another. If you are a “play-test” developer, this book is for you. We will show you how creatingautomated tests can be easy, effective, and even fun. If you are already “test-infected,” this book is also for you. We cover the basics in part 1,and then move on to the tough, real-life problems in parts 2, 3, and 4.1.1 Proving it works Some developers feel that automated tests are an essential part of the developmentprocess: You cannot prove a component works until it passes a comprehensive series oftests. In fact, two developers felt that this type of “unit testing” was so important that itdeserved its own framework. In 1997, Erich Gamma and Kent Beck created a simple buteffective unit testing framework for Java, called JUnit. The work followed the design of anearlier framework Kent Beck created for Smalltalk, called SUnit. DEFINITION: framework — A framework is a semi-complete application 1 . A framework provides a reusable, common structure to share between applications. Developers incorporate the1 Ralph Johnson and Brian Foote, “Designing Reusable Classes,” Journal of Object-OrientedProgramming 1.5 (June/July 1988): 22–35; http://www.laputan.org/drc/drc.html.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  7. 7. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 3 framework into their own application and extend it to meet their specific needs. Frameworks differ from toolkits by providing a coherent structure, rather than a simple set of utility classes.If you recognize those names, it is for good reason. Erich Gamma is one of the “Gang ofFour” who gave us the now classic Design Patterns book 2 . We know Kent Beck equally wellfor his groundbreaking work in the software discipline known as Extreme Programming(http://www.extremeprogramming.org). JUnit (http://www.junit.org) is open source software, released under IBM’s CommonPublic License Version 1.0 and hosted on SourceForge. The Common Public License isbusiness-friendly: People can distribute JUnit with commercial products without a lot of redtape or restrictions. JUnit quickly became the de facto standard framework for developing unit tests in Java.In fact, the underlying testing model, known as xUnit, is on its way to becoming the standardframework for any language. There are xUnit frameworks available for ASP, C++, C#, Eiffel,Delphi, Perl, PHP, Python, REBOL, Smalltalk, and Visual Basic—just to name a few! Of course, the JUnit team did not invent software testing or even the unit test. Originally,the term unit test described a test that examined the behavior of a single unit of work. Over time, usage of the term unit test broadened. For example, IEEE has defined unittesting as “Testing of individual hardware or software units or groups of related units”(emphasis added) 3 . In this book, we use the term unit test in the narrower sense of a test that examines asingle unit in isolation from other units. We focus on the type of small, incremental test thatprogrammers apply to their own code. Sometimes we call these programmer tests todifferentiate them from quality assurance tests or customer tests(http://c2.com/cgi/wiki?ProgrammerTest). Here is a generic description of a typical unit test from our perspective: “Confirm that themethod accepts the expected range of input, and that the method returns the expectedvalue for each input.” This description asks us to test the behavior of a method through its interface. If we giveit value x, will it return value y? If we give it value z instead, will it throw the properexception?2 Erich Gamma et al., Design Patterns (Reading, MA: Addison-Wesley, 1995).3 IEEE Standard Computer Dictionary: A Compilation of IEEE Standard Computer Glossaries(New York, IEEE, 1990).©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  8. 8. Download at WoweBook.Com4 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 DEFINITION: unit test—A unit test examines the behavior of a distinct unit of work. Within a Java application, the “distinct unit of work” is often (but not always) a single method. By contrast, integration tests and acceptance tests examine how various components interact. A unit of work is a task that is not directly dependent on the completion of any other task.Unit tests often focus on testing whether a method is following the terms of its API contract.Like a written contract by people who agree to exchange certain goods or services underspecific conditions, an API contract is a formal agreement made by the signature of amethod. A method requires its callers to provide specific object references or primitive valuesand returns an object reference or primitive value.. If the method cannot fulfill the contract,the test throws an exception and we say that the method has broken its contract. DEFINITION: API contract—A view of an Application Programming Interface (API) as a formal agreement between the caller and the callee. Often the unit tests help define the API contract by demonstrating the expected behavior. The notion of an API contract stems from the practice of Design by Contract, popularized by the Eiffel programming language (http://archive.eiffel.com/doc/manuals/technology/contract).In this chapter, we will walk through creating a unit test for a simple class from scratch. Wewill start by writing a test and its minimal runtime framework, so you can see how we usedto do things. Then, we will roll out JUnit to show you how the right tools can make life muchsimpler.1.2 Starting from scratchLet us say you have just written the Calculator class shown in listing 1.1.Listing 1.1 The test calculator class public class Calculator { public double add(double number1, double number2) { return number1 + number2; } }Although the documentation is not shown, the intended purpose of the Calculator’sadd(double, double) method is to take two doubles and return the sum as a double. Thecompiler can tell you that it compiles, but you should also make sure it works at runtime. Acore tenet of unit testing is “Any program feature without an automated test simply doesn’t©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  9. 9. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 5exist.” 4 The add method represents a core feature of the calculator. You have some codethat allegedly implements the feature. What is missing is an automated test that proves yourimplementation works. Isn’t the add method just “too simple to break”? The current implementation of the add method is too simple to break. If add were a minor utility method, then you might not test it directly. In that case, if add did fail, then tests of the methods that used add would fail. The add method would be tested indirectly, but tested nonetheless. In the context of the calculator program, add is not just a method, it is a program feature. In order to have confidence in the program, most developers would expect there to be an automated test for the add feature, no matter how simple the implementation appears. In some cases, you can prove program features through automatic functional tests or automatic acceptance tests. For more about software tests in general, see chapter 3. Yet testing anything at this point seems problematic. You do not even have a userinterface with which to enter a pair of doubles. You could write a small command lineprogram that waited for you to type in two double values and then displayed the result. Ofcourse, then you would also be testing your own ability to type a number and add the resultourselves. This is much more than what you want to do. You just want to know if this “unit ofwork” will actually add two doubles and return the correct sum. You do not want to testwhether programmers can type numbers! Meanwhile, if you are going to go to the effort of testing your work, you should also try topreserve that effort. It is good to know that the add(double,double) method workedwhen you wrote it. However, what you really want to know is whether the method workswhen you ship the rest of the application or whenever you make a subsequent modification.If we put these requirements together, we come up with the idea of writing a simple testprogram for the add method. The test program could pass known values to the method and see if the result matchesour expectations. You could also run the program again later to be sure the methodcontinues to work as the application grows. So what is the simplest possible test programyou could write? What about the CalculatorTest program shown in listing 1.2?Listing 1.2 A simple test calculator program public class CalculatorTest { public static void main(String[] args) { Calculator calculator = new Calculator(); double result = calculator.add(10,50);4 Kent Beck, Extreme Programming Explained: Embrace Change (Reading, MA: Addison-Wesley, 1999).©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  10. 10. Download at WoweBook.Com6 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 if (result != 60) { System.out.println("Bad result: " + result); } } }The first CalculatorTest is simple indeed. It creates an instance of Calculator, passesit two numbers, and checks the result. If the result does not meet your expectations, youprint a message on standard output. If you compile and run this program now, the test will quietly pass, and all will seem well.However, what happens if you change the code so that it fails? You will have to watchcarefully the screen for the error message. You may not have to supply the input, but youare still testing your own ability to monitor the program’s output. You want to test the code,not yourself! The conventional way to signal an error conditions in Java is to throw an exception. Letus throw an exception instead to indicate a test failure. Meanwhile, you may also want to run tests for other Calculator methods that you havenot written yet, like subtract or multiply. Moving to a modular design would make iteasier to catch and handle exceptions and make it easier to extend the test program later.Listing 1.3 shows a slightly better CalculatorTest program.Listing 1.3 A (slightly) better test calculator program public class CalculatorTest { private int nbErrors = 0; public void testAdd() { (1) Calculator calculator = new Calculator(); | double result = calculator.add(10, 50); | if (result != 60) { | throw new IllegalStateException("Bad result: " + result); | } | } (1) public static void main(String[] args) { CalculatorTest test = new CalculatorTest(); try { (2) test.testAdd(); | } | catch (Throwable e) { | test.nbErrors++; | e.printStackTrace(); | } | if (test.nbErrors > 0) { (2) throw new IllegalStateException("There were " + test.nbErrors + " error(s)"); } } }©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  11. 11. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 7Working from listing 1.3, at (1) you move the test into its own testAdd method. It is noweasier to focus on what the test does. You can also add more methods with more unit testslater, without making the main method harder to maintain. At (2), you change the mainmethod to print a stack trace when an error occurs and then, if there are any errors, end bythrowing a summary exception.1.3 Understanding unit-testing frameworksThere are several best practices that unit testing frameworks should follow. These seeminglyminor improvements in the CalculatorTest program highlight three rules that (in ourexperience) all unit testing frameworks should follow: Each unit test must run independently of all other unit tests. The framework must detect and report errors test by test. It must be easy to define which unit tests will run.The “slightly better” test program comes close to following these rules but still falls short. Forexample, in order for each unit test to be truly independent, each should run in a differentclass instance and ideally in a different class loader instance. You can now add new unit tests by adding a new method and then adding acorresponding try/catch block to main. This is a step up, but still short of what you would want in a real unit test suite. Ourexperience tells us that large try-catch blocks cause maintenance problems. You couldeasily leave a unit test out and never know it! It would be nice if you could just add new test methods and continue working. However,how would the program know which methods to run? Well, you could have a simple registration procedure. A registration method would atleast inventory which tests are running. Another approach would be to use Java’s reflection and introspection capabilities. Aprogram could look at itself and decide to run whatever methods follow a certain namingconvention —like those that begin with the letters test, for example. Making it easy to add tests (the third rule in our earlier list) sounds like another good rulefor a unit testing framework. The support code to realize this rule (via registration or introspection) would not betrivial, but it would be worthwhile. There would be a lot of work up front, but that effortwould pay off each time you added a new test. Happily, the JUnit team has saved you the trouble. The JUnit framework already supportsintrospecting methods. It also supports using a different class instance and class loaderinstance for each test, and reports all errors on a test-by-test basis. Now that you have a better idea of why you need a unit testing framework, let us set upJUnit and see it in action.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  12. 12. Download at WoweBook.Com8 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/20091.4 Setting up JUnit In order to use JUnit to write your application tests, you will simply need to add the JUnitjar file to your project’s compilation classpath and to your execution classpath. Follow thesesteps: Download the JUnit distribution (junit-4.6 or newer) from http://www.junit.org. JUnitcontains several test samples that you will run to get familiar with executing JUnit tests. Unzip the distribution Zip file to a directory on your computer system (for example, C:on Windows or /opt/ on UNIX). In this directory, unzipping will create a subdirectory for the JUnit distribution youdownloaded (for example, C:junit4.6 on Windows or /opt/junit4.6 on UNIX).You are now ready to run the tests provided with the JUnit distribution. JUnit comescomplete with Java programs that you can use to view the result of a test, including a text-based test runner with console output (figure 1.2). To run the text test runner, open a shell in C:junit4.6 on Windows or in/opt/junit4.6 UNIX, and type the appropriate command for your operating system:Windows:java -cp junit-4.6.jar;. junit.samples.AllTestsUNIX:java -cp junit-4.6.jar:. junit.samples.AllTests The AllTests class contains a main method to execute the sample tests: public static void main (String[] args) { junit.textui.TestRunner.run(suite()); } Figure 1.1 shows the result of the test executing.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  13. 13. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 9Fig 1.1 Execution of the JUnit distribution sample tests using the text test runnerNotice that the JUnit text test runner displays passing tests with a dot. Had there beenerrors, they would have displayed with an E instead of a dot. In part III of the book, we will look at running tests using the Ant build tool and also theMaven build tool.1.5 Testing with JUnitJUnit has many features that make it easy to write and run tests. You will see these featuresat work throughout this book: Separate test class instances and class loaders for each unit test to avoid side effects. JUnit annotations to provide resource initialization and reclamation methods: @Before, @BeforeClass, @After, and @AfterClass. A variety of assert methods to make it easy to check the results of your tests. Integration with popular tools like Ant, Maven, and popular IDEs like Eclipse, NetBeans, IntelliJ, and JBuilder.Without further ado, let us turn to listing 1.4 and see what the simple Calculator testlooks like when written with JUnitListing 1.4 The JUnit CalculatorTest program import static org.junit.Assert.*; import org.junit.Test; public class CalculatorTest { (1) @Test (2) public void testAdd() { Calculator calculator = new Calculator(); (3) double result = calculator.add(10, 50); (4) assertEquals(60, result, 0); (5)©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  14. 14. Download at WoweBook.Com10 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 } }This is a much simpler test, let us walk through it. At (1), you start by defining a test class. The only restriction is that the class must bepublic, you can name it whatever you like though. It is standard practice to end the classname with "Test". Notice also that in contrast to JUnit 3 where you needed to extend theTestCase class, this requirement has been removed in JUnit 4. At (2), you mark the method as a unit test method by adding the @Test annotation 5 . Abest-practice is to name your test methods following the testXXX pattern. JUnit does nothave method name restrictions, you can name your methods as you like, as long as theyhave the @Test annotation they will be executed by JUnit. At (3), you start the test by creating an instance of the Calculator class (the “objectunder test”), and at (4), as before, you execute the test by calling the method to test,passing it two known values. At (5), the JUnit framework begins to shine! To check the result of the test, you call anassertEquals method, which you imported with a static import on the first line of theclass. The Javadoc for the assertEquals method is: /** * Asserts that two doubles or floats are equal to within a positive delta. * If the expected value is infinity then the delta value is ignored. */ static public void assertEquals( double expected, double actual, double delta)In listing 1.4, you passed assertEquals these parameters: expected = 60 actual = result delta = 0Since you passed the calculator the values 10 and 50, you tell assertEquals to expect thesum to be 60. (You pass 0 as the delta since you are adding integers.) When you called thecalculator object, you tucked the return value into a local double named result.Therefore, you pass that variable to assertEquals to compare against the expected valueof 60. If the actual value is not equal to the expected value, JUnit throws an uncheckedexception, which causes the test to fail. Most often, the delta parameter can be zero, and you can safely ignore it. It comes intoplay with calculations that are not always precise, which includes many floating-point5 Annotations were first introduced in JDK 1.5. so in order to use them you need to have the 1.5 or later version ofthe JDK.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  15. 15. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 11calculations. The delta provides a range factor. If the actual value is within the rangeexpected - delta and expected + delta the test will pass. You may find it usefulwhen doing mathematical computations with rounding or truncating errors or when assertinga condition about the modification date of a file, as the precision of these dates depend onthe operating system. JUnit Design Goals The JUnit team has defined three discrete goals for the framework: The framework must help us write useful tests. The framework must help us create tests that retain their value over time. The framework must help us lower the cost of writing tests by reusing code. In listing 1.4, we showed how easy it is to write tests with JUnit. We will return to the other goals in chapter 2. Let us assume you have entered the code from listings 1.1 and 1.4 in theC:junitbookjumpstart directory (/opt/junitbook/jumpstart on UNIX). Let usfirst compile the code by opening a command shell in that directory and typing the following(we will assume you have the javac executable on your PATH):Windows: javac -cp junit4.6junit-4.6.jar *.javaUNIX: javac -cp /junit4.6/junit-4.6.jar *.javaYou are now ready to start the console test runner, by typing the following:Windows: java -cp .;junit4.6junit-4.6.jar ➔ org.junit.runner.JUnitCore CalculatorTestUNIX: java -cp .:/junit4.6/junit-4.6.jar ➔org.junit.runner.JUnitCore CalculatorTestFigure 1.2 shows the test result .The remarkable thing about the JUnit CalculatorTest class in listing 1.4 is that the codeis easier to write than the first CalculatorTest program in listing 1.2. In addition, you canrun the test automatically through the JUnit framework.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  16. 16. Download at WoweBook.Com12 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009Figure 1.2 Execution of the first JUnit test CalculatorTest using the text test runner NOTE If you are maintaining tests written prior to JUnit version 3.8.1, your class needs a String constructor, for example: public CalculatorTest(String name) { super(name); } This is no longer required with JUnit 3.8.1 and later.1.6 SummaryEvery developer should perform some type of test to see if code actually works. Developerswho use automatic unit tests can repeat these tests on demand to ensure that new codeworks and does not break existing tests. Simple unit tests are not difficult to create without JUnit, but as tests are added andbecome more complex, writing and maintaining tests becomes more difficult. JUnit is a unittesting framework that makes it easier to create, run, and revise unit tests. In this chapter, we scratched the surface of JUnit by stepping through a simple test. Ofcourse, JUnit has much more to offer. In chapter 2, we take a closer look at the JUnit framework classes (different annotationsand assertion mechanisms) and how they work together to make unit testing efficient andeffective. We will also walk through the differences between the old-style JUnit 3 and thenew features in JUnit 4.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  17. 17. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 1 02 Exploring JUnitThis chapter covers Using the core JUnit classes Understanding JUnit mechanisms Understanding the JUnit lifecycle©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  18. 18. Download at WoweBook.Com2 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 Mistakes are the portals of discovery. —James Joyce In chapter 1, we decided that we need a reliable and repeatable way to test our program.Our solution is to write or reuse a framework to drive test code that exercises our programsAPI. As our program grows with new classes and new methods to existing classes, we needto grow our test code as well. As experience has taught us that sometimes classes interact inunexpected ways, we need to make sure that we can run all of our tests at any time, nomatter what code changes took place. The question becomes, how do we run multiple testclasses? How do we find out which tests passed and which ones failed? In this chapter, we will look at how JUnit provides the functionality to answer thosequestions. We will begin with an overview of the core JUnit concepts – the test class, testsuite and test runner. We will take a close look at the core test runners and the test suite,before we revisit our old friend the test class. We will also examine how the core classeswork together. In the second part of this chapter, we will use an example application to show you how touse these core JUnit concepts. We will demonstrate best practices for writing and organizingtest code.2.1 Exploring core JUnit The CalculatorTest program from chapter 1, shown in listing 2.1, defines a test classwith a single test method testAdd. The requirements to define a test class are that the class must be public and contain azero-argument constructor. In our example, since we do not define any other constructors,we do not need to define the zero-argument constructor, Java creates it for us implicitly. The requirement to create a test method is that it must be annotated with @Test, bepublic, take no arguments, and return void.Listing 2.1 The CalculatorTest test case import static org.junit.Assert.assertEquals; import org.junit.Test; public class CalculatorTest { @Test public void testAdd() { Calculator calculator = new Calculator(); double result = calculator.add(10, 50); assertEquals(60, result, 0); } } JUnit creates a new instance of the test class before invoking each @Test method. Thishelps provide independence between test methods and avoids unintentional side effects in©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  19. 19. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 3the test code. Since each test methods runs on a new test class instance, you cannot reuseinstance variables values across test methods. To perform test validation, you use the assert methods provided by the JUnit Assertclass. As you can see from the previous example, you statically import these methods inyour test class. Alternatively, you can import JUnit Assert class itself, depending on yourtaste for static imports. The following table lists some of the most popular assert methods.Table 2.1 Some of the assertXXX methods in JUnit.assertXXX method What is it used forassertArrayEquals(“message”, A, B) Asserts the equality of the A and B arrays.assertEquals(“message”, A, B) Assert equality of objects A and B. This assert actually invokes the equals() method on the first object against the second.assertSame(“message”, A, B) Asserts that the A and B objects have the same value. While the previous assert method checks to see that both the A and B are the same objects (using equals method), the assertSame method actually checks to see if the A and B objects have the same value (using == operator).assertTrue(“message”, A) Assert the A condition is true.assertNotNull(“message”, A) Assert the A object is not null. Assert methods with two value parameters follow a pattern worth memorizing: the firstparameter (A above) is the expected value and the second parameter (B above) is the actualvalue. JUnit provides many other methods – like assertArrayNotEquals, assertNotSame,assertNotTrue, etc. It also provides the same methods with a different signature –without the message parameter. It is a best practice to provide an error message for all yourassert method calls. Recall Murphys Law and apply it here, when an assertion fails, describewhat went wrong in a human readable message. When you need to run several test classes at once, you create another object calleda test suite (or Suite.) Your test suite is actually a special test runner (or Runner), so youcan run it as you would a test class. Once you understand how a test class, Suite, andRunner work, you will be able to write whatever tests you need. These three objects formthe backbone of the JUnit framework. On a daily basis, you only need to write test classes and test suites. The other classeswork behind the scenes to bring your tests to life.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  20. 20. Download at WoweBook.Com4 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 DEFINITION: Test class (or TestCase or test case) — A class that contains one or more tests represented by methods annotated with @Test. Use a test case to group together tests that exercise common behaviors. In the remainder of this book, when we mention a test, we mean a method annotated with @Test; and when we mention a test case (or test class), we mean a class that holds these test methods—that is, a set of tests. Suite (or test suite) — A group of tests. A test suite is a convenient way to group together tests that are related. For example, if you do not define a test suite for a test class, JUnit automatically provides a test suite that includes all tests found in the test class (more on that later). Runner (or test runner) — A runner of test suites. JUnit provides different runners to execute your tests. We cover these runners later in this chapter and show you how to write your own test runners.Let us take a closer look at the responsibilities of each of the core objects that make upJUnit.Table 2.2 Core objects that make up JUnit.JUnit concept Responsibilities Introduced in … Section 2.1Assert Lets you define the conditions that you want to test. An assert method is silent when its proposition succeeds but throws an exception if the proposition fails. Section 2.1Test A method with an @Test annotation defines a test. To run this method JUnit constructs a new instance of the containing class and then invokes the annotated method. Section 2.1Test class A test class is the container for @Test methods. The Suite allows you to group test classes together. Section 2.3Suite The Runner class runs tests. JUnit 4 is backward Section 2.2Runner compatible and will run JUnit 3 tests. We can move on now on explaining in details those objects from the table above that westill haven’t talked about – that are the Runner and Suite objects. We will start byintroducing the Runner object in the next section and later on in section 2.3 we will talkabout Suites.2.2 Running tests with the JUnit test runnerWriting tests can be fun, but what about the grunt work of running them? When you are firstwriting tests, you want them to run as quickly and easily as possible. You should be able to©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  21. 21. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 5make testing part of the development cycle— code : run : test : code (or test : code : run :test if you are test-first inclined). There are IDEs and compilers for quickly building andrunning applications, but what can you use to run the tests?2.2.1 JUnit’s test runnersJUnit4 is built around the notion of backward compatibility. Because of the fact that the 4.xversion of JUnit is completely different from the 3.x ones, it should be possible to executenot only JUnit4 test, but also to execute “older” 3.x tests. That is the reason why in its latestversions JUnit provides a couple of runners – for running JUnit3x tests, JUnit4 tests and forrunning different sets of tests.Table 2.3 Different test runners that come with JUnit4Runner Purpose This runner is included in the current releaseorg.junit.internal.runners.JUnit38ClassRunner of JUnit only for backward compatibility. It will start the test case as a JUnit38 test case. This runner is inclined to force JUnit to startorg.junit.runners.JUnit4 the test case as a JUnit4 test case. Parameterized test-runner is supposed to runorg.junit.runners.Parameterized same sets of tests with different parameters. The Suite is actually a container that can holdorg.junit.runners.Suite different tests together. The Suite is also a runner that executes all the @Test annotated methods in your test-class. Normally JUnit will detect the right test runner to use without asking you, based on thetest-case you provide. If you want to force it to use any particular runner you need to usethe @RunWith annotation as shown in the following listing.Listing 2.2 @RunWith annotation of JUnit @RunWith(value=org.junit.internal.runners.JUnit38ClassRunner.class) public class TestWithJUnit38 extends junit.framework.TestCase { […] } So far we saw an overview of the different JUnit test-runners and how to instruct JUnit touse any of them. But in order to choose the right test-runner we need to look in more detailsinto those objects©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  22. 22. Download at WoweBook.Com6 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/20092.2.2 Selecting a test runnerThe two first runners listed in table 2.3 force JUnit to run the test respectfully as JUnit3.x orJUnit4.x test. JUnit does not need to be instructed which test-runner to use and these twotest-runners are only for special occasions. The third listed runner (Parameterized) is an interesting creature that allows you torun your single tests many times with different sets of parameters. As we believe anexample is worth several pages of explanation, the following listing demonstrates theParameterized runner in action.Listing 2.3 Running tests with the Parameterized test-runner. […] @RunWith(value=Parameterized.class) (1) public class ParameterizedTest { private double expected; (2) private double valueOne; (2) private double valueTwo; (2) @Parameters (3) public static Collection dataParameters() { (3) return Arrays.asList(new Object[][] { {2,1,1}, //expected, valueOne, valueTwo {3,2,1}, {4,3,1}, }); } public ParameterizedTest(double expected, double valueOne, double valueTwo) { (4) this.expected = expected; this.valueOne = valueOne; this.valueTwo = valueTwo; } @Test public void sum() { (5) Calculator calc = new Calculator(); (6) assertEquals(expected, calc.add(valueOne, valueTwo), 0); (7) } } So to have a test-class run with the Parameterized test-runner you need to haveseveral obligatory elements. You need to denote the @RunWith annotation to use theParameterized test-runner (1). Then we declare some local instance variables we aregoing to use in our tests (at (2)) and we provide the obligatory @Parameters-annotatedmethod (3). This method is used to provide the input and output data for the parameterizedtests. This method needs to be public, static and return a Collection instance bysignature. As we want to test the add method of our Calculator program we provide threeparameters – expected value, and two values that we will add together. At (4) we specify©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  23. 23. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 7the obligatory constructor for the test. Note that this time our test-case does not have a no-argument constructor, but instead has a constructor that accepts parameters for the test. At(5) we finally implement the sum @Test method, that instantiates the Calculator program(6), and asserts against the parameters we have provided (7). If you run this test you will see that it is executed exactly as many times as the size ofthe Collection returned by the @Parameters method – that is the number of the parameterentries. The execution of this single test-case has actually the same result as the executionof the following many test-cases with different parameters:sum: assertEquals( 2, calculator.add( 1,1 ), 0 );sum: assertEquals( 3, calculator.add( 2,1 ), 0 );sum: assertEquals( 4, calculator.add( 3,1 ), 0 ); For the last test-runner (Suite) we dedicate a separate section (2.3) so we will take acloser look on it later on.2.2.3 The JUnitCore façade To make running tests as quick and easy as possible, JUnit provides a façade(org.junit.runner.JUnitCore), which operates with any of the test runners. Thisfacade is designed to execute your tests and provide you with statistics regarding theoutcome. Because it is specifically designed for this purpose, the facade can be very easy touse. You can see the JUnitCore class in action in figure 1.3 in the previous chapter. Design patterns in action: Facade A 1 façade is a design pattern that provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. This can be used to simplify a number of complicated object interactions into a single interface. Facade exposes the interface of contained objects to the world, and the point of it is that this way clients dont have to be concerned with exactly which object in a subsystem theyre dealing with. They just call their methods on the facade in blissful ignorance. The JUnit façade works the exact same way as described – it determines which runner touse for running your tests. It supports running JUnit38 tests, JUnit4 tests or a mixture ofboth. There used to be a whole set of test runners in the previous 3.x version of JUnit,including Swing and AWT test runners, but they are not included in the current 4.x version ofthe framework. Those graphical test runners usually had a progress indicator running acrossthe screen, which was known as the famous JUnit green bar. JUnit testers tend to refer to1 The definition is taken from the Portland Pattern Repository here: http://c2.com/cgi/wiki?FacadePattern©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  24. 24. Download at WoweBook.Com8 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009passing tests as green-bar and failing tests as red-bar. “Keep the bar green to keep thecode clean” is the JUnit motto. So don’t get curious what its origin is, the next time you readit. As I already mentioned, in the current version of JUnit there is no graphical test runnersincluded, so the only way to use a graphical way to run your tests is to use your favorite IDE.All of the IDEs out there support integration with JUnit. You can see the Eclipse’s JUnit pluginexecuting a test in figure 2.1.2.2.4 Defining your own custom test runner Unlike other elements of the JUnit framework,there is no Runner interface. Instead, the various test runners bundled withJUnit all extend Runner. If you needed to write yourown test runner for any reason, you could alsoextend this class yourself. Please refer to Appendix Bwhere we cover this topic in details.2.3 Composing tests with TestSuiteSimple things should be simple … and complex thingsshould be possible. Suppose you compile the simplecalculator test program from listing 2.1 and hand it tothe console façade runner, like this: >java org.junit.runner.JUnitCore CalculatorTest Fig. 2.1 JUnit’s green bar, shown in Eclipse.It should run just fine, assuming you have the correctclasspath. Altogether, this seems simple - at least asfar as running a single test case is concerned. But what happens when you want to run multiple test cases? Or just some of your testcases? How can you group test cases? Between the notions of test-case and test-runner, it would seem that you need some typeof container that can collect several tests together and run them as a set. But, by making iteasier to run multiple cases, you don’t want to make it harder to run a single test case. JUnit’s answer to this puzzle is the Suite. The Suite is designed to run one or more testcases. The test runner launches the Suite; which test-cases to run is up to the Suite.2.3.1 Running the suiteYou might wonder how you managed to run the example at the end of chapter 1, when youdidn’t define a Suite. To keep simple things simple, the test runner automatically creates aSuite if you don’t provide one of your own. (Sweet!)©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  25. 25. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 9 The default Suite scans your test class for any methods that are @Test annotated.Internally, the default Suite creates an instance of your TestClass for each @Test method.This way every @Test method is executed separately from the others – so your test-methods do not interfere. If you added another test in the CalculatorTest class, like testSubtract, and youannotate it with the @Test annotation, the default Suite would automatically include it too. So you see the Suite object is actually a Runner that executes all of the @Testannotated methods in the test-class. But is it possible to combine test-methods fromdifferent test-classes? Of course it is - that’s the real purpose of the Suite object! The nextcode-listing shows exactly how to do this.Listing 2.4 Composing test-methods from different test-classes. […] @RunWith(value=org.junit.runners.Suite.class) (1) @SuiteClasses(value={TestFolderConfiguration.class, (2) TestFileConfiguration.class}) (2) public public class RunConfigurationTests { } As you can see the only thing you need to do is Specify the appropriate runner with the @RunWith annotation. List the tests we want to include in this test by specifying the test-classes in the@SuiteClasses annotation. All the test-methods from those classes will be included. Now you see for the CalculatorTest in listing 2.1, the default Suite could be representedin code like this: @RunWith(value=Suite.class) @SuiteClasses(value={CalculatorTest.class}) public class AllTests { } What we did so far was to introduce the different objects that build the backbone of theJUnit framework. We looked over TestClass, Runner, and Suite to explore them indetails. What we want next is to see how to use those classes in a real-world example. Andthat is exactly what we are going to do! In the next section we introduce the Controller design pattern and build a sampleController component application that we will test with JUnit. This way we will not only showyou how to use the JUnit components we have been dealing so far, but we will also introducea lot of JUnit best-practices with the means of the example application we have.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  26. 26. Download at WoweBook.Com10 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/20092.4 Introducing the controller componentCore J2EE Patterns describes a controller as a component that “interacts with a client,controlling and managing the handling of each request”, and tells us that it is used in bothpresentation-tier and business-tier patterns. 2In general, a controller does the following: Accepts requests Performs any common computations on the request Selects an appropriate request handler Routes the request so that the handler can execute the relevant business logic May provide a top-level handler for errors and exceptions A controller is a handy class and can be found in a variety of applications. For example, ina presentation-tier pattern, a web controller accepts HTTP requests and extracts HTTPparameters, cookies, and HTTP headers, perhaps making the HTTP elements easilyaccessible to the rest of the application. A web controller determines the appropriatebusiness logic component to call based on elements in the request, perhaps with the help ofpersistent data in the HTTP session, a database, or some other resource. The Apache Strutsframework is an example of a web controller. Another common use for a controller is to handle applications in a business tier pattern.Many business applications support several presentation layers. Web applications may behandled through HTTP clients. Desktop applications may be handled through Swing clients.Behind these presentation tiers there is often an application controller, or state machine.Many Enterprise Java Bean (EJB) applications are implemented this way. The EJB tier has itsown controller, which connects to different presentation tiers through a business façade ordelegate. Given the many uses for a controller, it’s no surprise that controllers crop up in a numberof enterprise architecture patterns, including Page Controller, Front Controller, andApplication Controller 3 . The controller you will design here could be the first step inimplementing any of these classic patterns. Let’s work through the code for the simplecontroller, to see how it works, and then try a few tests. If you would like to follow along andrun the tests as you go, all the source code for this chapter is available at SourceForge(http://junitbook.sf.net). See appendix A for more about setting up the source code.2.4.1 Designing the interfacesLooking over the description of a controller, four objects pop out: the Request, theResponse, the RequestHandler, and the Controller. The Controller accepts a2 Deepak Alur, John Crupi, and Dan Malks, Core J2EE Patterns: Best Practices and Design Strategies(Upper SaddleRiver, NJ: Prentice Hall, 2001).3 Martin Fowler, Patterns of Enterprise Application Architecture (Boston: Addison-Wesley, 2003).©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  27. 27. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 11Request, dispatches a RequestHandler, and returns a Response object. With adescription in hand, you can code some simple starter interfaces, like those shown in listing2.5.Listing 2.5 Request, Response, RequestHandler and Controller interfaces public interface Request { String getName(); (1) } public interface Response (2) { } public interface RequestHandler { Response process(Request request) throws Exception; (3) } public interface Controller { Response processRequest(Request request); (4) void addHandler(Request request, RequestHandler requestHandler); (5) }(1) Define a Request interface with a single getName method that returns the request’sunique name, just so you can differentiate one request from another. As you develop thecomponent you will need other methods, but you can add those as you go along.(2) Here you specify an empty interface. To begin coding, you only need to return aResponse object. What the Response encloses is something you can deal with later. Fornow, you just need a Response type you can plug into a signature.(3) Define a RequestHandler that can process a Request and return your Response.RequestHandler is a helper component designed to do most of the dirty work. It may callupon classes that throw any type of exception. So, Exception is what you have theprocess method throw.(4) Define a top-level method for processing an incoming request. After accepting therequest, the controller dispatches it to the appropriate RequestHandler. Notice thatprocessRequest does not declare any exceptions. This method is at the top of the controlstack and should catch and cope with any and all errors internally. If it did throw anexception, the error would usually go up to the Java Virtual Machine (JVM) or servletcontainer. The JVM or container would then present the user with one of those nasty whitescreens. Better you handle it yourself.(5) This is a very important design element. The addHandler method allows you to extendthe Controller without modifying the Java source.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  28. 28. Download at WoweBook.Com12 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 Design patterns in action: Inversion of Control Registering a handler with the controller is an example of Inversion of Control. This pattern is also known as the Hollywood Principle, or “Don’t call us, we’ll call you.” Objects register as handlers for an event. When the event occurs, a hook method on the registered object is invoked. Inversion of Control lets frameworks manage the event life cycle while allowing developers to plug in custom handlers for framework events. 42.4.2 Implementing the base classFollowing up on the interfaces in listing 2.5, listing 2.6 shows a first draft of the simplecontroller class.Listing 2.6 The generic controller package junitbook.sampling; import java.util.HashMap; import java.util.Map; public class DefaultController implements Controller { private Map requestHandlers = new HashMap(); (1) protected RequestHandler getHandler(Request request) (2) { if (!this.requestHandlers.containsKey(request.getName())) { String message = "Cannot find handler for request name " + "[" + request.getName() + "]"; throw new RuntimeException(message); (3) } return (RequestHandler) this.requestHandlers.get(request.getName()); (4) } public Response processRequest(Request request) (5) { Response response; try { response = getHandler(request).process(request); } catch (Exception exception) { response = new ErrorResponse(request, exception); } return response; } public void addHandler(Request request, RequestHandler requestHandler) { if (this.requestHandlers.containsKey(request.getName()))4 http://c2.com/cgi/wiki?HollywoodPrinciple©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  29. 29. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 13 { throw new RuntimeException("A request handler has " (6) + "already been registered for request name " (6) + "[" + request.getName() + "]"); (6) } else { this.requestHandlers.put(request.getName(), requestHandler); } } }(1) Declare a HashMap (java.util.HashMap) to act as the registry for your requesthandlers.(2) Add a protected method, getHandler, to fetch the RequestHandler for a givenrequest.(3) If a RequestHandler has not been registered, you throw a RuntimeException(java.lang.RuntimeException), because this happenstance represents a programmingmistake rather than an issue raised by a user or external system. Java does not require youto declare the RuntimeException in the method’s signature, but you can still catch it as anexception. An improvement would be to add a specific exception to the controller framework(NoSuitableRequestHandlerException, for example).(4) Your utility method returns the appropriate handler to its caller.(5) This is the core of the Controller class: the processRequest method. This methoddispatches the appropriate handler for the request and passes back the handler’s Response.If an exception bubbles up, it is caught in the ErrorResponse class, shown in listing 2.7.(6) Check to see whether the name for the handler has been registered, and throw anexception if it has. Looking at the implementation, note that the signature passes therequest object, but you only use its name. This sort of thing often occurs when an interfaceis defined before the code is written. One way to avoid over-designing an interface is topractice Test-Driven Development (see chapter 4).Listing 2.7 Special response class signaling an error. […] public class ErrorResponse implements Response { private Request originalRequest; private Exception originalException; public ErrorResponse(Request request, Exception exception) { this.originalRequest = request; this.originalException = exception; } public Request getOriginalRequest() { return this.originalRequest; }©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  30. 30. Download at WoweBook.Com14 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 public Exception getOriginalException() { return this.originalException; } }At this point, you have a crude but effective skeleton for the controller. Table 2.4 shows howthe requirements at the top of this section relate to the source code.Table 2.4 Resolving the base requirements for the componentRequirement Resolution public Response processRequest(Request request)Accept requests this.requestHandlers.get(request.getName())Select handler response = getRequestHandler(request).process(request);Route requests Subclass ErrorResponseError-handlingThe next step for many developers would be to cobble up a stub application to go with theskeleton controller. But not us! As “test-infected” developers, we can write a test suite forthe controller without fussing with a stub application. That’s the beauty of unit testing! Youcan write a package and verify that it works, all outside of a conventional Java application.2.5 Let’s test it!A fit of inspiration has led us to code the four interfaces shown in listing 2.5 and the twostarter classes shown in listings 2.6 and 2.7. If we don’t write an automatic test now, theBureau of Extreme Programming will be asking for our membership cards back! Listings 2.6 and 2.7 began with the simplest implementations possible. So, let’s do thesame with the new set of unit tests. What’s the simplest possible test case we can explore?2.5.1 Testing the DefaultControllerHow about a test-case that instantiates the DefaultController class? The first step indoing anything useful with the controller is to construct it, so let’s start there. Listing 2.8shows the bootstrap test code. It constructs the DefaultController object and sets up aframework for writing tests.Listing 2.8 TestDefaultController – a bootstrap iteration package junitbook.sampling; import org.junit.core.Test; import static org.junit.Assert.*; public class TestDefaultController (1) { private DefaultController controller;©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  31. 31. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 15 @Before public void instantiate() throws Exception (2) { controller = new DefaultController(); } @Test public void testMethod() (3) { throw new RuntimeException("implement me"); (4) } }(1) Start the name of the test case class with the prefix Test. The naming convention is notrequired, but doing so we mark the class as a test case so that you can easily recognize testclasses and possibly filter them in build scripts.(2) Use the @Before-annotated method to instantiate DefaultController. This is a built-in extension point that the JUnit framework calls between test methods.(3) Here you insert a dummy test method, just so you have something to run. As soon asyou are sure the test infrastructure is working, you can begin adding real test methods. Ofcourse, although this test runs, it also fails. The next step will be to fix the test!(4) Use a “best practice” by throwing an exception for test code that has not yet beenimplemented. This prevents the test from passing and reminds you that you must implementthis code. JUnit’s details The @Before and @After annotated methods are executed right before/after the execution of each one of your @Test methods, and regardless of the fact whether the test failed or not. This helps you to extract all of your common logic, like instantiating your domain objects and setting them up in some known state. You can have as many of these methods, as you want, but beware because in case you have more than one of the @Before/@After methods no one knows what is the order of their execution. JUnit also provides the @BeforeClass and @AfterClass annotations to annotate your methods in that class. The methods that you annotate will get executed, only once before/after all of your @Test methods. Again, as with the @Before and @After annotations you can have as many of these methods as you want, and again nothing is specified about the order of the execution. You need to remember that both the @Before/@After and @BeforeClass/@AfterClass annotated methods must be public by signature. The @BeforeClass/@AfterClass annotated methods must be public and also be static by signature.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  32. 32. Download at WoweBook.Com16 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/20092.5.2 Adding a handlerNow that you have a bootstrap test, the next step is to decide what to test first. We startedthe test case with the DefaultController object, because that’s the point of thisexercise: to create a controller. You wrote some code and made sure it compiled. But howcan you test to see if it works? The purpose of the controller is to process a request and return a response. But beforeyou process a request, the design calls for adding a RequestHandler to do the actualprocessing. So, first things first: you should test whether you can add a RequestHandler. The tests you ran in chapter 1 returned a known result. To see if the test succeeded, youcompared the result you expected with whatever result the object you were testing returned.The signature for addHandler is void addHandler(Request request, RequestHandler requestHandler)To add a RequestHandler, you need a Request with a known name. To check to see ifadding it worked, you can use the getHandler method from DefaultController, whichuses this signature: RequestHandler getHandler(Request request)This is possible because the getHandler method is protected, and the test classes arelocated in the same package as the classes they are testing. For the first test, it looks like you can do the following: Add a RequestHandler, referencing a Request. Get a RequestHandler and pass the same Request. Check to see if you get the same RequestHandler back.WHERE DO TESTS COME FROM?Now you know what objects you need. The next question is “where do these objects comefrom?” Should you go ahead and write some of the objects you will use in the application,like a logon request? The point of unit testing is to test one object at a time. In an object-oriented environmentlike Java, objects are designed to interact with other objects. To create a unit test, it followsthat you need two flavors of objects: the domain object you are testing and test objects tointeract with the object under test. DEFINITION: domain object—In the context of unit testing, the term domain object is used to contrast and compare the objects you use in your application with the objects that you use to test your application (test objects). Any object under test is considered to be a domain object.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  33. 33. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 17If you used another domain object, like a logon request, and a test failed, it would be hard toidentify the culprit. You might not be able to tell if the problem was with the controller or therequest. So, in the first series of tests, the only class you will use in production isDefaultController. Everything else should be a special test class. JUnit best practices: unit-test one object at a time A vital aspect of unit tests is that they are finely grained. A unit test independently examines each object you create, so that you can isolate problems as soon as they occur. If more than one object is put under test, you cannot predict how the objects will interact when changes occur to one or the other. When an object interacts with other complex objects, you can surround the object under test with predictable test objects. Another form of software test, integration testing, examines how working objects interact with each other. See chapter 3 for more about other types of tests.WHERE DO TEST CLASSES LIVE?Where do you put the test classes? Java provides several alternatives. For starters, you coulddo one of the following: Make them public classes in your package Make them inner classes within your test case classIf the classes are simple and likely to stay that way, then it is easiest to code them as innerclasses. The classes in this example are pretty simple. Listing 2.9 shows the inner classesyou can add to the TestDefaultController class.Listing 2.9 Test classes as inner classes public class TestDefaultController { [...] private class SampleRequest implements Request (1) { public String getName() { return "Test"; } } private class SampleHandler implements RequestHandler (2) { public Response process(Request request) throws Exception { return new SampleResponse(); } } private class SampleResponse implements Response (3) { // empty } [...]©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  34. 34. Download at WoweBook.Com18 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009(1) Set up a request object that returns a known name (Test).(2) Implement a SampleHandler. The interface calls for a process method, so you haveto code that, too. You’re not testing the process method right now, so you have it return aSampleResponse object to satisfy the signature.(3) Go ahead and define an empty SampleResponse just so you have something toinstantiate.With the scaffolding from listing 2.9 in place, let’s look at listing 2.10, which shows the testfor adding a RequestHandler.Listing 2.10 TestDefaultController.testAddHandler […] import static org.junit.Assert.*; public class TestDefaultController { [...] @Test public void testAddHandler() (1) { Request request = new SampleRequest(); (2) RequestHandler handler = new SampleHandler(); (2) controller.addHandler(request, handler); (3) RequestHandler handler2 = controller.getHandler(request); (4) assertSame(“Handler we set in controller should be the same handler we get”, handler2, handler);(5) } }(1) Pick an obvious name for the test method and annotate your test method with the @Testannotation.(2) Instantiate your test objects.(3) This code gets to the point of the test: controller (the object under test) adds the testhandler. Note that the DefaultController object is instantiated by the @Before-annotated method (see listing 2.8).(4) Read back the handler under a new variable name.(5) Check to see if you get back the same object you put in. JUnit best practices: choose meaningful test method names You can see that a method is a test-method by the @Test annotation. But you also must be able to understand what a method is testing by reading the name. Although JUnit does not imply any special rules for naming your test methods, a good rule is to start with the testXXX naming scheme, where XXX is the name of the method to test. As you add other tests against the same method, move to the testXXXYYY scheme, where YYY describes how the tests differ. Don’t be afraid that the names of your tests are getting©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  35. 35. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 19 long. As you will see by the end of the chapter it is sometimes not so obvious what a method is testing simply by looking at the assert methods in it – so the only chance we have is – naming your test-methods in a descriptive fashion and putting comments where necessary.Although it’s very simple, this unit test confirms the key premise that the mechanism forstoring and retrieving RequestHandler is alive and well. If addHandler or getRequestfails in the future, the test will quickly detect the problem. As you create more tests like this, you will notice that you follow a pattern of steps:Set up the test by placing the environment in a known state (create objects, acquireresources). The pre-test state is referred to as the test fixture.Invoke the method under test.Confirm the result, usually by calling one or more assert methods.2.5.3 Processing a requestLet’s look at testing the core purpose of the controller, processing a request. Because youknow the routine, we’ll just present the test in listing 2.11 and review it.Listing 2.11 testProcessRequest import static org.junit.Assert.*; public class TestDefaultController { [...] @Test public void testProcessRequest() (1) { Request request = new SampleRequest(); (2) RequestHandler handler = new SampleHandler(); (2) controller.addHandler(request, handler); (2) Response response = controller.processRequest(request); (3) assertNotNull("Must not return a null response", response); (4) assertEquals(“Response should be of type SampleResponse”, SampleResponse.class, response.getClass()); (5) } }(1) First annotate the test with the @Test annotation and give the test a simple, uniformname.(2) Set up the test objects and add the test handler.(3) Here the code diverges from listing 2.10 and calls the processRequest method.(4) You verify that the returned Response object is not null. This is important because youcall the getClass method on the Response object. It will fail with a dreadedNullPointerException if the Response object is null. You use theassertNotNull(String, Object) signature so that if the test fails, the error displayed©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  36. 36. Download at WoweBook.Com20 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009is meaningful and easy to understand. If you had used the assertNotNull(Object)signature, the JUnit runner would have displayed a stack trace showing ajava.lang.AssertionError exception with no message, which would be more difficultto diagnose.(5) Once again, compare the result of the test against the expected SampleResponse class. JUnit best practices: explain the failure reason in assert calls Whenever you use any of the JUnit assert* methods, make sure you use the signature that takes a String as the first parameter. This parameter lets you provide a meaningful textual description that is displayed in the JUnit test runner if the assert fails. Not using this parameter makes it difficult to understand the reason for a failure when it happens.FACTORIZING SETUP LOGIC Because both tests do the same type of setup, you can try moving that code into a@Before annotated method. At the same time you don’t want to move it into a new@Before method because you are not sure which method will be executed first, and thusyou may get an exception. Instead you can move it into the same @Before method. As you add more test methods, you may need to adjust what you do in the @Beforemethods. For now, eliminating duplicate code as soon as possible helps you write more testsmore quickly. Listing 2.12 shows the new and improved TestDefaultController class(changes are shown in bold).Listing 2.12 TestDefaultController after some refactoring […] public class TestDefaultController { private DefaultController controller; private Request request; private RequestHandler handler; @Before public void initialize() throws Exception { controller = new DefaultController(); request = new SampleRequest(); (1) handler = new SampleHandler(); (1) controller.addHandler(request, handler); (1) } private class SampleRequest implements Request { // Same as in listing 2.5 } private class SampleHandler implements RequestHandler { // Same as in listing 2.5 }©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  37. 37. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 21 private class SampleResponse implements Response { // Same as in listing 2.5 } @Test public void testAddHandler() (2) { RequestHandler handler2 = controller.getHandler(request); assertSame(handler2, handler); } @Test public void testProcessRequest() (3) { Response response = controller.processRequest(request); assertNotNull("Must not return a null response", response); assertEquals(“Response should be of type SampleResponse”, SampleResponse.class, response.getClass()); } }The instantiation of the test Request and RequestHandler objects is moved toinitialize (1). This saves you repeating the same code in testAddHandler (2) andtestProcessRequest (3). Also, we make a new @Before annotated method for addingthe handler to the controller. Since @Before methods are executed before every single@Test method, we make sure we have a fully setup DefaultController object. DEFINITION: refactor — To improve the design of existing code. For more about refactoring, see Martin Fowler’s already-classic book 5Note that you do not try to share the setup code by testing more than one operation in a testmethod, as shown in listing 2.13 (an anti-example).Listing 2.13 Do not combine test methods like this (anti-example) public class TestDefaultController { [...] @Test public void testAddAndProcess() { Request request = new SampleRequest(); RequestHandler handler = new SampleHandler(); controller.addHandler(request, handler); RequestHandler handler2 = controller.getHandler(request); assertEquals(handler2,handler); // DO NOT COMBINE TEST METHODS THIS WAY Response response = controller.processRequest(request); assertNotNull("Must not return a null response", response);5 Martin Fowler, Refactoring: Improving the Design of Existing Code (Reading, MA: Addison-Wesley, 1999).©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  38. 38. Download at WoweBook.Com22 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E Last saved: 7/7/2009 assertEquals(SampleResponse.class, response.getClass()); } } JUnit best practices: one unit test equals one @Test method Do not try to cram several tests into one method. The result will be more complex test methods, which will become increasingly difficult to read and understand. Worse, the more logic you write in your test methods, the more risk there is that it will not work and will need debugging. This is a slippery slope that can end with writing tests to test your tests! Unit tests give you confidence in a program by alerting you when something that had worked now fails. If you put more than one unit test in a method, it makes it more difficult to zoom in on exactly what went wrong. When tests share the same method, a failing test may leave the fixture in an unpredictable state. Other tests embedded in the method may not run, or may not run properly. Your picture of the test results will often be incomplete or even misleading. Because all the test methods in a TestClass share the same fixture, and JUnit can now generate an automatic test suite, it’s really just as easy to place each unit test in its own method. If you need to use the same block of code in more than one test, extract it into a utility method that each test method can call. Better yet, if all methods can share the code, put it into the fixture. Another common pitfall is to make test-methods that do not contain any assert statements. When you execute those tests you see JUnit flags them as successful, but this is an illusion of successful tests. Don’t do this! For best results, your test methods should be as concise and focused as your domain methods.Each test method must be as clear and focused as possible. This is why JUnit provides youwith the @Before and @BeforeClass methods: so you can share fixtures between testswithout combining test methods.2.5.4 Improving testProcessRequestWhen we wrote the testProcessRequest method in listing 2.11, we wanted to confirmthat the response returned is the expected response. The implementation confirms that theobject returned is the object that we expected. But what we would really like to know iswhether the response returned equals the expected response. The response could be adifferent class. What’s important is whether the class identifies itself as the correct response. The assertSame method confirms that both references are to the same object. TheassertEquals method utilizes the equals method, inherited from the base Object class.©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>
  39. 39. Download at WoweBook.ComLast saved: 7/7/2009 Tahchiev, Leme, Massol, and Gregory / JUnit in Action 2E 23To see if two different objects have the same identity, you need to provide your owndefinition of identity. For an object like a response, you can assign each response its owncommand token (or name). The empty implementation of SampleResponse didn’t have a name property you cantest. To get the test you want, you have to implement a little more of the Response classfirst. Listing 2.14 shows the enhanced SampleResponse class.Listing 2.14 A refactored SampleResponse public class TestDefaultController { [...] private class SampleResponse implements Response { private static final String NAME = "Test"; public String getName() { return NAME; } public boolean equals(Object object) { boolean result = false; if (object instanceof SampleResponse) { result = ((SampleResponse) object).getName().equals(getName()); } return result; } public int hashCode() { return NAME.hashCode(); } } [...]Now that SampleResponse has an identity (represented by getName()) and its ownequals method, you can amend the test method: @Test public void testProcessRequest() { Response response = controller.processRequest(request); assertNotNull("Must not return a null response", response); assertEquals(new SampleResponse(), response); }We have introduced the concept of identity in the SampleResponse class for the purpose ofthe test. However, the tests are really telling you that this should have existed in the properResponse class. Thus you need to modify the Response interface as follows: public interface Response©Manning Publications Co. Please post comments or corrections to the Author Online forum:http://www.manning-sandbox.com/forum.jspa?forumID=502 Licensed to JEROME RAYMOND <pedbro@gmail.com>

×