Browser methods

The browser object retrieved with twill.get_browser has the following useful methods Many of those work just as the related Twill command, except that you pass the parameters as strings into a method call e.g. browser.save_cookies 'cookies.txt' . A few of them behave differently, though, or don't have a Twill language equivalent, so we'll go into more detail about those now The get_code method returns the HTTP code for the current page. It doesn't do any comparisons between the code and an...

Running Your Tests Follow Your Nose

So far, we've talked a lot about how to write tests, but we haven't said much about how to run them. We've had to explicitly tell Python which tests to run, and we've had the either worry about which version of Python we were using in the case of doctest or put an if _name_ '_main_' inside every module for unittest . Clearly, there's room for improvement, when it comes to running tests. Learn about a Python tool called Nose, which automatically finds and executes tests Learn how to make Nose...

Installing Twill

You can find Twill in the Python Package Index at http pypi.python.org pypi twill . At the time of writing, the latest version can be directly downloaded from Windows users will need to use an archiving program which understands Tar and GZip formats, such as 7-Zip http www.7-zip.org to extract the files. Once you have the files unpacked, you can install them by opening a command prompt, changing to the twill-0.9 directory, and running or, if you can't write to Python's site-packages directory,...

A nifty trick

If you're using Python 2.4 or greater, you can define a function decorator that makes it simple to write Twill tests as Python functions. from twill.parse import execute_string from twill.errors import TwillAssertionError def twill_test func execute_string func._doc_, no_reset False if args and hasattr args 0 , 'fail' If you put that code in a Python module here called twill_decorator and then import twill_test into your testing code, you can write Twill tests like so from unittest import...

What just happened Ehn

We used Twill to browse to slashdot.org, navigated into the Science section, searched for aardvark, and then checked to see if the resulting page contained the words aardvark and Elephant. Of what use it that We're not limited to goofing around on slashdot.org. We can use the Twill language to describe any interaction between a web browser and a web server. That means, we can use it to describe the expected behavior of our own web applications. If we can describe expected behavior, we can write...

Time for action testing PID with unittest

We'll revisit the PID class or at least the tests for the PID class from Chapter 3. We'll rewrite the tests so that they operate within the unittest framework. Before moving on, take a moment to refer back to the final version of the pid.txt file from Chapter 3. We'll be implementing the same tests using the unittest framework. 1. Create a new file called test_pid.py in the same directory as pid.py. Notice that this is a .py file unittest tests are pure python source code, rather than being...

Integrating Twill operations into unittest tests

So far, our unit tests have treated each Twill script as a single operation that produces either a success or a failure. What if we want to, say, download an HTML page, perform some assertions about relationships between its content and a database, then follow a link to another page We can do this sort of thing by accessing Twill's browser object directly from our test code. The browser object has methods similar to the commands of the Twill language, so this should seem fairly familiar.

What just happened Rbl

Instead of using the Twill language to describe the interaction with a web site, we used Twill as a library that we could call from our test code. This allowed us to interleave Twill operations with unittest assertions. We could have included any other operations that we needed, as well. Using this technique, our tests can treat the web as just one more source of data that they can access. It's important to notice the differences between the Twill language and the methods available on the...

Time for action exploring the basics of Mocker

We'll walk through some of the simplest and most useful features of Mocker. To do that, we'll write tests that describe a class representing a specific mathematical operation multiplication which can be applied to the values of arbitrary other mathematical operation objects. In other words, we'll work on the guts of a spreadsheet program or something similar . We're going to use Mocker to create mock objects to stand in place of the real operation objects. 1. Create up a text file to hold the...

Time for action creating a fixture for a doctest

We'll provide a mock time.time in our test fixture and use it in our doctest. 1. Create a file called times.txt containing the following doctest code This isn't a reasonable test for any purpose, but it serves to illustrate a test that can't work without a mock object in place. 2. Run the doctest file using Nose, and the following screen gets displayed File line 2131, in runTest raise value 0 AssertionError Failed doctest test for times.txt File line 6, in times.txt Failed example File line 8,...

Time for action unit testing during development

1. The first step is to run the tests. Of course, we have a pretty good idea of what's going to happen they're all going to fail. Still, it's useful to know exactly what the failures are, because those are the things that we need to address by writing code. File pid.txt, line 5, in pid.txt Failed example import pid Exception raised File '7usr lib64 python2.6 doctest.py, line 1231, in__run compileflags, 1 in test.globs File lt doctest pid.txt 0 gt , line 1, in lt module gt import pid ImportError...

Table of Contents

