简体   繁体   中英

How to use setUp and tearDown in python unittest for this class

I am having an hard time learning test driven development.

I am writing a class which would take either a filename or file description and size an input and return the size-chunk of data from the file.

While starting out with the tests first all I could come up was to test if the arguments passed were not none and to check if arguments are valid fileobjects.

All i could muster up was below code, am I use the setUp and tearDown methods as I should or it is completely wrong? I am creating a temporary file and instance of class defined to read in the setUp() and am I supposed to remove the object someway in tearDown()

Below is the code

class Test_FileChunk(unittest.TestCase):
    """
    """
    def setUp(self):
        self.fhandle, self.fname = mkstemp()
        self.fc_obj = FileChunk(filename=self.fname)

    def tearDown(self):
        try:
            os.remove(self.fname)
        except OSError as oserr:
            print(oserr)

    def test_instance_variables(self):
        self.assertIsNotNone(self.fc_obj.filename)
        self.assertIsNone(self.fc_obj.filehandle)
        self.assertEqual(self.fc_obj.chunk_size, 8192)

    def test_check_if_instance_variables_are_valid_file_objects(self):
        handle = open(self.fc_obj.filename
        self.assertEqual(
            hasattr
                (handle, "r"), 'seek'), True,
                    msg="Is not a valid file object")
        handle.close()

I went through multiple TDD questions on stackoverflow and suggested tutorials but still it seems following a TDD tutorial is very interesting but actually doing TDD is very difficult. I can actually think of what I want to do in ReadChunk class but just cannot get my head around actually find the tests first and then writing the code. I was able to think to check whether the passed values are valid file object through TDD which wouldn't have occurred if I were coding without TDD, but I am not sure if I am using the unittest correctly. Cannot get the big picture. Could anyone please suggest how to go about this and whether the above code snipped is correct.

About your code

setUp and tearDown are optional methods to help you setup and well.. tear down the testing environment. They are commonly used to, for example, create and remove temporary folders to store output or setup a (mocked) database-connection during tests.

They should not be used test any functionality. So invoking the FileChunk-object should not happen in the setUp. In each test you want to test a certain case of the methods in FileChunk, ideally independently of each other. Therefore, you should invoke a new instance of FileChunk in every new case. So in this case in both test_instance_variables and test_check_if_instance_variables_are_valid_file_objects .

About TDD

To use pure TDD is kind of a change in mindset. There aren't any simple tutorials to you help on that; as entire books have been written about how to use TDD.

However, I can provide you with some guidelines.

  1. Identify the public interface of your class. Which methods should external classes be able to use? What should be the input and what should be the output of these methods?
  2. Identify the different cases of the method. When should it output true/false? When should it throw an exception?
  3. Write the test-cases based on the cases you have found in 2.
  4. Write the most basic dummy class for FileChunk, which essentially does nothing, but does have all functionality the unit-tests are testing. This way all tests can be run, although they will probably fail.
  5. Start improving the FileChunk-class until all tests pass.

An important aspect of TDD, in my opinion, is that you can't just start making tests. You should really know what the class should look like.

Unlike TemporaryFile(), the user of mkstemp() is responsible for deleting the temporary file when done with it. - Python Documentation

so removing the file in tearDown is the correct solution.

I personally would make some test functions like

def test_filename(self):
    self.assertEqual(self.fc_obj.filename, self.fname)
    self.assertIsTrue(os.path.isfile(self.fc_obj.filename))


def test_handle(self):
    self.assertIsNone(self.fc_obj.filehandle)

def open_file(self):
    # if you implemented an "open" method
    # you can use this method every time you test the opened file
    result = self.fc_obj.open()
    self.assertIsTrue(result, "File open failed")
    self.assertIsNotNone(self.fc_obj.filehandle)

# if you plan to implement a read and a write method you can add the following test
def test_read_write_file(self):
    self.open_file()
    random_data = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N))
    self.fc_obj.write(random_data)
    self.assertEqual(self.fc_obj.read(), random_data)

and so on and define a test for everything you plan to implement, implement it and run the test. Your class looks good until now but as you might have seen you should make the tests as concrete as you can for example use

self.assertEqual(self.fc_obj.filename, self.fname)

instead of

self.assertIsNotNone(self.fc_obj.filename)

If you want to a lot of test with your opened FileChunk object you could also add a second unittest.TestCase .

class TestOpenFileChunk(unittest.TestCase);
    def setUp(self):
        self.fhandle, self.fname = mkstemp()
        self.fc_obj = FileChunk(filename=self.fname)
        self.fc_obj.open()

    def tearDown(self):
        # if you have this method
        self.fc_object.close()
        # and then
        try:
            os.remove(self.fname)
        except OSError as why:
            print(why)

    def test_read_write(self):
        #...

If you want to create the FileChunk object only once you can also use the setUpClass and tearDownClass methods.

class TestOpenFileChunk(unittest.TestCase);
    @classmethod
    def setUpClass(cls):
        cls.fhandle, cls.fname = mkstemp()
        cls.fc_obj = FileChunk(filename=self.fname)
        cls.fc_obj.open()

    @classmethod
    def tearDownClass(cls):
        # if you have this method
        cls.fc_obj.close()
        # and then
        try:
            os.remove(cls.fname)
        except OSError as why:
            print(why)

and use the self.fc_obj like always in the test methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM