Appendix I: What to Do Next
Here I offer a few suggestions for things to investigate next, to develop your testing skills, and to apply them to some of the cool new technologies in web development (at the time of writing!).
I hope to turn each one of these into at least some sort of blog post, if not a future appendix to the book. I hope to also produce code examples for all of them, as time goes by. So do check out http://www.obeythetestinggoat.com, and see if there are any updates.
Or, why not try to beat me to it, and write your own blog post chronicling your attempt at any one of these?
I’m very happy to answer questions and provide tips and guidance on all these topics, so if you find yourself attempting one and getting stuck, please don’t hesitate to get in touch at [email protected]!
Notifications—Both on the Site and by Email
It would be nice if users were notified when someone shares a list with them.
You can use django-notifications to show a message to users the next time they refresh the screen. You’ll need two browsers in your FT for this.
And/or, you could send notifications by email. Investigate Django’s email test capabilities. Then, decide this is so critical that you need real tests with real emails. Use the IMAPClient library to fetch actual emails from a test webmail account.
Switch to Postgres
SQLite is a wonderful little database, but it won’t deal well once you have more than one web worker process fielding your site’s requests. Postgres is everyone’s favourite database these days, so find out how to install and configure it.
You’ll need to figure out a place to store the usernames and passwords for your local, staging, and production Postgres servers. Since, for security, you probably don’t want them in your code repository, look into ways of modifying your deploy scripts to pass them in at the command line. Environment variables are one popular solution for where to keep them…
Experiment with keeping your unit tests running with SQLite, and compare how much faster they are than running against Postgres. Set it up so that your local machine uses SQLite for testing, but your CI server uses Postgres.
Run Your Tests Against Different Browsers
Selenium supports all sorts of different browsers, including Chrome and Internet Exploder. Try them both out and see if your FT suite behaves any differently.
You should also check out a "headless" browser like PhantomJS.
In my experience, switching browsers tends to expose all sorts of race conditions in Selenium tests, and you will probably need to use the interaction/wait pattern a lot more (particularly for PhantomJS).
404 and 500 Tests
A professional site needs good-looking error pages. Testing a 404 page is easy, but you’ll probably need a custom "raise an exception on purpose" view to test the 500 page.
The Django Admin Site
Imagine a story where a user emails you wanting to "claim" an anonymous list. Let’s say we implement a manual solution to this, involving the site administrator manually changing the record using the Django admin site.
Find out how to switch on the admin site, and have a play with it. Write an FT that shows a normal, non–logged-in user creating a list, then have an admin user log in, go to the admin site, and assign the list to the user. The user can then see it in their "My Lists" page.
Write Some Security Tests
Expand on the login, my lists, and sharing tests—what do you need to write to assure yourself that users can only do what they’re authorized to?
Test for Graceful Degradation
What would happen if our email server goes down? Can we at least show an apologetic error message to our users?
Caching and Performance Testing
Find out how to install and configure
memcached. Find out how to use
ab to run a performance test. How does it perform with and without
caching? Can you write an automated test that will fail if caching is not
enabled? What about the dreaded problem of cache invalidation? Can tests
help you to make sure your cache invalidation logic is solid?
Pick a framework—perhaps Backbone.js or Angular.js—and spike in an implementation. Each framework has its own preferences for how to write unit tests, so learn the one that goes along with it, and see how you like it.
Async and Websockets
Supposing two users are working on the same list at the same time. Wouldn’t it be nice to see real-time updates, so if the other person adds an item to the list, you see it immediately? A persistent connection between client and server using websockets is the way to get this to work.
Check out one of the Python async web servers—Tornado, gevent, Twisted—and see if you can use it to implement dynamic notifications.
To test it, you’ll need two browser instances (like we used for the list sharing tests), and check that notifications of the actions from one appear in the other, without needing to refresh the page…
Switch to Using py.test
py.test lets you write unit tests with less boilerplate. Try converting some of your unit tests to using py.test. You may need to use a plugin to get it to play nicely with Django.
Check Out coverage.py
coverage.py will tell you what your test coverage is—what percentage of your code is covered by tests. Now, in theory, because
we’ve been using rigorous TDD, we should always have 100% coverage. But it’s
nice to know for sure, and it’s also a very useful tool for working on projects
that didn’t have tests from the beginning.
One way of testing it might be to have an "administrator" user that goes to the Django admin view to inspect users' lists, and checks that they are stored encrypted in the database.
Your Suggestion Here
What do you think I should put here? Suggestions, please!