Chapter 1 Testing for Fun and Profit_7 Chapter 2 Doctest The Easiest Testing Tool_11 Time for action - creating and running your first doctest 12 Time for action - writing a more complex test 14 Time for action - expecting an exception 16 Expecting blank lines in the output 17 Using directives to control doctest 17 Time for action - using ellipsis in tests 17 Time for action - normalizing whitespace 19 Skipping an example entirely 19 Time for action - skipping tests 20 Embedding doctests in...

Integrating with Python Mocker

You've used Mocker enough to see the repetitiveness involved in creating a mocking context at the beginning of the text and calling its verify and restore methods at the end. Mocker simplifies this for you by providing a class called MockerTestCase in the mocker module. MockerTestCase behaves just like a normal unittest TestCase, except that for each test, it automatically creates a mocking context, which it then verifies and restores after the test. The mocking context is stored in...

Putting it in practice an AVL tree

We'll walk step-by-step through the process of using doctest to create a testable specification for a data structure called an AVL Tree. An AVL tree is a way to organize key-value pairs, so that they can be quickly located by key. In other words, it's a lot like Python's built-in dictionary type. The name AVL references the initials of the people who invented this data structure. As its name suggests, an AVL tree organizes the keys that are stored in it into a tree structure, with each key...

Summary Rak

In this chapter, we looked at how to apply the skills covered in earlier parts of this book. We did this by stepping through a recording of your humble author's actual process in writing a package. At the same time, you had the chance to work through your own project, making your own decisions, and designing your own tests. You've taken the lead in a test-driven project, and you should be able to do it again whenever you want. Now that we've covered the heart of Python testing, we're ready to...

Make deletable

You can't delete a node that has children, because that would leave the node's children disconnected from the rest of the tree. If we delete the Elephant node from the bottom of the tree, what do we do about Aardvark, Goose, and Frog If we delete Goose, how do we find Frog afterwards The way around that is to have the node swap places with it's largest leaf descendant on the left side or its smallest leaf descendant on the right side, but we'll not do it that way . We'll test this by using the...

Testing Web Application Frontends using Twill

We haven't talked at all about testing user interfaces. Mostly because graphical user interfaces are not very amenable to being checked by automated testing tools it can be difficult to feed input to the system and difficult to disentangle all of the units involved . However, web applications are an exception to that rule, and their importance keeps increasing. Learn to use Twill to script interactions with web sites Learn how run Twill scripts from inside a testing framework Learn how to...

Time for action using Buildbot with Bazaar

1. To set up a buildmaster, create a directory for it to operate in and then run the command buildbot create-master lt directory gt where lt directory gt is the directory you just created for buildbot to work in. 2. Similarly, to set up a buildslave, create a directory for it to operate in and then run the command buildbot create-slave lt directory gt lt host port gt lt name gt lt password gt where lt directory gt is the directory you just created for the buildbot to work in, lt host port gt...

Automation with doctest unittest and Nose

The only real difference between an integration test and a unit test, is that you could break the code being tested into smaller meaningful chunks, in an integration test. In a unit test, if you divided the code up any more it wouldn't be meaningful. For this reason, the same tools that help automate unit testing can be applied to integration testing. Since system testing is really the highest level of integration testing, the tools can be used for that as well. The role of doctest in...

Time for action using ellipsis in tests

We'll use the ellipsis in a few different tests, to get a better feel for what it does and how to use it. 1. Insert the following text into your doctest file Next up, we're exploring the ellipsis. gt gt gt sys.modules doctest ELLIPSIS 'sys' lt module 'sys' built-in gt gt gt gt 'This is an expression that evaluates to a string' doctest ELLIPSIS 'This is a string' gt gt gt 'This is also a string' doctest ELLIPSIS 'This is a string' gt gt gt datetime.datetime.now .isoformat doctest ELLIPSIS 2. Run...

Time for action normalizing whitespace

We'll write a couple tests that demonstrate how whitespace normalization works. 1. Insert the following text into your doctest file Next, a demonstration of whitespace normalization. gt gt gt 1, 2, 3, 4, 5, 6, 7, 8, 9 doctest NORMALIZE_WHITESPACE text n contains weird spacing. doctest NORMALIZE_WHITESPACE This text contains weird spacing. 2. Run the tests using doctest and the following screen is displayed File test.txt, line 7, in test.txt Failed example 1 of 13 in test.txt Jest Failed 1...

Time for action browsing the web with Twill

