Skip to content

Unit Test Patterns

Prasad Talasila edited this page Feb 12, 2018 · 10 revisions

Unit Test Patterns

Side Effects

  • Avoid defining fakes/side_effects wherever possible and rather set the side_effect to iterable if we only need to ensure that correct returns are being assigned to mocked functions.
 mock_util.rec_list_splice.side_effect = util.load_from_disk(current_directory+ "/data/message_number_graph/rec_list_splice")

The /data/message_number_graph/rec_list_splice file contains a list. Once assigned as side_effect to mock_util.rec_list_splice() function, the mock library iterates over the list and returns the next item from the list every time the mocked function is called. Another way would be to define our own side_effects.

def explicit_side_effect(args):  
  return "some_value"

Although defining our own side_effects give us much more command over fakes but for our requirements, the first method is elegant and should be followed.

  • Explicitly add return statements to function if they need to be mocked.
def rec_list_splice(rec_list):
    rec_list[1] = rec_list[1][rec_list[1].find(">") + 1:len(rec_list[1])][1:]
    return rec_list

In rec_list_splice() function a explicit return is added, even though not required in the code, it helps while writing tests and is coherent with out way of using side_effects.

Whenever rec_list_splice() function is used, we need to take assign the returned value to an appropriate variable.

rec_list = util.rec_list_splice(rec_list)

With the use of the coding conventions put down by the previous two code examples, we are restricting the the mode of arguments to "pass by value", there by avoiding "pass by reference" which becomes difficult to test.

Mocking print statements

  • Use StringIO to redirect print statements to a python object.
        capturedOutput = StringIO.StringIO()
        sys.stdout = capturedOutput
        network.filter_edge_list(current_directory +'/data/filter_edge_list_input.txt', 10000, 100)
        sys.stdout = sys.__stdout__
        output = capturedOutput.getvalue()
        f = open(current_directory +'/data/filter_edge_list_out.txt','r')
        expected_output = f.read()
        f.close()
        capturedOutput.close()
        
        self.assertEqual(output, expected_output)
  • Remember to reset stdout to default sys.__stdout__
  • Remeber to close StringIO stream capturedOutput.close()
  • The stdout redirection is useful in muting unwanted print outputs while testing.
  • Use the captured output to compare with the expected results.
  • Avoid creating a new file and performing filecmp.

Clone this wiki locally