Unit testing is a well established practice to ensure your code actually does what it’s supposed to do. If you have good test coverage — most of your code has tests that cover it — then you’ll be much more confident about refactoring and making changes without worrying that you’re going to break something. But, unit tests are not always simple to write. Unit test are most useful if they run fast and don’t take too long to write and maintain.
The best case is if you have a pure function that takes some inputs and always returns the same output for those inputs. All you have to do is come up with several representative inputs and verify in the test that your function indeed returns the expected output. But, often your code will depend on other components, read something from a file or a database, log some information and may even have some side effects like sending email.
How would you test such code? The answer is mocking. You replace the dependency on the external component or the side effect with a fake that presents that same interface, but typically does nothing except storing the calls and the arguments and returning a canned response.
For example, consider the following function:
def send_promotion(customer_emails, promotion_message): for email in customer_emails: mail_sender.send_mail(email, promotion_message)
You definitely don’t want to email all your customers whenever you run a test. The solution is to replace the
send_mail() method of the mail_sender module with a mock that on every call just stores the fact that the code under test tried to send an email to customer X with message M. Then, in your test you can first replace
mail_sender.send_mail() with your mock
send_mail() function, then call the target function
send_promotion() with some customer_emails and a promotion message. Once
send_promotion() returns you can verify that indeed your mock
send_mail()function was called for each customer in the list and that the test of the message was indeed the promotion message.
This is a very simple example, of course. In practice the
send_promotion() function may perform some formatting to the actual email sent. The list of customers may be pruned based on various criteria and you may need to write multiple tests to cover all the possibilities.