Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test adapter improvements #1524

Merged
merged 25 commits into from
May 2, 2017
Merged

Test adapter improvements #1524

merged 25 commits into from
May 2, 2017

Conversation

billti
Copy link
Member

@billti billti commented Apr 12, 2017

The test-adapter-improvements branch was fairly out of date, as master has had a lot of work recently for VS 2017 build, string localization, Node.js debugger updates, etc... This is effectively that branch with master merged in, then the merge conflicts fixed, then I fetch the work in pull request #1430 from @ozyx, merged that and fixed the merge conflicts also.

This builds clean, but I haven't done much testing on it yet (or even code reviewed the existing changes in depth). Consider this the new baseline branch to get that work reviewed, tested, completed, and checked in.

ozyx and others added 19 commits October 14, 2016 16:08
* have run_tests return structured result used by TestExecutor

* have run_tests accept test data from stdin

* run_tests receives test data over stdin

* expose StandardOutput and disable async readline

* TestExecutor receives test results over process StandardOutput

* include testing framework in testInfo object sent to run_tests.js

* comments

* close readline interface after running test

* revert ProcessOutput

* use JsonConvert.DeserializeObject<TestResult>() instead

* create GetTestResultFromProcess() method

* use Process, copy over helper methods from ProcessOutput

* close StandardInput after sending test info

* include dependency for copied ProcessOutput method

* launch node inside of RunTestCases instead

* remove some debugging stuff

* handle case if result is null

* pass in streams as parameters to allow continual reading/writing

* move setup logic to RunTests

* only remove double quotes from test case info

* move Process launch logic into function

* mocha uses runner events to determine test pass/fail

* get TestExecutor in working state, still launching one process per one test

* get TextExecutor code into working state

* fixes from PR feedback
* prepare run_tests to run multiple tests

* have tape.js run_tests use callback to return result

* launch node if test run from 'run selected tests'
…1383)

* run_tests accepts a list of tests

* mocha.js runs a list of tests and records duration

* use full title for tests and initialize time to 0

* run ExportRunner tests with single node instance

* close readline interface after tests are done

* have ExportRunner tests record test duration

* tape framework runs multiple tests with one node instance

* enable TestExecutor to run multiple tests with one instance of node

* add comment
This will make the branch build on appveyor.
@billti
Copy link
Member Author

billti commented Apr 12, 2017

Hmmmm..... trying to debug the test I'm getting the below.... Looks like there's still some work to do here.

------ Run test started ------
An exception occurred while invoking executor 'executor://nodejstestexecutor/v1': Could not load file or assembly 'Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
========== Run test finished: 0 run (0:00:03.8664085) ==========

@billti
Copy link
Member Author

billti commented Apr 12, 2017

Using fuslogvw I can see it wasn't looking in PublicAssemblies (which is where that DLL lives), but even copying it over, I'm still getting other errors. Can't see anything similar in older issues, so looks like this is a regression we'll need to figure out (I'm not sure its related to this pull request - I'll need to roll back and test even before these changes that everything was working fine on the latest bits).

Calling assembly : Microsoft.NodejsTools.TestAdapter, Version=1.0.0.15, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2017\ENTERPRISE\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.x86.exe.Config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.VisualStudio.OLE.Interop, Version=7.1.40304.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Extensions/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Extensions/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Extensions/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/COMMONEXTENSIONS/MICROSOFT/TESTWINDOW/Extensions/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/EXTENSIONS/MICROSOFT/NODEJSTOOLS/NODEJSTOOLS/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/EXTENSIONS/MICROSOFT/NODEJSTOOLS/NODEJSTOOLS/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.DLL.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/EXTENSIONS/MICROSOFT/NODEJSTOOLS/NODEJSTOOLS/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: Attempting download of new URL file:///C:/PROGRAM FILES (X86)/MICROSOFT VISUAL STUDIO/2017/ENTERPRISE/COMMON7/IDE/EXTENSIONS/MICROSOFT/NODEJSTOOLS/NODEJSTOOLS/Microsoft.VisualStudio.OLE.Interop/Microsoft.VisualStudio.OLE.Interop.EXE.
LOG: All probing URLs attempted and failed.

