RoslynNUnitLight icon indicating copy to clipboard operation
RoslynNUnitLight copied to clipboard

Adding a reference

Open distantcam opened this issue 10 years ago • 11 comments
trafficstars

Is it possible to add a reference to the test code, so I can test analyzers that work with types from that reference?

For example, I want to write an analyzer that looks for types that implement an interface from my library. How do I write a test class that implements my interface?

distantcam avatar May 01 '15 06:05 distantcam

@distantcam I haven't tried, but it looks like you can already.

Instead of calling the next method from your tests: protected void HasDiagnostic(string markupCode, string diagnosticId)

you can instead call another overload: protected void HasDiagnostic(Document document, TextSpan span, string diagnosticId)

Prior to that, you need to obtain the Document and span by calling: public static bool TestHelpers.TryGetDocumentAndSpanFromMarkup(string markupCode, string languageName, ImmutableList<MetadataReference> references, out Document document, out TextSpan span)

which takes an optional list of references.

bkoelman avatar May 03 '15 23:05 bkoelman

@bkoelman Yes that's possible. Problem is it's a bit of work doing that because the document and span are out params of TryGetDocumentAndSpanFromMarkup, which also returns bool. So effectively I need to rewrite the whole method, and just call an overload. Which means I'm left maintaining a parallel version of a similar method. I'd much rather it be fixed in the library.

distantcam avatar May 04 '15 13:05 distantcam

@distantcam I choose to create a new test fixture subtype for my Immutable Collections analyzer to hide the helper calls Does this technique work for you?

https://github.com/DustinCampbell/CoreFxAnalyzers/blob/master/Source/CoreFxAnalyzers.Tests/ImmutableAnalyzerTestFixture.cs

DustinCampbell avatar May 08 '15 11:05 DustinCampbell

@DustinCampbell It works, but I have 2 problems with that approach.

If in the future another helper method chains off the methods hidden, they won't use the new methods because they're new, not overrrides. Not a big deal maybe, but not ideal.

Second, if the original methods are changed, I need to once again copy and paste the original code into my base class, and then modify it to work. Also not ideal.

distantcam avatar May 08 '15 11:05 distantcam

True. So, an optional parameter or overloads of HasDiagnostic and NoDiagnostic would be a better approach for you?

DustinCampbell avatar May 08 '15 11:05 DustinCampbell

@DustinCampbell Have you seen my PR #3 ? Adding a References property to the base fixture means I can override it in my test class once and not have to do it for each test call.

distantcam avatar May 08 '15 11:05 distantcam

Oops! :smile: No, I hadn't spotted it yet. My apologies, I've been on the road for the past couple of weeks.

DustinCampbell avatar May 08 '15 11:05 DustinCampbell

@DustinCampbell No worries. Yeah I thought you might be busy with a few things. Pretty sure I submitted that PR while watching one of the Build keynotes. ;)

distantcam avatar May 08 '15 12:05 distantcam

Sorry to interfere, but I believe I have something to add for taking into consideration here.

I would prefer to see an optional parameter or overloads of HasDiagnostic, NoDiagnostic and TestCodeFix, instead of a base class property. Because not all tests in the same test class may need to reference the same set of assemblies.

If they do (like in @distantcam's case), a private helper method in test class is easily created. But the other way around (my case), so when there's a readonly base class property that needs to vary per test, means that for each test I must reinstantiate a temporary derived instance of the base fixture and run against that.

bkoelman avatar May 08 '15 12:05 bkoelman

@bkoelman I can see need for both, but yes an override would also be useful.

distantcam avatar May 08 '15 13:05 distantcam

I use another approach to solve this issue: I reimplement the API under test within my test. For example: I had a test that should run on code from an extension method defined in a third party framework called ReactiveProperty.

This has some advantages:

  • no references to third party libraries (and their dependencies) needed
  • I can add support for third party libraries in different versions
  • each test shows exactly the code it is meant to run on

And some disadvantages

  • Reimplementing the signature of the third party library leads sometimes to lots of code. Example
  • I can easily make mistakes

BADF00D avatar Sep 18 '17 07:09 BADF00D