RoslynNUnitLight
RoslynNUnitLight copied to clipboard
Adding a reference
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 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 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 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 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.
True. So, an optional parameter or overloads of HasDiagnostic and NoDiagnostic would be a better approach for you?
@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.
Oops! :smile: No, I hadn't spotted it yet. My apologies, I've been on the road for the past couple of weeks.
@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. ;)
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 I can see need for both, but yes an override would also be useful.
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