Programming

동일한 프로젝트 또는 다른 프로젝트에 단위 테스트를합니까?

procodes 2020. 6. 28. 20:06
반응형

동일한 프로젝트 또는 다른 프로젝트에 단위 테스트를합니까?


편의를 위해 동일한 프로젝트에 단위 테스트를 두거나 별도의 어셈블리에 배치합니까?

우리가하는 것처럼 별도의 어셈블리에 배치하면 솔루션에 많은 추가 프로젝트가 생깁니다. 코딩하는 동안 단위 테스트에 유용하지만 이러한 추가 어셈블리없이 응용 프로그램을 어떻게 릴리스합니까?


제 생각에 단위 테스트는 생산 코드와 별도의 어셈블리에 배치해야합니다. 다음은 생산 코드와 동일한 어셈블리에 단위 테스트를 배치하는 몇 가지 단점입니다.

  1. 단위 테스트는 생산 코드와 함께 제공됩니다. 제품 코드와 함께 배송되는 유일한 제품은 생산 코드입니다.
  2. 단위 테스트로 인해 어셈블리가 불필요하게 부풀어 오릅니다.
  3. 단위 테스트는 자동화 또는 연속 빌드와 같은 빌드 프로세스에 영향을 줄 수 있습니다.

나는 어떤 프로도 모른다. 추가 프로젝트 (또는 10)를 갖는 것은 사기가 아닙니다.

편집 : 빌드 및 배송에 대한 추가 정보

또한 자동화 된 빌드 프로세스는 생산 및 단위 테스트를 다른 위치에 배치하는 것이 좋습니다. 이상적으로, 단위 테스트 빌드 프로세스는 프로덕션 코드가 빌드 된 경우에만 실행되고 제품 파일을 단위 테스트 디렉토리에 복사합니다. 이렇게하면 배송 등을 위해 실제 비트가 분리됩니다. 또한 특정 디렉토리의 모든 테스트에서이 시점에서 자동화 된 단위 테스트를 실행하는 것은 매우 사소한 일입니다.

요약하자면 다음은 비트 및 기타 파일의 일일 빌드 및 테스트 및 배송에 대한 일반적인 아이디어입니다.

  1. 프로덕션 파일이 특정 "프로덕션"디렉토리에 배치되어 프로덕션 빌드가 실행됩니다.
    1. 프로덕션 프로젝트 만 빌드하십시오.
    2. 컴파일 된 비트 및 기타 파일을 "production"디렉토리에 복사하십시오.
    3. 비트 및 기타 파일을 릴리스 후보 디렉토리 (예 : 크리스마스 릴리스 디렉토리는 "Release20081225")로 복사하십시오.
  2. 생산 빌드가 성공하면 단위 테스트 빌드가 실행됩니다.
    1. 프로덕션 코드를 "tests"디렉토리에 복사하십시오.
    2. "tests"디렉토리에 유닛 테스트를 빌드하십시오.
    3. 단위 테스트를 실행하십시오.
  3. 개발자에게 빌드 알림 및 단위 테스트 결과를 보냅니다.
  4. 릴리스 후보 (예 : Release20081225)가 승인되면이 비트를 배송하십시오.

별도의 프로젝트이지만 동일한 솔루션에 있습니다. (테스트 및 생산 코드를위한 별도의 솔루션을 사용하여 제품을 개발했습니다. 끔찍합니다. 항상 두 가지를 전환하고 있습니다.)

별도의 프로젝트에 대한 이유는 다른 사람들이 명시한 것입니다. 데이터 기반 테스트를 사용하는 경우 프로덕션 어셈블리에 테스트를 포함하면 상당한 양의 팽창이 발생할 수 있습니다.

프로덕션 코드의 내부 멤버에 액세스해야하는 경우 InternalsVisibleTo를 사용하십시오 .


