3.0 Plugins for Unit Testing

I've been using a BDD framework lately called NSpecify. Previously, there was a plugin supporting NSpecify. Since the plugin architecture has changed, I thought that I would write my plugin for 3.0.

So far, I can get my NSpecify tests to display in the Unit Test Explorer, but I cannot get them to execute. I derived a class from JetBrains.ReSharper.TaskRunnerFramework.RemoteTaskRunner, but it never gets called (not even constructed).

On my implementation of IUnitTestProvider, I am doing this:
public RemoteTaskRunnerInfo GetTaskRunnerInfo()
{
return new RemoteTaskRunnerInfo(typeof (NSpecifyTaskRunner));
}

However, this is not being called either.

I cannot find any documentation regarding any of this. Any advice or guidance would be appreciated.

7 comments
Comment actions Permalink

Hello Christopher,

Did you implement RemoteTask's for your task runner and how did you implement
GetTaskSequence()?
You can send me plugin sources so I can review them and suggest how to fix
the problem.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


CB> I've been using a BDD framework lately called NSpecify. Previously,
CB> there was a plugin supporting NSpecify. Since the plugin
CB> architecture has changed, I thought that I would write my plugin for
CB> 3.0.
CB>
CB> So far, I can get my NSpecify tests to display in the Unit Test
CB> Explorer, but I cannot get them to execute. I derived a class from
CB> JetBrains.ReSharper.TaskRunnerFramework.RemoteTaskRunner, but it
CB> never gets called (not even constructed).
CB>
CB> On my implementation of IUnitTestProvider, I am doing this:
CB> public RemoteTaskRunnerInfo GetTaskRunnerInfo()
CB> {
CB> return new RemoteTaskRunnerInfo(typeof
CB> (NSpecifyTaskRunner));
CB> }
CB> However, this is not being called either.
CB>
CB> I cannot find any documentation regarding any of this. Any advice
CB> or guidance would be appreciated.
CB>


0
Comment actions Permalink

Thanks Illya, I appreciate your assistance.
I should note that I started off by copying the NUnit provider. I was not sure where to begin, so I was reverse engineering in order to understand how it all works.

GetTaskSequence() looks right to me, but I'm only hearing half of the conversation. :)

I implemented two RemoteTasks: NSpecifyFunctionalityTask which is analgous to a TestFixture and NSpecifySpecificationTask will is the same as a test.



Attachment(s):
BlueSpire.ReSharper.UnitTestProvider.nSpecify.zip
0
Comment actions Permalink

I started over with 3.0.1, and I was able to get it working. I believe that I must have had some typos previously, as the API appears the same after the patch.
Many thanks!

0
Comment actions Permalink

Hello Christopher,

There was the bug in ReSharper which prevented unit test providers situated
in plugins to run. We fixed it in 3.0.1.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


CB> I started over with 3.0.1, and I was able to get it working. I
CB> believe that I must have had some typos previously, as the API
CB> appears the same after the patch.
CB>
CB> Many thanks!
CB>


0
Comment actions Permalink

Thanks Ilya,
Would it be possible to get a brief description of the significant classes for the unit test API?
I am still unclear as to the responsibilities of a few things. For example, does the inheritor of TreeModelBrowserPresenter render to the unit test explorer? If so, what is responsible for marking the tests in the IDE?
I would also like a bit of info on the API that actually executes the tests (I assume it's RemoteTaskRunner).

many thanks,
Christopher

0
Comment actions Permalink

Hello Christopher,

I use TreeModelBrowserPresenter to build up IPresentableItem, which in turn
is displayed in the trees. I do this just to reuse existing system for presenting
typical items with an icon and rich text. From the API standpoint, all you
need is implement IUnitTestProvider and build IPresentableItem from UnitTestElement
in the Present() method. You can use "node" parameter to check for parent
element, if you want to customize appearance depending on the grouping. You
can also check presentation state for expaned/collapsed, focused and selected
states of the element.

As for marking elements in code window (I assume you mean this by in IDE)...
Implementation of Explore(IFile,...) should provide consumer with UnitTestElementDisposition
objects, which describe UnitTestElements layout in the specific (parsed)
file. You can't change presentation of highlighting at the moment without
implementing own IDaemonStage, IDaemonStageProcess and IHighlighting.

RemoteTaskRunner is pretty simple thing. It gets Start, Execute, Finish calls
for each task. If task has subtasks, they are executed after Execute of parent
task, but before its Finish. E.g., if you have ParentTask and ChildTask,
they will be called in this order:

ParentTask.Start()
ParentTask.Execute()
ChildTask.Start()
ChildTask.Execute()
ChildTask.Finish()
ParentTask.Finish()

/* Actually, RemoteTaskRunner.Start(task) is called, but I show them this
way for clarity */

Hierarchy of tasks is formed from sequences - IUnitTestProvider.GetTaskSequence.
For each UnitTestElement to be executed we request task sequence - what tasks
should be run in assumption this is the only element to be run. After task
sequences are sent to the runner process, they are composed into the tree
using their equality. Example:
Element1 -> Task1, Task2, Task3
Element2 -> Task1, Task2, Task4
Element3 -> Task1, Task5, Task6
Element4 -> Task7, Task8

Execution tree then will be as follows:

  • Task1

    • Task2

      • Task3 (Element1)

      • Task4 (Element2)

    • Task5

      • Task6 (Element3)

  • Task7

    • Task8 (Element4)


According to this, calls will be done:
Task1.Start+Execute
Task2.Start+Execute
Task3.StartExecuteFinish
Task4.StartExecuteFinish
Task2.Finish
Task5.Start+Execute
Task6.StartExecuteFinish
Tsak5.Finish
Task1.Finish
Task7.Start+Execute
Task8.StartExecuteFinish
Task7.Finish

For unit testing, first task in sequence should normally be IsolatedAssemblyTask,
which is executed internally and setups AppDomain for unit testing. For test
fixture elements return empty sequence - there is nothing to executed in
the absence of tests. For test elements return sequence of IsolatedAssemblyTask,
TestFixtureTask, TestTask.

ConfigureAppDomain is called once per loaded assembly. There you can check
config files and set few properties of the thread where tasks will be run.

Sincerely,
Ilya Ryzhenkov

JetBrains, Inc
http://www.jetbrains.com
"Develop with pleasure!"


CB> Thanks Ilya,
CB>
CB> Would it be possible to get a brief description of the significant
CB> classes for the unit test API?
CB>
CB> I am still unclear as to the responsibilities of a few things. For
CB> example, does the inheritor of TreeModelBrowserPresenter render to
CB> the unit test explorer? If so, what is responsible for marking the
CB> tests in the IDE?
CB>
CB> I would also like a bit of info on the API that actually executes
CB> the tests (I assume it's RemoteTaskRunner).
CB>
CB> many thanks,
CB> Christopher


0
Comment actions Permalink

Very helpful! Thank you!

0

Please sign in to leave a comment.