开发者

C# / Visual Studio: production and test code placement

开发者 https://www.devze.com 2023-01-01 14:52 出处:网络
In JavaLand开发者_JAVA百科, I\'m used to creating projects that contain both production and test code. I like this practice because it simplifies testing of internal code without artificially exposing

In JavaLand开发者_JAVA百科, I'm used to creating projects that contain both production and test code. I like this practice because it simplifies testing of internal code without artificially exposing the internals in a project's published API.

So far, in my experiences with C# / Visual Studio / ReSharper / NUnit, I've created separate projects (i.e., separate DLLs) for production and test code. Is this the idiom, or am I off base? If this idiomatically correct, what's the right way to deal with exposing classes and methods for test purposes?

Thanks,

-Patrick


Testing internal code is easy: use [InternalsVisibleTo] to make your production assembly "trust" your test assembly. The test assembly will then have access to all the production assembly's internal members.

The MSDN documentation linked above gives an example. It's very simple.

You should definitely separate the two out as you're doing though, IMO. You don't really want your test code (or data) to end up in production assemblies.

EDIT: Just to respond to Steven's point about testing internals: I think it's entirely reasonable to test internals. I treat unit tests as white box tests, not black box. There's definitely a place for testing only the public API - particularly for integration tests - but I find there are plenty of places where it makes sense to test internal members. Heck, without that ability, how are you going to test internal types? Sometimes a relatively small public API is layered on top of a complex internal implementation - and testing units of that implementation can be tricky through just the public API.

It does make the testing potentially more brittle, in that internal implementation changes can require test changes which wouldn't be needed if you were only testing public APIs... but it can also make the production code more robust, as you're more likely to write copious tests for corner cases etc if it's easy to do so.

Moderation in all things, basically.


Test code in the production code? I have no idea how Java handles that, but it sounds quite scary to me :-)

It's "the norm" in DotNetLand to usually have one test assembly per main assembly, which in my mind is good for several reasons:

  • Separation of code - I'm not sure how Java handles this, but what's to stop you accidentally shipping test code in your app if you have them all in the same project? This is hopefully just my ignorance of how Java works from a testing perspective than a real concern.
  • Testing from the "outside" - If you're forced to test from the outside of the code your testing it should force you to think more about whether you're testing the behavior of the code under test, rather than the implementation. You can work around internal state using things like InternalsVisibleTo, but whenever you reach for things like that it might well be a sign you're testing implementation details, not externally observable behaviour which leads to brittle tests.

The second point may sound like "teaching you to suck eggs" a little, but it's a trap I've seen many devs fall into.


You will find answers to your questions in this post (how to unit test private methods). In essence, if you are not able to separate your test code from your production code, you should reconsider your design (and that is true for Java, too).


You are correct in assuming that the creation of separate assemblies/projects to isolate your test code from your production code is the norm in .NET land. I really encourage the practice when mentoring people about unit testing because I don't want test code mixed in amongst my production code.

Generally speaking, I am extremely reluctant to test private/protected methods of my SUT. The great thing about TDD/UnitTesting is that you describe external behaviour and leave the implementation details flexible and "black boxed". You are then free to make as many refactorings as you feel are appropriate and as long as they do not break the external behaviours, the tests should not need to be changed.

If you are in some way tied to the implementation details (inheritance, access to privates/protected methods from within the production assembly), your tests will need to be refactored as frequently as the internal details of the class change.

Occasionally, you may have an internal class/method that you want to test. In this case, you can use the [assembly:InternalsVisibleTo("Test Assembly Name")] attribute in your production AssemblyInfo.cs file and allow your test assembly to see the internals of your production assembly.

InternalsVisibleToAttribute on MSDN

It should be noted that if you are new to .NET, internal is a different access qualifier than private and protected. An internal class is "public" within the assembly that houses it.

Hope this answers your questions.

0

精彩评论

暂无评论...
验证码 换一张
取 消