프로덕션 코드로 테스트를 배포하는 것에 대한 이의 제기를 이해하지 못합니다. 작은 마이크로 캡으로 팀을 이끌었습니다 (14 ~ 130 명). 우리는 6 개 정도의 Java 앱을 보유하고 있었고, 특정 분야에서 테스트를 수행하기 위해 테스트를 현장에 배치하는 것이 매우 중요하다는 것을 알았습니다.비정상적인 동작을 보이는 기계. 현장에서 임의의 문제가 발생하고 비용이 전혀 들지 않는 미스터리에서 수천 개의 단위 테스트를 던질 수 있었으며 설치 문제, 비정상적인 RAM 문제, 기계 관련 문제, 비정상적인 네트워크 문제, 등등. 나는 현장에 시험을하는 것이 매우 귀중하다고 생각합니다. 또한 임의의 시간에 임의의 문제가 발생하며, 단위 테스트가 이미 통지를 위해 실행 대기중인 상태로있는 것이 좋습니다. 하드 드라이브 공간이 저렴합니다. 데이터와 함수를 함께 유지하려고 노력하는 것처럼 (OO 디자인), 코드와 테스트를 함께 유지하는 데 기본적으로 유용한 것이 있다고 생각합니다 (함수 + 함수를 검증하는 테스트).

테스트를 C # /. NET / Visual Studio 2008의 동일한 프로젝트에 배치하고 싶지만 여전히 달성하기에 충분하지는 않습니다.

FooTest.cs와 동일한 프로젝트에서 Foo.cs를 유지하면 얻을 수있는 큰 이점 중 하나는 클래스에 형제 테스트가 없을 때 개발자에게 지속적으로 알려줍니다! 이것은 더 나은 테스트 중심 코딩 관행을 장려합니다 ... 구멍이 더 분명합니다.


더 나은 캡슐화를 달성하기 위해 코드와 동일한 프로젝트에 단위 테스트를 배치하십시오.

내부 메소드를 쉽게 테스트 할 수 있습니다. 즉 내부에 있어야하는 메소드를 공개하지 않습니다.

또한 단위 테스트를 작성하는 코드에 가깝게 만드는 것이 좋습니다. 메소드를 작성할 때 동일한 프로젝트에 있기 때문에 해당 단위 테스트를 쉽게 찾을 수 있습니다. unitTests가 포함 된 어셈블리를 빌드 할 때 unitTest의 오류로 인해 컴파일러 오류가 발생하므로 빌드하기 위해 unittest를 최신 상태로 유지해야합니다. 별도의 프로젝트에서 단위 테스트를 수행하면 일부 개발자가 단위 테스트 프로젝트 빌드를 잊어 버리고 잠시 동안 깨진 테스트가 누락 될 수 있습니다.

