0

I am a bit confused on what the limits are for a unit tests and integration/functional tests? Are there any definite boundaries between these?

Let me start with a scenario ....

If I have a set of classes that perform a process. Each processes comprises have a few tasks.

ProcessA {
   var a = do TaskA;
   var c = do TaskC;
   var b = do TaskB;
}

ProcessB {
   var c = do TaskC;
   var d = do TaskD;
}

ProcessC {
   var a = do TaskA;
   var d = do TaskD;
}

If we take the above design, then I can write unit tests to test out each of the Tasks to make sure that they do what they are supposed to. I am cool with that.

My problem arises with the fact that I would like write unit test, or I think they would be unit tests, for all the Processes. I want to make sure that the tasks are in the proper order, and the business rules are correct within the process itself.

The definition of a unit test is that unit tests test out a bite size chunk of the code. What I am trying to test out is a larger, 'ProcessA', 'ProcessB', code. In those tests, I will still be decoupling from the datastore & services. Would that still be considered a unit test or integration/functional test?

UPDATE

Based on all the comments, I guess the proper question to ask is that if all the external dependencies are mocked in 'ProcessA', 'ProcessB', etc. classes, would a unit test for those classes be considered a unit test or a integration test?

And thanks for being patient with me ....

Skadoosh
  • 2,476
  • 7
  • 39
  • 51
  • possible duplicate of [Unit tests vs Functional tests](http://stackoverflow.com/questions/2741832/unit-tests-vs-functional-tests) – Peter Ritchie Mar 03 '14 at 16:19

3 Answers3

2

As soon as you said I want to make sure that the tasks are in the proper order, and the business rules are correct within the process itself. you stopped talking about unit tests and began talking about integration tests.

Even though you are decoupling from the datastore and services you are testing busines rules. If your organization is anything like mine, business rules can (and often do) change. It is this volatile nature that makes it an integration test.

The base rule I've used is "unit tests are modular, independent pieces of code not dependant upon external data sources. whereas integration tests are tests that require the use of external data sources, either mocked up or from production."

The art of Unit Testing, second edition lists Integration tests with the following definition:

I consider integration tests as any tests that aren’t fast and consistent and that use one or more real dependencies of the units under test. For example, if the test uses the real system time, the real filesystem, or a real database, it has stepped into the realm of integration testing.

and unit tests with the following (emphasis mine):

A unit test is an automated piece of code that invokes the unit of work being tested, and then checks some assumptions about a single end result of that unit. A unit test is almost always written using a unit testing framework. It can be written easily and runs quickly. It’s trustworthy, readable, and maintainable. It’s consistent in its results as long as production code hasn't changed.

Based upon the same book as above. A unit test :

  • Is an automated piece of code that invokes a different method and then checks some assumptions on the logical behaviour of that method or class.
    • This is true if you can reduce ProcessA/B/C into small chunks that can be tested independently of one another.
  • can be executed repeatedly by anyone on the development team.
    • If someone from your team requires values or a cheat sheet to refer to determine if the test passes or not, it is not a unit test.

Now based upon your edit it depends. Integration tests and unit tests can overlap and many other developers may have different ideas on to how they would label the tests.

The answer to your question is to determine the best practice for you and your development team. If the consensus it's a unit test, then consider it as such.

Unit and integration tests should help the process, not hinder it. Please don't let semantics get in the way of that.

Robert H
  • 10,659
  • 17
  • 63
  • 102
  • I understand that once the code goes out QA env, then the QA team can do their 'integration' testing & then up to the proj owners for 'func' testing. I am still stuck on the fact that I can still write the same integration/functional test as unit test and have them be automated. Is that the right thinking? – Skadoosh Mar 03 '14 at 16:47
  • I'm hoping I'm not misinterpeting the question, but based upon your comment the question becomes less of categorizing your tests and more one of process. For instance, in a small shop you may not have a dedicated QA team and each developer may be responsible for writing unit and integration tests, whereas a larger shop will have a set procedure for unit and integration tests. The process between these two shops is different, even though the steps are the same. – Robert H Mar 03 '14 at 16:53
  • @G0tPwned Or, reinterpreting the comment, the most fundamental difference between the two is the source of your data. Unit tests exist as a closed entity, integration tests are more fluid and contain variable data. Both types of tests can be automated and can have a similar workflow. Clear as mud right? – Robert H Mar 03 '14 at 16:54
  • I didn't mention this in my question, but we are a small shop so part of the QA team is the developer that's writing the code, which is why I'd like to automate as much surface area as I can. You're right! Its quite muddy. – Skadoosh Mar 03 '14 at 17:07
  • After reading your update, it makes sense why it would testing different 'Process' classes in my scenario can be an integration test. Those classes, though independent from each other (i.e. ProcessA has no dependency ProcessB or ProcessC), can have different output based on the data fed into the class. Therefore, that said, someone else looking at it WILL need a cheatsheet to figure out what is going on in the tests. – Skadoosh Mar 03 '14 at 18:23
1

Setting aside tools etc... Unit test is simply testing a specific piece of code and would typically be performed by the programmer.

Functional and Integration are typically performed by QA team:

Functional Testing is testing if the code does what it was intended to do.

Integration Testing is about testing code and measuring how it interacts with other modules/parts of the system.

T McKeown
  • 12,312
  • 1
  • 21
  • 30
  • So based on the definition, if the code under testing is still within the same library, and a unit test is written against it, it would still be considered a unit test? For example, if a unit test is written for 'ProcessA', then its still a unit test as long as all external dependencies are mocked? – Skadoosh Mar 03 '14 at 17:16
  • Unit testing shouldn't be an onerous task. What matters is that the code is tested, that the new code is tested in as many paths to account for 100% code coverage. "external dependencies being mocked", as always it depends... if the mocking has proven to be reliable then fine. There has to be a reasonable expectation as to what unit testing can accomplish. If your test is the ONLY testing being performed then it sounds like you are wearing a lot of hats. – T McKeown Mar 03 '14 at 17:22
1

I would say that a unit test is a test that tests one class only (a unit), whereas integration tests test the integration of multiple classes/assemblies and/or even external data sources. Functional tests should explicitly test the functionality exposed to the users (which may be internal users, outside of the dev team etc.)

EDIT: The only way to implement unit tests for composite classes is to use dependency injection. This means that you should define an interface (possibly more than one), e.g.:

interface ITask
{
  Perform();
}

and inject it into your Process classes:

class ProcessC
{
  ITask taskA;
  ITask taskD;
  ProcessA(ITask taskA, ITask taskD)
  {
    this.taskA = taskA;
    this.taskD = taskD;
  }

  void Run() //change to your real methods
  {
    taskA.Perform(); //capture results
    taskD.Perform();
  }
}

Now you can mock the injected interface ITask (using a mocking framework), so that you can isolate the behaviour of a process from the behaviour of the tasks.

Community
  • 1
  • 1
Grzenio
  • 33,623
  • 43
  • 148
  • 226
  • That makes sense on who does what. So then, should I disguise a integration test, remove all external dependencies, and write as a unit test? Would that not be considered a unit test at that point? – Skadoosh Mar 03 '14 at 16:50
  • @G0tPwned, some software projects don't have external dependencies at all, i.e. some specialized libraries. But still if you are testing the whole thing I argue that this is an integration level testing. – Grzenio Mar 03 '14 at 17:06
  • That is my confusion. I feel like as a developer all I can do is write the code for the 'ProcessA' & 'ProcessB' classes and hope that the code in there is correct. I should not write unit tests that as essentially integration tests. So, then how can I make sure that the rules at 'ProcessA' class level is correct? – Skadoosh Mar 03 '14 at 17:12
  • 1
    @G0tPwned, please see the edit to the answer. This kind of design with dependency injection is a key for unit testing. You can't do unit testing without it (as you already noticed anyway). – Grzenio Mar 03 '14 at 17:47
  • 1
    That is exactly what I am doing. All the 'Tasks' will derive from a base abstract class and everything will use the base type. – Skadoosh Mar 03 '14 at 19:09