4

Suppose there is a function get-data which returns a map of information about the id of the user passed in. Now this function uses 3 functions source-a, source-b and source-c to get three different kinds of maps. Now we combine all these maps into one map and return from get-data.

When I test get-data, should I test for existence of data for keys? Does it makes sense for this function to fail unit tests if one of source-a, source-b and source-c fail? If thats function job is to combine data, and it's doing it, it should be enough, right?

Karol Selak
  • 221
  • 2
  • 8
Amogh Talpallikar
  • 1,997
  • 2
  • 26
  • 39
  • 1
    So basically my mistake was to write code first and then write test cases. If I would have written unit test befor the function. whenever I would be writing a bigger function I wouldn't be asking such questions. – Amogh Talpallikar Jan 24 '14 at 13:08
  • use mockito to give mock data from other data sources – tgkprog Jan 24 '14 at 13:34
  • 4
    It wasn't a mistake to write code first. However, if you start writing your code with testing in mind, you will make a different set of decisions. Often, I can't figure out how to test something until after I've written the code; being mindful of the testing requirements helps me to formulate testing strategies and, eventually, tests. – BobDalgleish Jan 24 '14 at 13:36
  • @BobDalgleish is correct. Additionally, testing forces you to think about the code which calls your function, and every way it could be done. To at least consider that is beneficial even if you write the code first. – Magus Apr 17 '14 at 17:28
  • see also: [Shouldn't unit tests use my own methods?](https://softwareengineering.stackexchange.com/q/330304/31260) – gnat Aug 22 '18 at 10:44

2 Answers2

16

Suppose there is a function get-data which returns a map of information about the id of the user passed in.

Great. You should test that then. For a given ID, do you get the right data back?

now this function uses 3 functions source-a, source-b and source-c to get three different kinds of maps.

Which is an implementation detail you should ignore in the test. All you're testing is that your unit of work (this method) does what it's supposed to (take an ID and return XYZ data for that ID). How the method does that isn't particularly relevant - after all, a key benefit of that unit test is that you can refactor the implementation of the method and the test will verify you did that correctly.

That said, you're likely going to need to mock the data sources, so at some point the test will likely need to know how the code works to do that. You'll need to balance three competing goals here: making the test isolated (by mocking the data), making the test focused on requirements, and pragmatism.

In the end, it's the code that matters. Tests exist to support the actual code, spending a lot of time and trouble mucking about with polishing tests isn't nearly as useful as making tests.

Telastyn
  • 108,850
  • 29
  • 239
  • 365
  • 3
    +1, because whether or not you have refactored a method to use three others or is a single giant method is irrelevant to the unit test itself, which is only concerned with arguments, returns, and exceptions. – Magus Apr 17 '14 at 17:24
4

In unit testing you must only test the functionality of one class, if your source-a, source-b and source-c methods call other classes, you should mock them (they should be unit tested in their own classes).

In integration testing, you test the behavior of several classes interacting between them, that means that your get-data function must test that the data that is retrieving is correct (source-a, source-b and source-c are correct, and the data is being joining properly).

Unit testing are easier and more focused, and should be created by developers. Integration tests usually get obsolete relatively fast (if any internal component has been modified), so they are harder to mantain. Should be created by a QA profile.

greuze
  • 365
  • 3
  • 7
  • 1
    "*In unit testing you must only test the functionality of one class*". Absolute nonsense. The single biggest impediment to devs writing good automated tests is this crap about unit tests only being allowed to test a single class/method or whatever. Whoever dreamt up this claim made a mistake comparable to null mistake. – David Arno Sep 15 '21 at 08:26