컴파일 태그 (IF #Debug)를 사용하여 생산 코드에서 단위 테스트를 제거 할 수 있습니다.

자동 통합 테스트 (iUnit으로 제작)는 단일 프로젝트에 속하지 않으므로 별도의 프로젝트에 있어야합니다.


단위 테스트는 항상 별도의 프로젝트에서 진행됩니다. 실제로 솔루션에 포함 된 모든 프로젝트에 대해 별도의 테스트 프로젝트가 있습니다. 테스트 코드는 응용 프로그램 코드가 아니며 코드와 섞어서는 안됩니다. 적어도 TestDriven.Net을 사용하여 별도의 프로젝트로 유지하는 한 가지 이점은 테스트 프로젝트를 마우스 오른쪽 버튼으로 클릭하고 해당 프로젝트의 모든 테스트를 실행하여 한 번의 클릭으로 전체 응용 프로그램 코드 라이브러리를 테스트 할 수 있다는 것입니다.


경우 NUnit과의 프레임 워크를 사용, 같은 프로젝트에서 테스트를 넣어 추가적인 이유가있다. 단위 테스트와 혼합 된 다음 프로덕션 코드 예제를 고려하십시오.

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?


I fluctuate between same project and different projects.

If you're releasing a library releasing the test code with the production code is a problem, otherwise I find it usually isn't (although there's a strong psychological barrier before you try).

When putting tests in the same project I find it easier to switch between tests and the code they test, and easier to refactor/move them around.


I put them in separate projects. The name of the assembly mirrors that of the namespaces, as a general rule for us. So if there is a project called Company.Product.Feature.sln, it has an output (assembly name) of Company.Product.Feature.dll. The test project is Company.Product.Feature.Tests.sln, yielding Company.Product.Feature.Tests.dll.

You are best keeping them in a single solution and controlling the output via the Configuration Manager. We have a named configuration for each of the main branches (Development, Integration, Production) in lieu of using the default Debug and Release. Once you have your configurations setup, you can then include or exclude them by clicking on the "Build" checkbox in the Configuration Manager. (To get the Configuration Manager, right-click the solution and go to Configuration Manager.) Note, that I find the CM in Visual Studio to be buggy at times. A couple of times, I have had to go into the project and/or solution files to clean up the targets that it created.

Additionally, if you are using Team Build (and I am sure that other .NET build tools are the same) you can then associate the build with a named configuration. This means that if you don't build your unit tests for your "Production" build, for example, the build project can be aware of this setting as well and not build them since they were marked as such.

Also, we used to do XCopy drops off of the build machine. The script would just omit copying anything named *.Tests.Dll from being deployed. It was simple, but worked.


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": "yaml",
}

I would say keep them separate.

On top of the other reasons mentioned, having code and tests together skews test coverage numbers. When you report on unit test coverage - reported coverage is higher because the tests are covered when you run unit tests. When you report on integration test coverage, the reported coverage is lower because integration tests would not run unit tests.


I am really inspired by the unit testing framework of the Flood NN library by Robert Lopez. It uses a different project for every single unit tested class, and has one solution holding all these projects, as well as a main project that compiles and runs all the tests.

The neat thing is also the layout of the project. The source files are in a folder, but then the folder for the VS project is below. This allows you to make different subfolders for different compilers. All the VS projects are shipped with the code, so it is very easy for anyone to run any or all of the unit tests.


I know this is a very old question, but I would like to add my experience there I recently change unit testing habit from separate projects to same one.

Why?

First I am very tend to keep main project folder structure same with test project. So, if I have a file under Providers > DataProvider > SqlDataProvider.cs then I am creating same structure in my unit test projects like Providers > DataProvider > SqlDataProvider.Tests.cs

But after project is getting bigger and bigger, once you move files around from one folder to another, or from one project to another, then it is getting very cumbersome work to sync those up with unit test projects.

Second, it is not always very easy to navigate from class to be tested to unit test class. This is even harder for JavaScript and Python.

Recently, I started to practice that, every single file I created (for example SqlDataProvider.cs) I am creating another file with Test suffix, like SqlDataProvider.Tests.cs

At the beginning it seems it will bloat up files and library references, but at long term, you will eliminate moving file syndrome at first glance, and also you will make sure, every single file those are candidates of being tested will have a pair file with .Tests suffix. It gives you easy of jumping into test file (because it is side by side) instead of looking through separate project.

You can even write business rules to scan through project and identify class which does not have .Tests file, and report them to the owner. Also you can tell your test runner easily to target .Tests classes.

Especially for Js and Python you will not need to import your references from different path, you can simply use same path of target file being tested.

I am using this practice for a while, and I think it is very reasonable trade-off between project size vs maintainability and learning curve for new comers to the project.


Separate projects, although I debate with myself whether they should share the same svn. At the moment, I'm giving them separate svn repositories, one called

"MyProject" - for the project itself

and one called

"MyProjectTests" - for the tests associated with MyProject.

This is fairly clean and has the advantage that commits to the project and commits to the tests are quite separate. It also means you can hand over the project's svn if needed, without having to release your tests. It also means you can have branch/trunk/tag directories for your tests and for your project.

But I'm increasingly inclined to have something like the following, in a single svn repository, for each project.

MyProject
|\Trunk
| |\Code
|  \Tests
|\Tags
| |\0.1
| | |\Code
| |  \Tests
|  \0.2
|   |\Code
|    \Tests
\Branches
  \MyFork
   |\Code
    \Test

I'd be interested to know what other people think of this solution.

참고URL : https://stackoverflow.com/questions/347156/do-you-put-unit-tests-in-same-project-or-another-project

반응형