Thông tin tài liệu:
Growing Object-Oriented Software, Guided by Tests- P8: Test-Driven Development (TDD) hiện nay là một kỹ thuật được thành lập để cung cấp các phần mềm tốt hơn nhanh hơn. TDD là dựa trên một ý tưởng đơn giản: các bài kiểm tra Viết cho code của bạn trước khi bạn viết đoạn code riêng của mình. Tuy nhiên, điều này "đơn giản" ý tưởng có kỹ năng và bản án để làm tốt. Bây giờ có một tài liệu hướng dẫn thiết thực để TDD mà sẽ đưa bạn vượt ra ngoài những khái niệm cơ bản. Vẽ trên một...
Nội dung trích xuất từ tài liệu:
Growing Object-Oriented Software, Guided by Tests- P8326 Chapter 27 Testing Asynchronous Code brittle—they would misreport if the system changes the assumptions they’ve been built on. One response is to add a test to confirm those expectations—in this case, perhaps a stress test to confirm event processing order and alert the team if circumstances change. That said, there should already be other tests that confirm those assumptions, so it may be enough just to associate these tests, for example by grouping them in the same test package. Distinguish Synchronizations and Assertions We have one mechanism for synchronizing a test with its system and for making assertions about that system—wait for an observable condition and time out if it doesn’t happen. The only difference between the two activities is our interpre- tation of what they mean. As always, we want to make our intentions explicit, but it’s especially important here because there’s a risk that someone may look at the test later and remove what looks like a duplicate assertion, accidentally introducing a race condition. We often adopt a naming scheme to distinguish between synchronizations and assertions. For example, we might have waitUntil() and assertEventually() methods to express the purpose of different checks that share an underlying implementation. Alternatively, we might reserve the term “assert” for synchronous tests and use a different naming conventions in asynchronous tests, as we did in the Auction Sniper example. Externalize Event Sources Some systems trigger their own events internally. The most common example is using a timer to schedule activities. This might include repeated actions that run frequently, such as bundling up emails for forwarding, or follow-up actions that run days or even weeks in the future, such as confirming a delivery date. Hidden timers are very difficult to work with because they make it hard to tell when the system is in a stable state for a test to make its assertions. Waiting for a repeated action to run is too slow to “succeed fast,” to say nothing of an action scheduled a month from now. We also don’t want tests to break unpredictably because of interference from a scheduled activity that’s just kicked in. Trying to test a system by coinciding timers is just too brittle. The only solution is to make the system deterministic by decoupling it from its own scheduling. We can pull event generation out into a shared service that is driven externally. For example, in one project we implemented the system’s scheduler as a web service. System components scheduled activities by making HTTP requests to the scheduler, which triggered activities by making HTTP “postbacks.” In another project, the scheduler published notifications onto a message bus topic that the components listened to. Externalize Event Sources 327 With this separation in place, tests can step the system through its behaviorby posing as the scheduler and generating events deterministically. Now we canrun system tests quickly and reliably. This is a nice example of a testing require-ment leading to a better design. We’ve been forced to abstract out scheduling,which means we won’t have multiple implementations hidden in the system.Usually, introducing such an event infrastructure turns out to be useful formonitoring and administration. There’s a trade-off too, of course. Our tests are no longer exercising the entiresystem. We’ve prioritized test speed and reliability over fidelity. We compensateby keeping the scheduler’s API as simple as possible and testing it rigorously(another advantage). We would probably also write a few slow tests, running ina separate build, that exercise the whole system together including the realscheduler.This page intentionally left blankAfterwordA Brief History of MockObjectsTim MackinnonIntroductionThe ideas and concepts behind mock objects didn’t materialise in a single day.There’s a long history of experimentation, discussion, and collaboration betweenmany different developers who have taken the seed of an idea and grown it intosomething more profound. The final result—the topic of this book—should helpyou with your software development; but the background story of “The Makingof Mock Objects” is also interesting—and a testament to the dedication of thepeople involved. I hope revisiting this history will inspire you too to challengeyour thoughts on what is possible and to experiment with new practices.OriginsThe story began on a roundabout1 near Archway station in London in late 1999.That evening, several members of a London-based software a ...