What is the difference between integration and uni

2020-01-22 13:17发布

I know the so-called textbook definition of unit tests and integration tests. What I am curious about is when it is time to write unit tests... I will write them to cover as many sets of classes as possible.

For example, if I have a Word class, I will write some unit tests for the Word class. Then, I begin writing my Sentence class, and when it needs to interact with the Word class, I will often write my unit tests such that they test both Sentence and Word... at least in the places where they interact.

Have these tests essentially become integration tests because they now test the integration of these 2 classes, or is it just a unit test that spans 2 classes?

In general, because of this uncertain line, I will rarely actually write integration tests... or is my using the finished product to see if all the pieces work properly the actual integration tests, even though they are manual and rarely repeated beyond the scope of each individual feature?

Am I misunderstanding integration tests, or is there really just very little difference between integration and unit tests?

20条回答
The star\"
2楼-- · 2020-01-22 13:39

In addition, it's important to remember that both unit tests and integration tests can be automated and written using, for example, JUnit. In JUnit integration tests, one can use the org.junit.Assume class to test the availability of environment elements (e.g., database connection) or other conditions.

查看更多
啃猪蹄的小仙女
3楼-- · 2020-01-22 13:41

Have these tests essentially become integration tests because they now test the integration of these 2 classes? Or is it just a unit test that spans 2 classes?

I think Yes and Yes. Your unit test that spans 2 classes became an integration test.

You could avoid it by testing Sentence class with mock implementation - MockWord class, which is important when those parts of system are large enough to be implemented by different developers. In that case Word is unit tested alone, Sentence is unit tested with help of MockWord, and then Sentence is integration-tested with Word.

Exaple of real difference can be following 1) Array of 1,000,000 elements is easily unit tested and works fine. 2) BubbleSort is easily unit tested on mock array of 10 elements and also works fine 3) Integration testing shows that something is not so fine.

If these parts are developed by single person, most likely problem will be found while unit testing BubbleSoft just because developer already has real array and he does not need mock implementation.

查看更多
对你真心纯属浪费
4楼-- · 2020-01-22 13:42

I call unit tests those tests that white box test a class. Any dependencies that class requires is replaced with fake ones (mocks).

Integration tests are those tests where multiple classes and their interactions are tested at the same time. Only some dependencies in these cases are faked/mocked.

I wouldn't call Controller's integration tests unless one of their dependencies is a real one (i.e. not faked) (e.g. IFormsAuthentication).

Separating the two types of tests is useful for testing the system at different levels. Also, integration tests tend to be long lived, and unit tests are supposed to be quick. The execution speed distinction means they're executed differently. In our dev processes, unit tests are run at check-in (which is fine cos they're super quick), and integration tests are run once/twice per day. I try and run integration tests as often as possible, but usually hitting the database/writing to files/making rpc's/etc slows.

That raises another important point, unit tests should avoid hitting IO (e.g. disk, network, db). Otherwise they slow down alot. It takes a bit of effort to design these IO dependencies out - i can't admit I've been faithful to the "unit tests must be fast" rule, but if you are, the benefits on a much larger system become apparent very quickly.

查看更多
小情绪 Triste *
5楼-- · 2020-01-22 13:46

The nature of your tests

A unit test of module X is a test that expects (and checks for) problems only in module X.

An integration test of many modules is a test that expects problems that arise from the cooperation between the modules so that these problems would be difficult to find using unit tests alone.

Think of the nature of your tests in the following terms:

  • Risk reduction: That's what tests are for. Only a combination of unit tests and integration tests can give you full risk reduction, because on the one hand unit tests can inherently not test the proper interaction between modules and on the other hand integration tests can exercise the functionality of a non-trivial module only to a small degree.
  • Test writing effort: Integration tests can save effort because you may then not need to write stubs/fakes/mocks. But unit tests can save effort, too, when implementing (and maintaining!) those stubs/fakes/mocks happens to be easier than configuring the test setup without them.
  • Test execution delay: Integration tests involving heavyweight operations (such as access to external systems like DBs or remote servers) tend to be slow(er). This means unit tests can be executed far more frequently, which reduces debugging effort if anything fails, because you have a better idea what you have changed in the meantime. This becomes particularly important if you use test-driven development (TDD).
  • Debugging effort: If an integration test fails, but none of the unit tests does, this can be very inconvenient, because there is so much code involved that may contain the problem. This is not a big problem if you have previously changed only a few lines -- but as integration tests run slowly, you perhaps did not run them in such short intervals...

Remember that an integration test may still stub/fake/mock away some of its dependencies. This provides plenty of middle ground between unit tests and system tests (the most comprehensive integration tests, testing all of the system).

Pragmatic approach to using both

So a pragmatic approach would be: Flexibly rely on integration tests as much as you sensibly can and use unit tests where this would be too risky or inconvenient. This manner of thinking may be more useful than some dogmatic discrimination of unit tests and integration tests.

查看更多
【Aperson】
6楼-- · 2020-01-22 13:47

I think I would still call a couple of interacting classes a unit test provided that the unit tests for class1 are testing class1's features, and the unit tests for class2 are testing its features, and also that they are not hitting the database.

I call a test an integration test when it runs through most of my stack and even hits the database.

I really like this question, because TDD discussion sometimes feels a bit too purist to me, and it's good for me to see some concrete examples.

查看更多
Ridiculous、
7楼-- · 2020-01-22 13:48

I think when you start thinking about integration tests, you are speaking more of a cross between physical layers rather than logical layers.

For example, if your tests concern itself with generating content, it's a unit test: if your test concerns itself with just writing to disk, it's still a unit test, but once you test for both I/O AND the content of the file, then you have yourself an integration test. When you test the output of a function within a service, it's a unit-test, but once you make a service call and see if the function result is the same, then that's an integration test.

Technically you cannot unit test just-one-class anyway. What if your class is composed with several other classes? Does that automatically make it an integration test? I don't think so.

查看更多
登录 后发表回答