Dark theme

Writing tests


Let's design a class to deal with latitude and longitude format data. We'll get it to store data in the range 0-90 North or South, and 0-180 East or West. We want functions to be able to find out the degrees and the direction, along with both. To make things simplier, for now, we'll just deal with longitude. Here's the UML of the class we want to ultimately make:

string def get_long_degrees() --> int # 0 - 180 def get_long_direction() --> string # 'E' or 'W' " title=" class LatLong(): def set_long(longitude: string) def get_long() --> string\n def get_long_degrees() --> int # 0 - 180 def get_long_direction() --> string # 'E' or 'W' ">


Here's the start of a class that tests this: testlatlong.py.

Take the time initially to understand what the tests are doing. We not only test for likely good arguments, but also arguments which are likely to be a problem. Associated with these we're said we expect an exception back (we'll build the exception classes ourselves). Compare the tests with our outline above. You'll see we've shifted most of the actual checking of arguments to set_long as there's really no point in holding bad arguments. If set_long does the checking of arguments, there's no real need for elaborate testing of the return values, provided we've called set_long first.

Note also the difference in call signature between assertEqual(a.get_long(), "10E") and assertRaises(latlong.NumberOutOfRangeError, a.set_long, "1000E"). This is jsut how they are written: assertEqual compares and two things, not least so you can compare direct access variables; assertRaises takes in an exception class name, a function name, and the parameters for the function. Here's the documentation for assertEqual and assertRaises.

Finally, note that for the sound arguments, we don't actually test set_long (though we could access the variable directly), instead we call get_long to check it has worked ok. There's no right answer to testing methods that don't return anything; you have to decide on direct access to the variables or a function call as seems to minimise possible side effects.


Can you design the tests for the remaining two functions get_long_degrees and get_long_direction? Note that they don't need any very elaborate tests as set_long does most of the checking; what they do need, however, is to catch a new type of exception if the value hasn't yet been set using set_long: you can make up a name for this (most end in Error as you can see).

Once you've written them, we'll then write the code to match the tests!