getting started, raw newbie

59 views
Skip to first unread message

matt wilkie

unread,
Sep 29, 2010, 7:56:29 PM9/29/10
to Pythoscope
Hello,

I'm a fledgling developer in general and a raw newbie when it comes to
unit testing at all, so perhaps I'm not in the right place. If this is
the case, kindly direct me to fairer shores.

I've sampled some unit testing kool-aid[1] and liked the flavour.
However when I try and apply testing to the small body of work I have
and understand[2], I run aground. It was the search to get this ship
back in the water that led me to pythoscope, with hope. I'm still on
the shoals though. Does anyone here have the time and inclination to
instruct with an example or two of what magic spell goes in "assert
False # TODO: implement your test here" to get me started?

---- function from [3] ----
def get_fc_list():
''' return list of feature class names '''
# these really should be read from a file or a command argument
instead of hardcoded
feature_classes = [ "BS_1250009_0", "BS_1370009_2",
"BS_2000009_0",
"BS_2010009_0", "BS_2010009_2", "BS_2060009_0", "BS_2080009_0"]
return feature_classes

--- corresponding pythoscope test [4] ---
import unittest

class TestGetFcList(unittest.TestCase):
def test_get_fc_list(self):
# self.assertEqual(expected, get_fc_list())
assert False # TODO: implement your test here

if __name__ == '__main__':
unittest.main()
------


[1] http://stackoverflow.com/questions/67299/is-unit-testing-worth-the-effort
[2] http://trac.osgeo.org/osgeo4w/browser/trunk/apt
http://bitbucket.org/maphew/canvec
[3] http://bitbucket.org/maphew/canvec/src/d3229191dfda/Canvec/Scripts/drop-items.py
[4] http://bitbucket.org/maphew/canvec/src/d3229191dfda/Canvec/Scripts/tests/test_drop-items.py

many thanks!

-matt

Pieter Van Dyck

unread,
Sep 30, 2010, 9:19:53 PM9/30/10
to pytho...@googlegroups.com
Hi Matt,

I've learned that the best way to understand something is to try and explain it, so I'll give it a shot.
I don't think a basic HowTo discussion is off topic but if people object we can take it off-list.

Indeed unittests are a cool aid but they're not magic.
Very much simplified, they work best piecemeal and up front.
Done that way they tend to increase productivity and are fun to do.

Retro-fitting unittests to existing code, on the other hand, is a different matter all together.
I'd advise against it unless you have to (and in that case get a copy of this book first: http://my.safaribooksonline.com/0131177052?bookview=toc)
Pythoscope can help with some of it but most of the frustrating work is still yours.

Ok, after that extended caveat, let's take a look at your example and see if we can identify the right incantation.

First off, note that an example of such incantation is commented out right before the 'assert False' statement.
Currently, the standard suggestions by Pythoscope are useful but fairly trivial, use them as a starting point to build your own incantations.
Pythoscope is capable of generating more concrete tests if you feed it examples of how your function is called btw.

A first attempt might look like this:
---- pythoscope inspired test 1 ----
import unittest
import drop_items

class TestGetFcList(unittest.TestCase):
   def test_get_fc_list(self):
      expected = [ "BS_1250009_0", "BS_1370009_2","BS_2000009_0",
   "BS_2010009_0", "BS_2010009_2", "BS_2060009_0", "BS_2080009_0"]

       self.assertEqual(expected, drop_items.get_fc_list())
------

Not very exciting but then the function under test doesn't actually do much either. It's really not more than a glorified constant at this point.
That could be all there is to it if the concrete values in the list are what's important.

Chances are that the values are only incidental.
Maybe what's really important is that the function returns a list with 7 elements for instance.
In that case our test might look more like this (in python 2.7):
---- pythoscope inspired test 2 ----
import unittest
import drop_items

class TestGetFcList(unittest.TestCase):
   def test_get_fc_list_returns_list(self):
      self.assertIsInstance(drop_items.get_fc_list(), list)
   def test_get_fc_list_returns_7_elements(self):
      expected = 7
      fcs = drop_items.get_fc_list()
      self.assertEqual(expected, len(fcs))
------

For a simple function as this we could even decide to skip unittests and instead write tests for its callers.

A lot more can be said about the subject but there's plenty of books and articles out there already so I'll leave it at that.

cheers,
Pieter


--
You received this message because you are subscribed to the Google Groups "Pythoscope" group.
To post to this group, send email to pytho...@googlegroups.com.
To unsubscribe from this group, send email to pythoscope+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pythoscope?hl=en.


Matt Wilkie

unread,
Oct 12, 2010, 2:18:57 PM10/12/10
to pytho...@googlegroups.com
Hi Pieter, thank you for the information and examples. I appreciate
the time spent.

--
-matt

Pieter Van Dyck

unread,
Oct 13, 2010, 10:03:08 AM10/13/10
to pytho...@googlegroups.com
You're welcome Matt.

It may be helpful to realise that unittests are not so much about testing as they are about documenting our understanding or expectations about a piece of code.
The testing is just there to detect when the code stops behaving according to our expectations.

When you write unittests up front, they can be fun because it feels a lot like playing around with the code 'to see what it does'.
Except you're taking executable notes so you can easily repeat your playing around and extend it as needed.

In principle, the same goes for writing unittests on existing code but often that code wasn't written to be tested and the experience quickly turns frustrating as you try to untangle dependencies.

Pieter

-matt

Reply all
Reply to author
Forward
0 new messages