def testInternMakesCoffee(self): self.caffeinated = False def DrinkCoffee(): self.caffeinated = True DelegateToIntern(work=Intern().MakeCoffee, callback=DrinkCoffee) self.assertFalse(self.caffeinated, "I watch YouTubework; intern brews") time.sleep(60) # 1min should be long enough to make coffee, right? self.assertTrue(self.caffeinated, "Where's mah coffee?!?")
def testInternMakesCoffee(self): is_started, can_finish, is_done = Event(), Event(), Event() def FakeCoffeeMaker(): is_started.set() # Allow is_started.wait() to return. # Wait up to 1min for can_finish.set() to be called. The timeout # prevents failures from hanging, but doesn't delay a passing test. can_finish.wait(timeout=60) # .await() in Java DelegateToIntern(work=FakeCoffeeMaker, callback=lambda:is_done.set()) is_started.wait(timeout=60) self.assertTrue(is_started.isSet(), "FakeCoffeeMaker should have started") self.assertFalse(is_done.isSet(), "Don't bug me before coffee's made") can_finish.set() # Now let FakeCoffeeMaker return. is_done.wait(timeout=60) self.assertTrue(is_done.isSet(), "Intern should ping when coffee's ready")
Those fortunate enough to program asynchronously with Qt4 C++ can use a combination of QSignalSpy and KDE's QTest::kWaitForSignal to get the same behavior.cfr http://api.kde.org/4.1-api/kdelibs-apidocs/kdecore/html/namespaceQTest.html
Separating the behavior of an object from the execution context is also a good idea. Java 5 ExecutorService objects are a great way to determine at run time the execution context. Rather than spawning threads, dependency injection can be used to give an object an executor service, and then in unit tests the executor service passed can be a SerialExecutorService which executes everything on the current thread. This isn't the best description, but more here: http://hamletdarcy.blogspot.com/2007/05/unit-testing-multi-threaded-code-with.html
Q: Shouldn't the order of these two lines be:is_done.wait(timeout=60)can_finish.set() # Now let FakeCoffeeMaker return.
Your test is named testInternMakesCoffee() but after your magic refactor you're not testing an intern's ability to make coffee, you're testing your test, or at best your Delegator. Or maybe you should have renamed your test to testDelegateToIntern()How would you actually write a test for Intern().MakeCoffee in a threaded environment?
The comments you read and contribute here belong only to the person who posted them. We reserve the right to remove off-topic comments.