ReSharper tests are functional tests, testing a complete end to end slice of ReSharper functionality, rather than a smaller unit such as a class. This is because it is impractical to try and mock an abstract syntax tree and a semantic model - it is simpler to build a real syntax tree and semantic model and exercise real functionality with the actual data model.
Under normal operation, ReSharper runs as an extension to Visual Studio, but this is also impractical for testing purposes. When running tests, ReSharper is started and runs as an in-memory test environment.
To create an in-memory ReSharper instance, ReSharper tests use an NUnit setup fixture, which is a fixture class that is run once, before any tests that are in the same namespace or below are run. (E.g. the
Foo.MySetupFixture setup fixture class is run before any tests in the
Foo namespace or below, such as
Foo.Bar.MyTests, are run. See the NUnit docs for more details on setup fixtures). This allows the fixture to set up and tear down any data required for those tests - i.e. the test environment.
An extension should create a class that derives from
ExtensionTestEnvironmentAssembly<TTestEnvironmentZone> and mark it with the
[SetUpFixture] attribute. The
TTestEnvironmentZone type parameter is used by the test environment to decide what parts of the ReSharper platform are initialised, and available during testing. See Zones below for more details.
This is all that is necessary to create a ReSharper test environment based on the files in the output folder. The ReSharper test environment will scan all of the files in the output folder looking for components to load via the Component Model, which means that the plugin does not need to be installed into this in-memory ReSharper instance.
Zones are a feature that ReSharper uses to manage shipping multiple products with overlapping assemblies, features and licensing requirements. Essentially, they are used to decide what parts of the application are active. More details on the use of Zones for testing can be found in the Testing Zones section.
Briefly, an extension should create a test zone definition that states what zones are required in order to run the tests. Typically, the following is sufficient. The use of the
IRequire<PsiFeatureTestZone> states that the test environment needs to run all components that have declared that they are required for testing PSI features, which includes code completion, unit testing, parsing, analysis and so on.