Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reuse code for integration and unit tests?

I work with a distributed system that has unit and integration tests. I am trying to save time and maintenance efforts by reusing code between integration and unit tests. For this I implemented an interface and 2 classes: fake and real. Fake class returns some stubbed data, and real class makes a few calls to other distributed services.

Current structure of my projects

/BaseTest              
   interface IFoo
-------------------------------------
/UnitTest
   class FakeFoo : IFoo

   [TestFixture]
   class FooTest {...} //uses FakeFoo
-------------------------------------
/IntegrationTest
   class RealFoo : IFoo

   [TestFixture]
   class FooTest {...} //uses RealFoo

I want to somehow reuse code for both tests, so if I have a test

[Test]
public void GetBarIsNotNullTest()
{
    var foo = IoC.Current.Resolve<IFoo>();
    Bar actual = foo.GetBar();
    Assert.IsNotNull(actual);   
}

I want this test to run with both implementations: RealFoo and FakeFoo. So far I thought about copy-pasting tests between /UnitTest and /IntegrationTest projects, but this doesn't sound right.

System is written in C#, but I believe this question is language agnostic.

Anyone has better ideas? Am I doing this wrong?

like image 315
oleksii Avatar asked Jul 25 '12 13:07

oleksii


People also ask

Are integration tests the same as unit tests?

Unit Testing is a kind of white box testing, whereas Integration Testing is a kind of black-box testing. For Unit Testing, accessibility of code is required, as it tests the written code, while for Integration Testing, access to code is not required, since it tests the interactions and interfaces between modules.

What is the major problem during integration testing?

The most common problem I see with integration testing is that most attempts at integration testing do not recognize that people “using” the system have different expectations of the system, and will use the “integrations” differently depending on those expectations and their business needs.

Should I separate unit and integration tests?

Separating things Usually unit tests are fast and even if you run them by mistake, you won't feel uncomfortable. Integration, contract and acceptance tests can take several minutes if the project is huge. That's why it makes sense to separate integration and unit tests.

Why is integration testing is harder than unit testing?

Integration tests are harder to write. Unit tests can be run in any order, or even simultaneously. Integration tests usually required a strict order and can't be run simultaneously.


1 Answers

Even though others had good points in their answers, this is what I ended up doing

I created a base class for unit and integration tests

[TestFixture]
public class FooBase
{
    [Test]
    public void GetBarIsNotNullTest()
    {
        var foo = IoC.Current.Resolve<IFoo>();
        Bar actual = foo.GetBar();
        Assert.IsNotNull(actual);   
    }

    //many other tests  
}

And then two derived classes from the FooBase. These class will only have the SetUp and nothing else. i.e.:

[TestFixture]
public class UnitTestFoo : FooBase
{
    [SetUp]
    public void SetUp()
    {
        IoC.Current.Register<IFoo, FakeFoo>();        
    }

    //nothing else here
}

[TestFixture]
public class IntegrationTestFoo : FooBase
{
    [SetUp]
    public void SetUp()
    {
        IoC.Current.Register<IFoo, RealFoo>();        
    }

    //nothing else here
}

So if I now run my tests, I get the tests defined in the parent class FooBase run twice for unit tests class and integration tests class with their own real and fake objects. This works because of the inheritance of the test fixtures.

like image 173
oleksii Avatar answered Oct 06 '22 21:10

oleksii