Effective Unit Testing in Java
Manning Publications (Verlag)
978-1-935182-57-3 (ISBN)
- Titel ist leider vergriffen;
keine Neuauflage - Artikel merken
This book is aimed at Java programmers of all experience levels who are looking to improve the quality of the unit tests they write. While we do provide appendices that teach you about a test framework (JUnit), our primary goal is to help Java programmers who already know how to write unit tests with their test framework of choice to write better unit tests. Regardless of how many unit tests you’ve written so far, we’re certain that you can still get better at it, and reading a book like this might be just what you need to stimulate a line of thought that you’ve struggled to put into words.
- Teaches how to write good tests
- Uses state-of-the-art open source software
- Offers real-world insights from an expert author
Code is written by humans who make mistakes, hence bugs and the need for testing. Savvy Java developers know that not all testing is created equal. In addition to traditional functional testing, many shops are adopting developer testing techniques such as unit testing. Specific, automated tests are created to verify the accuracy and function of code while or even before it's written to catch bugs early. »Effective Unit Testing« teaches how to write good tests that are concise and to the point, useful, and maintainable. This book focuses on tools and practices specific to Java. It introduces emerging techniques like specification by example and behavior-driven development, and shows how to add robust practices into developers toolkits.
Developer testing has been increasing its mindshare significantly among Java developers over the past 10 years or so. Today, no computer science student graduates without having at least read about automated unit tests and their importance in software development. The idea is simple—to ensure that our code works and keeps working—but the skill takes significant effort to learn.
Some of that effort goes to simply writing tests and learning the technology such as a test framework like JUnit. Some of that effort (and quite possibly most of it) that’s required for truly mastering the practice of writing automated unit tests goes to reading test code and improving it. This constant refactoring of tests—trying out different ways of expressing your intent, structuring tests for various aspects of behavior, or building the various objects used by those tests—is our pragmatic way of teaching ourselves and developing our sense for unit tests.
That sense is as much about what good unit tests are like as it is about what not-so-good unit tests are like. There may be some absolute truths involved (such as that a code comment repeating exactly what the code says is redundant and should be removed) but the vast majority of the collective body of knowledge about unit tests is highly context-sensitive. What is generally considered good might be a terrible idea in a specific situation. Similarly, what is generally a bad idea and should be avoided can sometimes be just the right thing to do.
It turns out that often the best way to find your way to a good solution is to try one approach that seems viable, identify the issues with that approach, and change the approach to remove the icky parts. By repeating this process of constantly evaluating and evolving what you have, eventually you reach a solution that works and doesn’t smell all that bad. You might even say that it’s a pretty good approach!
With this complexity in mind, we’ve adopted a style and structure for this book where we don’t just tell you what to do and how to write unit tests. Instead, we aim to give you a solid foundation on what kind of properties we want our tests to exhibit (and why) and then give you as many concrete examples as we can to help you develop your sense for test smells—to help you notice when something about your test seems to be out of place.
Effective Unit Testing takes on a multifaceted challenge that calls for a structure that supports each of those facets. In our wisdom (gained through several iterations of failed attempts) we’ve decided to divide this book into three parts.
Part 1 begins our journey toward better tests by introducing what we’re trying to achieve and why those goals should be considered desirable in the first place. These three chapters present the fundamental tools and simple guidelines for writing a good test.
Chapter 1 starts off with the value proposition of automated unit tests. We establish the value by considering the many things that factor into our productivity as programmers and how well-written automated unit tests contribute to that productivity or prevent things from dragging us down.
Chapter 2 sets the bar high and attempts to define what makes a test good. The properties and considerations in this chapter serve as the core foundation for part 2, touching on how we want our tests to be readable, maintainable, and reliable.
Chapter 3 steps out of the line for a moment to introduce test doubles as an essential tool for writing good tests. It’s not really using test doubles that we’re after but rather using them well and with consideration. (They’re not a silver bullet in case you were wondering.)
Part 2 turns the tables and offers a stark contrast to part 1 in its approach, presenting a catalog of test smells you should watch for. Along with describing a suspect pattern in test code we’ll suggest solutions to try when you encounter such a smell. The chapters in this part are divided into three themes: smells that suggest degraded readability, smells that indicate a potential maintenance nightmare, and smells that reek of trust issues. Many of the smells in part 2 could be featured in any of these three chapters, but we’ve tried to arrange them according to their primary impact.
Chapter 4 focuses on test smells that are primarily related to the intent or implementation of a test being unnecessarily opaque. We touch on things like illegible assertions, inappropriate levels of abstraction, and information scatter within our test code.
Chapter 5 walks through test smells that might lead to late nights at the office, because it takes forever to update one mess of a unit test related to a small change or because making that small change means we need to change a hundred tests. We take on code duplication and logic in our test code and we expound on the horrors of touching the filesystem. And it’s not like we’re giving a free pass to slow tests either because time is money.
Chapter 6 concludes our catalog of test smells with a sequence of gotchas around assumptions. Some of these assumptions are made because there’s an inconvenient comment in our test code and some are the unfortunate products of a failure to express ourselves unambiguously.
Part 3 could have been called “advanced topics.” It’s not, however, because the topics covered here don’t necessarily build on parts 1 or 2. Rather, these are topics that a Java programmer might stumble onto at any point on his or her test-writing journey. After all, almost everything about “good” unit tests is context-sensitive so it’s not surprising that a pressing topic for one programmer is a minor consideration for another, whether it’s about inheritance between unit test classes, about the programming language we use for writing tests, or about the way our build infrastructure executes the tests we’ve written.
Chapter 7 picks up on where chapter 2 left off, exploring what constitutes testable design. After a brief overview of useful principles and clarifying how we are essentially looking for modular designs, we study the fundamental testability issues that untestable designs throw our way. The chapter concludes with a set of simple guidelines to keep us on the righteous path of testable design.
Chapter 8 throws a curveball by posing the question, what if we’d write our unit tests in a programming language other than Java? The Java Virtual Machine allows the modern programmer to apply a number of alternative programming languages and integrate it all with plain Java code.
Chapter 9 returns to common reality by taking on the challenge of dealing with increasingly slow build times and delayed test results. We look for solutions both within our test code, considering ways of speeding up the code that’s being run as part of our build, and in our infrastructure, pondering whether we could get that extra bit of oomph from faster hardware or from a different way of allocating work to the existing hardware.
Despite JUnit’s popularity and status as the de facto unit test framework within the Java community, not all Java programmers are familiar with this great little open source library. We’ve included two appendices to help those individuals and programmers who haven’t squeezed all the horsepower out of JUnit’s more advanced features.
Appendix A offers a brief introduction to writing tests with JUnit and how JUnit pokes and prods those tests when you tell it to run them. After skimming through this appendix you’ll be more than capable of writing tests and making assertions with JUnit’s API.
Appendix B takes a deeper dive into the JUnit API with the goal of extending its built-in functionality. While not trying to cover everything about JUnit to the last bit of detail, we’ve chosen to give you a brief overview of the two common ways of extending JUnit—rules and runners—and devote this appendix to showcasing some of the built-in rules that are not only useful, but also give you an idea of what you can do with your custom extensions.
Lasse Koskela is a coach, trainer, consultant and programmer. He hacks on open source projects, moderates discussions at JavaRanch, and writes about software development. A pioneer of the Finnish agile community, Lasse speaks frequently at international conferences. He's the author of "Test Driven," also published by Manning.
preface
acknowledgments
about this book
about the cover illustration
Part 1 Foundations
Chapter 1 The promise of good tests
State of the union: writing better tests
The value of having tests
Tests as a design tool
Summary
Chapter 2 In search of good
Readable code is maintainable code
Structure helps make sense of things
It’s not good if it’s testing the wrong things
Independent tests run easily in solitude
Reliable tests are reliable
Every trade has its tools and tests are no exception
Summary
Chapter 3 Test doubles
The power of a test double
Types of test doubles
Guidelines for using test doubles
Summary
Part 2 Catalog
Chapter 4 Readability
Primitive assertions
Hyperassertions
Bitwise assertions
Incidental details
Split personality
Split logic
Magic numbers
Setup sermon
Overprotective tests
Summary
Chapter 5 Maintainability
Duplication
Conditional logic
Flaky test
Crippling file path
Persistent temp files
Sleeping snail
Pixel perfection
Parameterized mess
Lack of cohesion in methods
Summary 113
Chapter 6 Trustworthiness
Commented-out tests
Misleading comments
Never-failing tests
Shallow promises
Lowered expectations
Platform prejudice
Conditional tests
Summary
Part 3 Diversions
Chapter 7 Testable design
What’s testable design?
Testability issues
Guidelines for testable design
Summary
Chapter 8 Writing tests in other JVM languages
The premise of mixing JVM languages
Writing unit tests with Groovy
Expressive power with BDD tools
Summary
Chapter 9 Speeding up test execution
Looking for a speed-up
Speeding up test code
Speeding up the build
Summary
appendix A JUnit primer
appendix B Extending JUnit
index
On the night of June 10, 2009, I found an email in my inbox from Christina Rudloff from Manning, asking me if I knew anyone who might be a good candidate to write a Java edition of Roy Osheroves book, The Art of Unit Testing in .NET. I told her Id do it. That was a long time ago and what youre looking at right now has very little in common with Roys book. Let me explain. The project started as a straight translation from .NET to Java, only rewriting where necessary to match the changing technology platform, its tooling, and its audience. I finished the first chapter, the second chapter, the third chapter, and suddenly I found myself rewriting not just short passages but entire chapters. The tone of voice wasnt mine; sometimes I would disagree or have preferences incompatible with Roys, and sometimes I simply felt strongly about saying something, setting things straight, and putting a stake into the ground. Eventually, I decided to start over. It was clear that we were not in a translation project. This was a brand new title of its owna book that helps a Java programmer improve his tests, gaining a deeper insight into what makes a test good and what kind of pitfalls to look out for. You can still see Roys thinking in many ways in this book. For instance, the chapter titles of the catalog in part 2 Ive blatantly borrowed from Roy and chapter 7 was written largely thanks to Roys counterpart in The Art of Unit Testing in .NET. This is a book for the Java programmer. Yet, I didnt want to straitjacket the ideas in this book artificially, so I tried to steer away from being too language-specific even though all of the code examples in the pattern catalog, for example, are Java. Writing good tests is a language-agnostic problem and I heartily recommend you read this book thoughtfully, even if you happen to spend most of your office hours hacking on another programming language. Along those same lines, I didnt want to give you a tutorial on JUnit or my favorite mock object library. Aside from such technology being a constantly changing landscape and bound to become stale information within months of publication, I wanted to write the kind of book that I would want to read. I like focused books that dont force me to lug around dead weight about a testing framework I already know by heart or a mock object library I dont use. For these reasons, Ive tried to minimize the amount of technology-specific advice. There is some but I want you to know that Ive done my best to keep it to a minimumjust enough to have meaningful conversations about the underlying concepts that I find essential in writing, running, maintaining, and improving tests. I tried to write the book I wouldve wanted to read. I hope you will enjoy it and, most importantly, integrate some of these ideas into your own practice.
Erscheint lt. Verlag | 7.3.2013 |
---|---|
Zusatzinfo | illustrations |
Verlagsort | New York |
Sprache | englisch |
Maße | 188 x 232 mm |
Gewicht | 422 g |
Einbandart | kartoniert |
Themenwelt | Informatik ► Programmiersprachen / -werkzeuge ► Java |
Informatik ► Software Entwicklung ► Qualität / Testen | |
ISBN-10 | 1-935182-57-9 / 1935182579 |
ISBN-13 | 978-1-935182-57-3 / 9781935182573 |
Zustand | Neuware |
Haben Sie eine Frage zum Produkt? |
aus dem Bereich