1

I am writing production code that parses a large file, which itself contains many different cases. To unittest the production code, I want to write a test case for each case. My question case is what a good way is to set up the testing directory and the testing code.

The current directory structure is:

root/
    src/
        parser.py
    test/
        test_parser.py
        raw/
            case_1.csv
            case_2.csv
            ...

The testing code looks like this:

from parser import parse
import unittest import TestCase


class Test_Parser(TestCase):

   def setUp(self):
       raw_dir = 'raw'

   def test_case_1(self):
       filename = self.raw_dir + '/case_1.csv'
       actual = parse(filename)
       # assert actual == expected

   def test_case_2(self):
       filename = self.raw_dir + '/case_2.csv'
       actual = parser(filename)
       # assert actual == expected

   ...

Is there a more Pythonic way to factor the directory self.raw_dir out, so that the test case is cleaner and one only has to write filename = 'case_1.csv'?

1
  • 1
    To start with, you should use os.path.join Commented Dec 16, 2014 at 0:08

1 Answer 1

1

If you want to avoid writing the whole path in your test methods, which is understandable, you could isolate this in a separate method which doesn't begin with _test and therefore won't be called when executing the tests:

import os
import parser
import unittest

class TestParser(unittest.TestCase):

    def setUp(self):
        self.raw_dir = "raw"

    def get_path(self, filename):
        path = os.path.join(self.raw_dir, filename)
        return path

    def file_parse(self, filename):
        # every method of this class being supposed to call
        # the parser, it makes sense to isolate these calls
        # into a specific method to avoid repetition
        # - won't be the same is the class is more general-purpose
        path = self.get_path(filename)
        actual = parser.parse(path)
        return actual

    def test_case_1(self):
        actual = self.file_parse(filename='case_1.csv')
        # assert actual == expected

    def test_case_2(self):
        actual = self.file_parse(filename='case_2.csv')
        # assert actual == expected

The main idea here is separation of concerns. One specific method to take care of the "putting dirs and filenames into a correct path" labour, another one to do the parsing and the test methods to do the actual tests (and only that).

Note that as suggested, you should use os.path.join (documentation) instead of hardcoding the slashes /.

Also, according to PEP8, class names should be CamelCase, not under_score or A_Mix_Of_Both.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for the tips and tricks. For documentation purposes, is it a good idea to move the call to the production code outside of the test cases and "hide" them in its own function?
ok I misunderstood the question in your comment :) - in that case, it doesn't matter if you call your production code in a separate method. Because you are testing the result. The assert actual == expected is what you're testing, and you're calling your parser several times for that. Your class being a TestParser, it makes sense to isolate the calls to the parser. This won't be true if it's a more general-purpose testing class. Hope I make myself clear :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.