Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do you put unit tests in same project or another project?

People also ask

Should unit tests depend on each other?

Tests should never depend on each other. If your tests have to be run in a specific order, then you need to change your tests. Instead, you should make proper use of the Setup and TearDown features of your unit-testing framework to ensure each test is ready to run individually.


Separate project, but in the same solution. (I've worked on products with separate solutions for test and production code - it's horrible. You're always switching between the two.)

The reasons for separate projects are as stated by others. Note that if you're using data-driven tests, you might end up with quite a significant amount of bloat if you include the tests in the production assembly.

If you need access to the internal members of the production code, use InternalsVisibleTo.


In my opinion, unit tests should be placed in a separate assembly from production code. Here are just a few cons of placing unit tests in the same assembly or assemblies as production code are:

  1. Unit tests get shipped with production code. The only thing shipped with product code is production code.
  2. Assemblies will be unnecessarily bloated by unit tests.
  3. Unit tests can affect build processes like automated or continuous build.

I don't really know of any pros. Having an extra project (or 10) isn't a con.

Edit: More Info On Build and Shipping

I would further recommend that any automated build process place production and unit tests into different locations. Ideally, the unit test build process only runs if the production code builds, and copies the product files into the unit tests directory. Doing it this way results in the actual bits being separated for shipping, etc. Additionally, it is fairly trivial to run automated unit testing at this point on all tests in a particular directory.

To summarize, here is the general idea for a daily build and testing and shipping of bits and other files:

  1. Production build runs, placing production files into a specific "production" directory.
    1. Build production projects only.
    2. Copy compiled bits and other files into a "production" directory.
    3. Copy bits and other files into a release candidate directory, aka a Christmas release directory would be "Release20081225".
  2. If production build succeeds, unit test build runs.
    1. Copy production code to "tests" directory.
    2. Build unit tests to "tests" directory.
    3. Run unit tests.
  3. Send build notifications and unit tests results to developers.
  4. When a release candidate (like Release20081225) is accepted, ship these bits.

I do not understand the frequent objection to deploying tests with production code. I led a team at a small microcap (grew from 14 to 130 people). We had a half-dozen or so Java apps and we found it EXTREMELY valueable to deploy tests into the field to execute them on a specific machine that was exhibiting unusual behavior. Random problems occur in the field and being able to throw a few thousand unit tests at the mystery with zero cost was invaluable and often diagnosed problems in minutes...including installation problems, flaky RAM problems, machine-specific problems, flaky network problems, etc, etc. I think it is incredibly valuable to put tests into the field. Also, random problems pop up at random times and it is nice to have the unit tests sitting there already waiting to be executed at a moments notice. Hard-drive space is cheap. Just like we try to keep data and functions together (OO design), I think there is something fundamentally valuable in keeping code and tests together (function + tests that validate the functions).

I would like to put my tests in the same project in C#/.NET/Visual Studio 2008, but I still haven't investigated this enought to achieve it.

One big benefit of keeping Foo.cs in the same project as FooTest.cs is that developers are constantly reminded when a class is missing a sibling test! This encourages better test-driven coding practices...holes are more apparent.


After spending some time in TypeScript projects, where tests are often placed in a file alongside the code they are testing, I grew to prefer this approach over keeping them separate:

  • It is quicker to navigate to the test file.
  • It is easier to remember to rename the tests when you rename the class being tested.
  • It is easier to remember to move the tests when you move the class being tested.
  • It is immediately obvious if a class is missing tests.
  • You don't need to manage two duplicate file structures, one for tests and one for code.

So when I started a new .NET Core project recently I wanted to see if it was possible to mimic this structure in a C# project without shipping the tests or test assemblies with the final release.

Putting the following lines in the project file appears to be working well so far:

  <ItemGroup Condition="'$(Configuration)' == 'Release'">
    <Compile Remove="**\*.Tests.cs" />
  </ItemGroup>
  <ItemGroup Condition="'$(Configuration)' != 'Release'">
    <PackageReference Include="nunit" Version="3.11.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="3.12.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
  </ItemGroup>

The above ensures that in the Release configuration all the files named *.Tests.cs are excluded from compilation, and also that the required unit testing package references are removed.

If you still want to be able to unit test the classes in their release configuration you can just create a new configuration derived from Release called something like ReleaseContainingTests.


Update: After using this technique for a while I've also found it's helpful to customize your icons in VS Code to make the tests (and other things) stand out a bit more in the explorer pane:

VS Code Screenshot

To do this, use the Material Icon Theme extension and add something like the following to your VS Code preferences JSON:

"material-icon-theme.files.associations": {
  "*.Tests.cs": "test-jsx",
  "*.Mocks.cs": "merlin",
  "*.Interface.cs": "Raml",
}

Update 2:

If you get the error Program has more than one entry point defined then you can follow the instructions here, which is basically to add <GenerateProgramFile>false</GenerateProgramFile> inside a <PropertyGroup> element in your project's .csproj file, and this will stop the testing framework from adding its own entry point.


Put Unit tests in the same project as the code to achieve better encapsulation.

You can easily test internal methods, which means you wont make methods public that should have been internal.

Also it's really nice to have the unit tests close to the code you're writing. When you write a method you can easily find the corresponding unit tests because it's in the same project. When you build a assembly that includes unitTests, any errors in the unitTest will give you an compilereerror, so you must keep your unittest up-to-date, just to build. Having unittest in a seperate project, might cause some developers to forget building the unittest-project, and missing the broken tests for a while.

And you can remove the unit tests from the production code, by using compilation tags (IF #Debug).

Automatic Integration Tests (made i NUnit) should be in a seperate project since they don't belong to any single project.


My unit tests always go in a separate project. In fact, for every project I have in my solution, there is a separate test project that goes along with it. Testing code is not application code and should not be intermingled with it. One advantage to keeping them in separate projects -- at least using TestDriven.Net -- is that I can right-click on a test project and run all the tests in that project, testing an entire library of application code with one click.


If NUnit framework is used, there is an additional reason to put the tests in the same project. Consider the following example of the production code mixed with unit tests:

public static class Ext
{
     [TestCase(1.1, Result = 1)]
     [TestCase(0.9, Result = 1)]
     public static int ToRoundedInt(this double d)
     {
         return (int) Math.Round(d);
     }
}

The unit tests here serve as documentation and specification to the code being tested. I do not know how to achieve this effect of self-documenting, with the tests located in a separate project. The user of the function would have to search for the tests to see those test cases, which is unlikely.

Update: I know that such usage of TestCase attribute was not that the developers of NUnit intented, but why not?