[Tutor] urllib2 and tests

Steven D'Aprano steve at pearwood.info
Sun May 5 06:08:15 CEST 2013


On 05/05/13 13:27, RJ Ewing wrote:
> When I run the following test.py, I get the following error:
[...]
> If I run the fetch_file function outside of the test, it works fine. Any
> ideas?

The code you are actually running, and the code you say you are running below, are different. Your error message refers to a file test_filefetcher.py, not the Test.py you show us. As given, Test.py cannot possibly work, since it doesn't define "filefetcher". I can only guess that this is meant to be the module you are trying to test, but since you don't show us what is in that module, I can only guess what it contains.


More comments below:


> RROR: test_fetch_file (__main__.TestFileFetcher)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
>    File "test_filefetcher.py", line 12, in test_fetch_file
>      fetched_file = filefetcher.fetch_file(URL)

What's filefetcher? I'm guessing its the module you are testing, which is consistent with the next line showing the file name filefetcher.py:


>    File "/Users/rjewing/Documents/Work/filefetcher.py", line 7, in fetch_file
>      return urllib2.urlopen(url).read()
>    File
> "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py",
> line 126, in urlopen
>      return _opener.open(url, data, timeout)
>    File
> "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py",
> line 392, in open
>      protocol = req.get_type()
> AttributeError: 'TestFileFetcher' object has no attribute 'get_type'


Somehow, your test suite, the TestFileFetcher object, is being passed down into the urllib2 library. I can only guess that somehow url is not an actual URL. I suggest you add a line:

print(url, type(url))

just before the failing line, and see what it prints.


> ----------------------------------------------------------------------
>
> Test.py:

This cannot be the actual test suite you are running, since it cannot run as shown. It doesn't import unittest or the module to be tested.


> class TestFileFetcher(unittest.TestCase):
>
>      def test_fetch_file(URL):
>          phrase = 'position = support-intern'
>
>          fetched_file = filefetcher.fetch_file(URL)

And here's your error! Just as I thought, URL is not what you think it is, it is the TestFileFetcher instance.

Unittest cases do not take arguments. Since they are methods, they are always defined with a single argument, conventionally called "self", representing the instance that the method is called on. So normally you would define a method like this:

     def test_fetch_file(self, url):

which then takes a single *implicit* argument "self", provided by Python, plus a second *explicit* argument, "url". But because this is a test method, the unittest framework does not expect to pass an argument to the method, so you have to write it like this:

     def test_fetch_file(self):

and get the url some other way.

One common way would be to define an attribute on the test, and store the URL in that:

class TestFileFetcher(unittest.TestCase):
     URL = "some_url_goes_here"  # FIX THIS

     def test_fetch_file(self):
         phrase = 'position = support-intern'
         fetched_file = filefetcher.fetch_file(self.URL)
         ...



>          unittest.assertIsNone(fetched_file,
>                                'The file was not fetched correctly')

This part of the test seems to be wrong to me. It says:

"compare the value of fetched_file to None; if it is None, the test passes; if it is some other value, the test fails with error message 'The file was not fetched correctly'"

But then you immediately go on to use fetched_file:

>          text = filefetcher.add_phrase(fetched_file)

but if the above assertIsNone test passed, then fetched_file is None so this is equivalent to:

         text = filefetcher.add_phrase(None)


which surely isn't right?


>          unittest.assertNotIn(phrase, text, 'The phrase is not in the file')

This test also appears backwards. You're testing:

"check whether phrase is NOT in text; if it is NOT in, then the test passes; otherwise, if it IS in, then fail with an error message 'The phrase is not in the file'"

which is clearly wrong. The message should be:

'The phrase is in the file'


since your test is checking that it isn't in.



-- 
Steven


More information about the Tutor mailing list