5

I am attempting to utilize the Presenter-First approach to a new project. I find myself with unittest below. Am I utilizing poor unit testing practices by including so many assertions in this test? If yes, is the issue with my approach to the test or to the implementation of presenter.setOverview? In otherwords, should the setOverview method call self.setSalesQty rather than self.view.setSalesQty? In this case, I would have a separate test for presenter.setSalesQty and the testSetOverview test would no longer need to worry about testing this.

def testSetOverview(self):
    # set up mock objects
    p = PropertyMock()
    type(self.mock_model).descriptions = p
    self.mock_model.getData.side_effect = [5, 10]
    self.mock_model.getDescription.side_effect = 'Description'

    # get required variables
    end = dt.date.today()
    start = dt.date(year=end.year, month=1, day=1)
    pn = 'abcd'

    # call presenter method
    self.presenter.setOverview(pn)

    # test to make sure proper calls were made
    model_getData_calls = [call(pn=pn, start=start, end=end,
                       data=self.mock_model.SHIPPED_QUANTITY),
                   call(pn=pn, start=start, end=end,
                        data=self.mock_model.PRICE_PAID)]

    self.mock_model.getData.assert_has_calls(model_getData_calls, any_order=True)
    assert self.mock_model.getDescription.called

    self.mock_view.setSalesQty.assert_called_with(val=5)
    self.mock_view.setSalesDols.assert_called_with(val=10)
    self.mock_view.setDescription.assert_called_with(val='Description')
wesanyer
  • 982
  • 1
  • 6
  • 27

1 Answers1

1

So generally when writing unit tests you would like to test one specific thing. Because when you write more code and the test fails it will be a lot easier for you to understand what in the unit test failed. It may be that with the assertions that you've made so far you are testing one behaviour or functionality of the code, then the assertions are fine.

To make an example, you have two functions below list_counter depends on word_count. So when testing list_counter you could make two assertions to make sure the two components in list_counter is correct. But it would probably be wiser to test word_count separately.

def word_count(word):
    return len(word)

def list_counter(listing=None):
    total = 0
    for l in listing:
        total += word_count(l)

    return (len(listing), total)

It's difficult to comment more specifically on your case since I don't have access to what the model looks like. self.mock_view appears out of nowhere too.

Jonathan
  • 8,453
  • 9
  • 51
  • 74
  • not putting more information about self.mock_view and self.mock_model was intentional - these are mock objects, and as such (in my understanding) should not be under test. The Presenter itself is under test, and it is dependent on these two objects, and utilizes them to do its work. – wesanyer Dec 18 '15 at 14:25
  • Yes, they shouldn't be tested, but seeing the objects that they represent may help give you advice about how you should write your test. – Jonathan Dec 18 '15 at 15:28
  • Fair enough. The approach I was taking , though, in keeping with "presenter first" was to, well, write the presenter unit tests and implementation first. Before I wrote anything for the model or the view. I subbed in the mocks as a placeholder, and after writing my presenter tests and implementation, I used the mocked method calls as a starting place for my model and view unit tests and implementation. Is this atypical? – wesanyer Dec 18 '15 at 15:53