Bill
Bill

Reputation: 33

How do I get python unittest to test that a function returns a csv.reader object?

I'm using python 2.7 and delving into TDD. I'm trying to test a simple function that uses the csv module and returns a csv.reader object. I want to test that the correct type of object is being returned with the assertIsInstance test however I'm having trouble figuring out how to make this work.

#!/usr/bin/python
import os, csv

def importCSV(fileName):
  '''importCSV brings in the CSV transaction file to be analyzed'''
  try:
    if not(os.path.exists("data")):
      os.makedirs("data") 
  except(IOError):
    return "Couldn't create data directory!"
  try:
    fileFullName = os.path.join("data", fileName)
    return csv.reader(file(fileFullName))
  except(IOError):
    return "File not found!"

The test currently looks like this....

#!/usr/bin/python
from finaImport import finaImport 
import unittest, os, csv

class testImport(unittest.TestCase):
  '''Tests for importing a CSV file'''

  def testImportCSV(self):
    ''' Test a good file and make sure importCSV returns a csv reader object     '''
    readerObject = finaImport.importCSV("toe")
    self.assertTrue(str(type(readerObject))), "_csv.reader")

I really don't think wrapping "toe" in a str and type function is correct. When I try something like...

self.assertIsInstance(finaImport.importCSV("toe"), csv.reader)

It returns an error like...

TypeError:  isinstance() arg2 must be a class, type, or tuple of classes and types

Help???

Upvotes: 3

Views: 2951

Answers (1)

rkersh
rkersh

Reputation: 4465

self.assertTrue(str(type(readerObject)), "_csv.reader")

I don't think that your first test (above) is so bad (I fixed a small typo there; you had an extra closing parenthesis). It checks that the type name is exactly "_csv.reader". On the other hand, the underscore in "_csv" tells you that this object is internal to the csv module. In general, you shouldn't be concerned about that.

Your attempt at the assertIsInstance test is flawed in that csv.reader is a function object. If you try it in the REPL, you see:

 >>> import csv
 >>> csv.reader
 <built-in function reader>

Often, we care less about the type of an object and more about whether it implements a certain interface. In this case, the help for csv.reader says:

>>> help(csv.reader)

... The returned object is an iterator. ...

So, you could do the following test (instead or in addition to your other one):

self.assertIsInstance(readerObject, collections.Iterator)

You'll need a import collections for that, of course. And, you might want to test that the iterator returns lists of strings, or something like this. That would allow you to use something else under the hood later and the test would still pass.

Upvotes: 3

Related Questions