@billti
Copy link
Member Author

billti commented Apr 12, 2017

Slightly more progress... looks like the Node.js process is being launched with --debug-brk, and I can see it is running, but VS is not attaching, so it just sits there.

I'd also note that with the deprecation of the old debug protocol and --debug switch in the upcoming Node.js 8 release, there's probably more work to do here for this to work anyway.

@billti
Copy link
Member Author

billti commented Apr 12, 2017

Digging through the code, I can see @ozyx commented out the attach in one of his commits. (See ozyx@97a5d9e#diff-e3f74ce6d8921c9c68f663ff5523a243R260 )

Any reason for this? Is this just work in progress? I'll see if I can get this hooked up again.

@billti
Copy link
Member Author

billti commented Apr 12, 2017

FWIW: The error regarding loading Microsoft.VisualStudio.OLE.Interop.DLL also occurs in the RTW release of VS 2017 with the Node.js workload installed (i.e. without these changes), and if I replace that then another DLL fails to load (envdte90 which is also in PublicAssemblies), and I'm sure that would continue as I added more.

So seems like debugging is already broken there, and I'll need to open a separate issue for that - though this pull request still likely breaks debugging tests on VS 2015.

@ozyx
Copy link
Contributor

ozyx commented Apr 13, 2017

Commenting out the attach was a mistake on my part and replacing it shouldn't affect the functionality of my changes-- not sure why debugging is broken here. I'm currently getting my environment set-up and will be taking a look at this some time this week.

@billti
Copy link
Member Author

billti commented Apr 13, 2017

Thanks @ozyx . You can't just uncomment it, as you've replaced the _nodeProcess variable which was the NTVS class Microsoft.VisualStudioTools.Project.ProcessOutput, with one of just System.Diagnostic.Process, which is of the wrong type to pass to AttachToProcess. I was looking at moving it back today, and it may be a little work.

Also FYI, I got the debugger working (before this change) on VS 2017 by adding the below entries to the file at C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.executionengine.x86.exe.config

      <dependentAssembly>
        <assemblyIdentity name="Microsoft.VisualStudio.OLE.Interop" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <codeBase version="7.1.40304.0" href="..\..\..\PublicAssemblies\Microsoft.VisualStudio.OLE.Interop.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="EnvDTE90" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <codeBase version="9.0.0.0" href="..\..\..\PublicAssemblies\envdte90.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="EnvDTE80" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <codeBase version="8.0.0.0" href="..\..\..\PublicAssemblies\envdte80.dll" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="EnvDTE" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
        <codeBase version="8.0.0.0" href="..\..\..\PublicAssemblies\envdte.dll" />
      </dependentAssembly>

The problem is that these assemblies are no longer in the GAC in VS 2017 (see https://docs.microsoft.com/en-us/visualstudio/extensibility/breaking-changes-2017)
, so the test execution process can't find them. Adding the above bindings is a workaround for now until I figure out a more elegant solution.

@billti
Copy link
Member Author

billti commented Apr 13, 2017

Now I've got test debugging working again for VS 2017 in the original code (see #1527), I'm digging into this code a bit more. I think this is going to take a bit of refactoring and cleaning up still. I'm seeing the same code blocks repeated 3 times (the 2 RunTests overloads now effectively contain copies of the code the was, and still is, in RunTestCases - and as the RunTests methods call in to RunTestCases, its repeating operations it doesn't need to).

I see a Node.js process is still being launched for each test file. Is that necessary? It would be a perf win if not. Also, the launching logic needs to change back (or other changes made) so that debugging can attach again with this model.

I'll try and step through this a little more tomorrow and see what I come up with.

@ozyx
Copy link
Contributor

ozyx commented Apr 13, 2017

Prior to these changes, the node process would be launched per test instead of per test file. Mocha tests were run by calling mocha.only() on each test, which caused the tests to run before() and after() hooks multiple times. Since test pass/fail was only determined on the node process exit code I worked with @mjbvz to develop a channel of communication between the Javascript and C# via stdout and JSON 'result' objects. This should be a perf win from the way the test adapter operated beforehand, although agreed that the code could use some cleaning up.

There's some dialogue between me and @mjbvz on issue #518 that might be helpful.

@billti
Copy link
Member Author

billti commented Apr 19, 2017

I spent quite a bit of time on this today. I've cleaned up the code to remove some repeated blocks, and to move operations that only needed to be done once outside of loops. On my laptop, with 60 unit tests spread across 2 files I see:

Processing finished for framework of Mocha
========== Run test finished: 60 run (0:00:00.9522771) ==========

So running all of them in under a second... not bad!

I also fixed the test debugging on VS 2017 with a slighter cleaner approach than I checked in to 'master' recently. This should also improve perf and make the code simpler.

if (!DTELoaded)
{
string currentProc = Process.GetCurrentProcess().MainModule.FileName;
if (Path.GetFileName(currentProc).ToLowerInvariant().Equals("vstest.executionengine.x86.exe"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer StringComparer.OrdinalIgnoreCase.Equals since this deals with nulls cleanly. (i.e. doesn't throw if either argument is null)

// .ts file path -> project settings
var fileToTests = new Dictionary<string, List<TestCase>>();
var sourceToSettings = new Dictionary<string, NodejsProjectSettings>();
NodejsProjectSettings settings = null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: projectSettings


if (!File.Exists(settings.NodeExePath))
{
frameworkHandle.SendMessage(TestMessageLevel.Error, "Interpreter path does not exist: " + settings.NodeExePath);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably grab this message from the resource bundle

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed... but this assembly isn't localized at all currently, so that's a bigger effort.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

string.Join(Environment.NewLine, _nodeProcess.StandardErrorLines),
(!runCancelled && _nodeProcess.ExitCode == 0) ? TestOutcome.Passed : TestOutcome.Failed);
_nodeProcess.Dispose();
private static int GetFreePort() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a note where you copied this from ( I've seen something similar in the debugger code).. I think we want to refactor in the future to clean that up.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't copy this from anywhere - I just moved it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably still refactor though

@billti
Copy link
Member Author

billti commented Apr 20, 2017

Was hoping to get this in today... but on testing the various frameworks, looks like the changes totally broke Tape. I think I can see why, as loadTestCases isn't even being called any more in run_tests (per changes in bf150b7 ).

@ozyx , did you try these changes after making them? I can only assume it can't of been working for you either - unless I'm doing something wrong on my end.

I'll be on vacation for a couple days, so will need to come back to this later.

@billti
Copy link
Member Author

billti commented Apr 20, 2017

That last commit (5cfb3e2) seems to mostly have Tape working also now. Should be nearly good to go!

@billti
Copy link
Member Author

billti commented Apr 29, 2017

Ugggh. Spent forever tracking down those last couple of issues. One was in Tape itself (see referenced issue above), and the other was as a VS Preview update reset some of my files without me knowing it - so I was back running on old code I was sure I'd already fixed 😩 Good times...

These last changes (and the Tape fix) seem to have things running well. Maybe just some final clean up after another set of eyes to sign-off before checking in. Thanks.

@paulvanbrenk
Copy link
Contributor

LGTM

@billti billti merged commit 436afab into master May 2, 2017
@billti
Copy link
Member Author

billti commented May 2, 2017

Yaaaaaaaaaaaaaaaaaaaaaaaaaay! Thanks @ozyx for all the good work to get this improvement in.

@billti billti deleted the billti/test-adapter-improvements branch May 2, 2017 00:18
@ozyx
Copy link
Contributor

ozyx commented May 2, 2017

Awesome, thanks! Glad to be able to contribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants