0

I've been working on some code to practice unit testing. The original is supposed to get all file names in a directory, and list the number of files with the same extension. When I run the same function using unittest, the test appends a None at the end, breaking the test.

#!/usr/local/bin/python3

import os
from glob import glob
from collections import Counter

directory = os.getcwd()
filetype = "*.*"

def lookUp(directory, filetype):
    """Returns filename in the current directory"""
    files = [os.path.basename(i) for i in
            glob(os.path.join(directory,filetype))]
    countExt = Counter([os.path.splitext(i)[1] for i in files])
    for i in countExt:
        print("There are %d file(s) with the %s extension" %
        (countExt[i], i))

returns this output:

There are 3 file(s) with the .html extension
There are 1 file(s) with the .txt extension
There are 2 file(s) with the .py extension
There are 3 file(s) with the .doc extension

and my unittest code:

#!/usr/local/bin/python3

import unittest
import FileHandling
import os
import tempfile
from glob import glob



class TestFileHandling(unittest.TestCase): #Defines TestHandling class

    def setUp(self): # define seUp function
        self.testdir = os.getcwd()
        #self.testdir = tempfile.mkdtemp("testdir") # creates a test directory
        os.chdir(self.testdir) # changes to test directory
        self.file_names = ["file1.txt", "file1.doc", "file2.doc", "file3.doc", "file1.html", "file2.html", "file3.html"] # name seven filenames
        for fn in self.file_names: # creates files
            joinedfile = os.path.join(self.testdir, fn) #joins the filename with the temp directory name
            f = open(joinedfile, "w") # create the file
            f.close() # close the file from writing



    def test_lookUp_text(self): # test function for lookUp
        print(FileHandling.lookUp(self.testdir, "*.*"))
        #print(os.getcwd())
        #self.assertEqual(files, expected,)



def tearDown(self):
    for fn in self.file_names:
        os.remove(joinedfile)

if __name__ == "__main__":
    unittest.main()

returns this output:

There are 2 file(s) with the .py extension
There are 3 file(s) with the .doc extension
There are 1 file(s) with the .txt extension
There are 3 file(s) with the .html extension
None
.
----------------------------------------------------------------------
Ran 1 test in 0.016s

OK

Why is there an additional None output at the end of the unittest output?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
citizenzer0
  • 349
  • 1
  • 2
  • 6

1 Answers1

0

Your function doesn't use a return statement, so Python returns None (the default). You are printing that value. Note that your test isn't broken by it, your test is actually not testing anything, only running the code.

Simply remove your print() call:

def test_lookUp_text(self):
    FileHandling.lookUp(self.testdir, "*.*")

You should consider changing your function to return the a report to print rather than print directly, then your unit test more easily can make assertions about the right output having been produced.

You should also consider learning how the unittest.mock library could help you here; you could mock out the os.listdir() call so you don't actually have to create test files, and instead leave it to your mocked os.listdir() call to return a pre-determined list of strings.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • HI, thanks for the response. I should have been clearer in my original post, the print was just there for my own diagnostics purposes. When I remove the print i get "AssertionError: None != 'There are 1 file(s) with the .txt extension'", which I assumed was from the trailing NONE output. Thanks – citizenzer0 Aug 09 '15 at 19:33
  • @user3830278: again, your function doesn't return anything. It *prints*, which means the output is written to `sys.stdout`. You could try and capture that but it'd be easier if your function instead returned a string or list. – Martijn Pieters Aug 09 '15 at 20:48
  • @user3830278: see [How to assert output with nosetest/unittest in python?](http://stackoverflow.com/q/4219717) for an example that captures stdout, but since you are trying out unittesting it would be far easier for you to build a string and return that to test. – Martijn Pieters Aug 09 '15 at 21:17
  • Hey Martijn, thanks so much for your help, I finally realized what you meant. I used a dict object for the results, and printed the dict object in the FileHandling program while returning the dict object to the testing and it worked like a cham. Thanks! – citizenzer0 Aug 12 '15 at 17:57