We'll take Twill for a spin, using its interactive interpreter. 1. Start the interactive Twill interpreter If you're using a version of Python older than 2.6, you won't be able to do a - -user installation, which means you'll need to have write access to the Python installation's site-packages directory. You may notice a couple of warnings about the deprecated md5 module when you start Twill. You may safely ignore them. 2. Get a list of Twill commands. You can get further information about a...

Time for action creating and running your first doctest

We'll create a simple doctest, to demonstrate the fundamentals of using doctest. 1. Open a new text file in your editor, and name it test.txt. 2. Insert the following text into the file This is a simple doctest that checks some of Python's arithmetic operations. 3. We can now run the doctest. The details of how we do that depend on which version of Python we're using. At the command prompt, change to the directory where you saved test.txt. 4. If you are using Python 2.6 or higher, type python...

Summary Kio

We learned a lot in this chapter about Twill, and how to use it to write tests for web applications. Invoking Twill scripts from Python tests Integrating Twill's capabilities as a library into Python testing code Now that we've learned about testing web applications, we're ready to move on to talking about integration testing and system testing - which is the topic of the next chapter.

Time for action running Twill script files

The first way is to store the Twill script in a separate file, and then use the twill.parse. execute_file function to run it. 1. Place the following code into a file called fail.twill go http slashdot.org 2. Naturally, this script will fail, but go ahead and run it with twill-sh to see for yourself. 3. Now to run the script from Python. Pull up an interactive Python shell and do the following gt gt gt from twill.parse import execute_file gt gt gt execute file 'fail.twill' AT LINE fail.twill 0...

Mocking functions

Normal objects that is to say, objects with methods and attributes created by instantiating a class aren't the only things you can make mocks of. Functions are another kind of object that can be mocked, and it turns out to be pretty easy. During your demonstration, if you want a mock object to represent a function, just call it. The mock object will recognize that you want it to behave like a function, and it will make a note of what parameters you passed it, so that it can compare them against...

Twill commands

Twill has a number of commands, and so far we've only covered a few of them. In this section you'll find a brief discussion of each of Twill's commands. The help command prints out a list of all of Twill's commands, or tells you the details of a specific command. For example, to get the details of the add_auth command, you should type Help for command add_auth add_auth lt realm gt lt uri gt lt user gt lt passwd gt Add HTTP Basic Authentication information for the given realm uri. If you want to...

Installing Nose

At the time of this writing, Nose's home page is http code.google.com p python-nose , with downloads available at http code.google.com p python-nose downloads list. Go ahead and download the latest version, and uncompress it into a temporary directory. If you're using Windows, you'll need a program such as 7-Zip http 7-zip.org to uncompress the file Linux and Mac users won't need any special software. After uncompressing Nose, we need to install it. Everything we had to consider when installing...

Calling functions via a mock

Sometimes a function that we're mocking has side-effects that are important to our tests. Mocker handles these situations by allowing you to specify one or more functions that should be called, when a particular expression occurs. These functions can either be existing functions that are pulled from somewhere in your codebase, or they can be special functions that you've embedded in your test specifically to produce the desired side effects. There is one restriction on which functions can be...

Replacing library objects with mocks

Several times, we've seen a need to replace something outside of our own code with a mock object for example, time.time needed to be replaced with something that produced predictable results, in order for the tests on our PID controller to be meaningful. Mocker provides us with a tool to address this common need, and it's quite simple to use. Mocker's mocking contexts contain a method called replace which behaves pretty much like mock from our point of view, but which is able to completely...

Time for action installing Nose as a Git postcommit hook

1. The hooks are stored in a subdirectory of a Git repository, so the first thing that we need to do is initialize a repository. Make a new directory for the Git repository and execute the following command inside of it 2. Git hooks are executable programs, so they can be written in any language. To run Nose, it makes sense to use a shell script on Unix-like systems or batch file on Windows for the hook. If you're using a Unix-like system, place the following two lines into a file called...

Time for action installing Nose as a Mercurial postcommit hook

1. We'll use the repository configuration file to store the hook, which means that the first thing we have to do is have a repository to work with. Make a new directory at a convenient place and execute the following command in it 2. One side-effect of that command is that a .hg subdirectory got created. Change to that directory, and then create a text file called hgrc containing the following text 3. Back in the repository directory i.e. the parent of the .hg directory , we need some tests for...

Time for action creating a package fixture

Now we'll create a fixture that wraps around all the test modules in an entire package. 1. Add a new file called_init_.py in the tests directory that we created in the last Time for action section. That's two underbars, the word 'init, and two more underbars . The presence of this file tells Python that the directory is a package. Place the following code inside of_init_.py in the tests directory from mocker import Mocker from datetime import datetime fake_datetime mocker.replace datetime...