vstest: Entire test runner workflow is too slow and unenjoyable
I’m on the ASP.NET team and using the VS 2017 Community RTM build and CLI tools. There are a few key issues that totally disrupt my workflow with the test runner and generally make the experience unenjoyable. We use xunit with the test explorer and here are the issues I experience daily:
-
The test explorer window is too narrow and test names are unreadable by default.
Test names contain the full namespace which make it impossible to fit into the tiny winow. After I expand it to see actual, it moves the summary window to the side (which I never wanted to begin with):
-
The test runner rebuilds the test project and it’s dependencies when running any test. This is horrible experience in .NET Core projects because of the missing of “up to date” check. The entire project graph is checked for stale assets to run a single test.
-
I’m unable to right click a specific test in source and run the test. It seems to run all tests in that class instead of running the specific test method I targeted. This used to work before the move to csproj and has been broken with the new test runner and tooling.
-
Test discovery is super slow across multiple projects. It seems as though test discovery happens sequentially for each project in the solution instead of in parallel. Why is that?
-
The test runner inside visual studio doesn’t show console output. I want to see my
Console.WriteLine
output in the test runner window. I use it to debug race conditions all the time. Sometimes using the debugger doesn’t cut it because it slows everything down to a point where it’s hard to reproduce the problem. There are developers are my team that built a hacked up version of the test runner to enable this on their dev boxes. This is a real blocker. -
I can’t see the active test being run. There are situations where I want to see the current test being run (both on the command line and in visual studio) so I can tell which one is hanging (if it hangs). It would have saved me so many hours if there was a simple way to show the active test being run in both the test explorer and on the command line.
-
Certain crashes make the test runner implode. I’m working on a refactoring and when I run tests sometimes this happens:
The active test run was aborted. Reason: Unable to communicate with test host process.
Which probably means the process crashed but the test runner doesn’t help me diagnose things here. I don’t know which test was running when it crashed, so I have to manually binary search until I find the one that is the culprit.
I’ve been actively using this product for the last week in-depth and I feel like a few simple tweaks could really make this much much better.
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 213
- Comments: 57 (21 by maintainers)
Hey all, I just wanted to give an update on the progress we’ve made in this experience. We still have a long way to go, but here are some improvements you can see in Visual Studio 2017 Update 15.6.
We’ve added a hierarchy view that should help the readability of test names as well as navigation. The Projects, namespaces, and classes are different tiers in the hierarchy.
Real Time Test Discovery is on by default in Update 15.6 and should improve this greatly. This discovers tests from source code instead of by built assemblies and is much faster.
@issafram Wouldn’t it be great if
Console.WriteLine
just worked?It’s been a long beat since we’ve given an update on this ticket. Almost every experience request should be addressed in the past several Visual Studio and VS Test Platform updates. Let me give an roll call:
Going forward, there is still lots to fix in the testing experience, but I’d suggest we open a fresh issues for the individual features and close this one. I’d like to thank the community for following, upvoting, and commenting their scenarios! Hopefully most of you see a night and day difference between the test experience of 2017 and what we have today. (And if you don’t, please keep the feedback coming!)
Also, a note on this repo, the vstest repo specifically refers to the VSTest Platform. The majority of Visual Studio Test Explorer feedback should be submitted on https://developercommunity.visualstudio.com/ with the Provide Feedback Tool. in Visual Studio. This distinction is because the Test Explorer code is closed source and not a part of this repo. Thank you again for helping us improve this experience for the millions of developers who use this tool!
@Jehoel I believe we will be able to look at adding a splitter option in the next few sprints. Please follow this developer community ticket: “Group Summary” section in “Test Explorer” moves. If you are still experiencing perf issues, I’d also encourage you to file a bug on developer community.
On the names/width issue; since the names are hierarchical, this seems to be a perfect opportunity for an implicit tree structure, perhaps grouped so that you don’t have 5 levels with only one sub-level and nothing else; so in your example there would be just one parent node of
With nodes underneath that for every separate thing with a different FQN, and the test methods as the leaf level
Relatively simple UI change that can be done purely on the text of the FQN (no input from the provider needed), and could make it so much more usable
As some of you know, I’m on a mission to be able to stop using ReSharper. Without a doubt the most frequent reason I need to keep turning ReSharper back on is the convenience of these things:
Of the several testing UIs I’ve seen, Visual Studio is the only one that lacks the intuitive hierarchical paradigm. When trying to run an arbitrary selection of tests repeatedly, scrolling through a massive flat list with near-uselessly-primitive grouping abilities is distracting and tediously manual. It leaves me switching ReSharper or NCrunch back on so that I feel like I can focus on coding.
I genuinely believe that the VS teams want to provide a focused, considerate tool out of the box. You wouldn’t want to blindly copy another tool. This is one of the few areas in which I can say urgently that specific other tools have gotten it very right; thus this feedback. 😃
First time VS Test user, long time R# user.
Started with
VS 2017 Community Edition
to see if it’s caught up with Resharper (aka R#) for some/specific features. Literally unable to do any testing because of the tooling … or more precise, the same issues @davidfowl has accurately and kindly mentioned.Literally all the points raised impact us here too 😦
Even something as simple and similar as David’s point 3 - run/debug current test which the cursor is flashing, in … or right click in that test method (code) and run/debug.
Here’s some sample screenies from R#.
No, this is not trying to be 'MS is copying another product and trying to destroy it" … but … please be inspired by this premium product.
A number of us feel that we just can’t use the built in VS Test while these features aren’t around.
Sure we have paid R# lic’s. But we find R# really slows down our VS experience (it does SOOO much, to be fair to it … just tooo much for us) … which is why we would love to see if we can start using VS Test instead.
This project should please be OpenSourced. Plz. Let the community help!
6a. Please update the icon used for “test currently running”. Ideally to an icon that moves, but at least to an icon that is not mainly green the same color indicating passed tests. This also make the currently running test very hard to find, especially if it is in a list of tests you already ran and passed.
@pvlakshm or @codito - how about my questions about:
Ref:
Also … today we were trying to use it again and had this issue: We ran all tests (say 50 or 100). A test (or two? three?) errored. We saw the “red error bar” at the top but had no idea which actual test errored.
Here’s a simple example…
Which test has errored? Then compare this to a tool that makes things easier to work with:
Not hating at all - just trying to help and hope this feedback (under the OP’s same topic) can be addressed 😃
🙏
@codito Is anyone working on fixing any of the issues mentioned? How much of it is open sourced? Maybe the community can help with some of it.
The problem is I’m not trying to
Console.WriteLine
from my test. I’m trying to do it in product code. Plumbing that through manually isn’t fun.@kendrahavens Thanks for the update and I really don’t want to add another +1 comment to a github thread … but …
just adding the hierarchy view has been such a godsend! Testing is already a bazillion (yes, I used scientific metrics to calculate the improvement level) times easier to manage.
Thank you for listening!
Looking forward to the other improvements that hopefully coming too 🥂
Often also leaves lots of dotnet processes hanging around
@davidfowl great feedback. Taking up the test window ones:
This could be related to https://github.com/dotnet/roslyn-project-system/issues/62? /cc @davkean
It is possible to do parallel discovery with “Parallel” option enabled in Test Explorer. https://github.com/Microsoft/vstest/issues/499 is tracking if discovery should be parallel by default.
This is an usability issue. Created #626. Test explorer shows the
in progress
test in theNot Run
tests group. And thePassed Tests
group shows first. If a user has thousand tests, clearlyNot Run
is below the screen real estate to provide a meaningful feedback to user.Created #627 to track this.
Thanks again for bringing this up. Request readers to vote the individual issues (it will help us prioritize).
With apologies for the thread necromancy (this issue is still open after-all), but is there any “fix” for how the Test Explorer window automatically moves to a vertical-split when its made wider? (The whole point for making the Test Explorer window wider is to see more of the test-list section!) - David Fowler reported it in his original posting in 2017 and it’s still a problem today:
As I’m currently using
xUnit_style_verbose_test_names_that_describe_what_should_happen
and the still narrow layout of the Test Explorer window doesn’t work-well with this naming convention (even with namespace and type grouping).Also, right-clicking on the top few nodes in the explorer when tests are grouped by namespace and class (with xUnit at least, I don’t think it affects MSTest but I might be wrong) has a 2-3 second delay before the context-menu actually appears - this is consistently reproducible on different machines. Right-clicking on a test node results in the menu appearing near-instantly (but still with a subtle delay).
Yeah, this is unusable. It builds every single time there is a test. I’m looking at a minute and a half before it runs my single test that is: Assert.True(1 == 1).
@codito
This does appear to be a significant bottleneck for LUT runs. With every LUT run ( which we do after every edit) here is what we are seeing:
Additionally. I think VS process will also have these memory overhead that I have mentioned below.
I do understand why you guys have designed it the way it is ( to make it work for all scenarios) , however to deliver the performance that LUT needs, we do need a by-pass from this. It should be an alternative that is available to TP clients. if the existing mechanism is too bulky for their scenarios. We ( @genlu ) do have perf traces which show these bottlenecks pretty clearly. We made changes to the Test Platform code to collect this information. Please let us know if you would like to see them.
@sbaid - we would need this to address perf and scale issues for LUT for the quarterly release. Please let us know if you want us to file a separate issue for this. Additionally, it seems that a lot of issues are getting mixed up in this meta issue. It would be good to list all of the related issues at the very top and start marking them with updated status ( like under investigation, completed etc) so that all of us know about the progress. If we do not do that then I worry that things may fall through the cracks.
@bradwilson A thought about the Console problem - what if you set your own writer for Console (via SetOut) that stored it’s data based on
AsyncLocal<T>
. That way you could associate console output with the currently running test.Thank you for all the feedback and discussions.
Here is a summary of the concerns raised in this thread. I have pointed to the relevant issue tracking it. At the end I have added a pointer to the Test Explorer backlog. Please take a look there and vote up the individual issues therein. We will be executing based on the vote count.
1. The test explorer window is too narrow and test names are unreadable by default. This is xUnit specific. Names are controlled by config. Use “methodDisplay”: “method”. Please see here: https://xunit.github.io/docs/configuring-with-json.html
2. The test runner rebuilds the test project and it’s dependencies when running any test. This is horrible experience in .NET Core projects because of the missing of “up to date” check. The entire project graph is checked for stale assets to run a single test. This is related to dotnet/roslyn-project-system#62. /cc @davkean, @srivatsn
3. I’m unable to right click a specific test in source and run the test. It seems to run all tests in that class instead of running the specific test method I targeted. This used to work before the move to csproj and has been broken with the new test runner and tooling. This is xUnit-specific. This appears to be newly broken in 2.2, and there is an open bug: xunit/xunit#1140
4. Test discovery is super slow across multiple projects. It seems as though test discovery happens sequentially for each project in the solution instead of in parallel. Why is that? We are using the following issue to track scaling up test discovery for large solutions: #674
5. The test runner inside visual studio doesn’t show console output. I want to see my Console.WriteLine output in the test runner window … This is xUnit specific. Please see here: https://xunit.github.io/docs/capturing-output.html. Also, In 2.x, xUnit.net doesn’t capture the console output. You could use ITestOutputHelper: https://xunit.github.io/docs/capturing-output.html Also, see here: xunit/xunit#1119
6. I can’t see the active test being run. There are situations where I want to see the current test being run (both on the command line and in visual studio) so I can tell which one is hanging (if it hangs). It would have saved me so many hours if there was a simple way to show the active test being run in both the test explorer and on the command line. We are using the following issue to track this: #626
7. Certain crashes make the test runner implode. I’m working on a refactoring and when I run tests sometimes this happens: “The active test run was aborted. Reason: Unable to communicate with test host process.” We are using the following issue to track this: #627
8. Is anyone working on fixing any of the issues mentioned? How much of it is open sourced? Maybe the community can help with some of it. I have created a UV item: https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/18785326-make-the-vs-test-explorer-open-source. Please vote. Along with your vote feel free to indicate if you would be willing to contribute.
9. Group by namespace Please note that the Test Explorer already supports group-by-namespace.
10. Run all or just several tests from Test Explorer under performance profiler Please vote for the issue here: #660. We will use that to inform moving this into the backlog.
Test Explorer backlog Here is our Test Explorer backlog: #676 It captures the focus of our upcoming work. Please considering voting on the individual issues therein.
@davkean That’s just one level though. Notice how I mentioned Tiered levels?
It’s nice to break it down by Tiers. I think @mgravell said the same thing, above?
Keeping an excessive-overhead protocol for backwards compatibility isn’t a good answer. There needs to be a way for software which is regularly updated to opt in to some fast communication mechanism. Really it should just be in-process function calls- it’s not ok for the adapter infrastructure to be 90% of the time involved in running tests, not in this world of pervasive TDD and new features like live unit testing.
@codito, Repro Steps:
Restore.cmd
I’m also not sure that reading source information is the slow part here, I’m pretty sure its the serialization mechanism between the test adapter and VS.
xUnit can discover all 60k tests in Roslyn in seconds (by default its just reflecting over all attributes that inherit from
[Fact]
and[Theory]
, it can be slightly more expensive with a custom discoverer, but we don’t have one).You can also crack the PDBs and pull out the source information for the tests in a very small amount of time (seconds) as well (and if this was a bottleneck, then it could be made lazy and only pulled/displayed when the user selects an individual testcase, either for navigation or for viewing details).
With both of those problems “gone”, the remaining issues are:
I completely agree. I have been always staying out of using XUnit for this sole reason (+ another one that when using output capturing and you have lots of output, XUnit is damn slow - or with its resharper integration, not sure… - while NUnit works perfectly there)
For the things which appear to be xUnit.net-centric:
"methodDisplay": "method"
. https://xunit.github.io/docs/configuring-with-json.htmlITestOutputHelper
: https://xunit.github.io/docs/capturing-output.html@davidfowl
5.2) I experimented with using AsyncLocal (as suggested above) to preserve the output per test in MSTest, and found this amazing XUnit extension by @simoncropp that already implements it for XUnit. https://github.com/SimonCropp/XunitContext#xunitcontextbase
All you need to do is install the XUnitContext package and use the provided base class or register the context yourself. Then all Console writes (and other sources as well), will be written to the output stream per test and echoed in the test output when the test fails.
Here output from two tests running in parallel:
As you can hopefully see in the above output, the results are written to their respective tests even though the tests are running in parallel. The nice thing is that even non-awaited task that finishes while the test is still running will write into the correct output.
There are 3 more edge cases, that I was able to identify:
I was able to capture 2 and 3, in my extension because I used a global setup to replace the Console logger before any test run. That said we don’t have a way of showing that output in TestExplorer at the moment anyway, but it might be an improvement to consider, and get it at least into logs. Each of the edge cases has an example in the code below, in case @simonCropp would like to comment, or correct my usage of his nuget package.
Regarding the
Console.WriteLine
thing, I was working on something yesterday and wishing that Core had anIConsole
interface, which could be automatically wired up with a simple pass-through to the static class by the IoC. I ended up daydreaming about a framework-level attribute or interface which would allow you to specify a default implementation for interfaces to use if one has not been specified during IoC configuration, something that could be supported by all DI systems. Like this:Polite ping to @pvlakshm or @codito again ☝️
Ah, misread your second image, apologies. 😃
@tannergooding try opening Task manager next time and killing VsTest.Console while you are waiting… (Once cpu has hit ~0%)
@onovotny, you’re correct, just didn’t explain myself very well 😄. I meant that the default discoverers (asumming you don’t have any custom discoverers) appear to use reflection over attributes to locate the tests. Customer discoverers can do whatever mechanism they wish.
In either case, xUnit is able to discover all 60k of the Roslyn tests in seconds (not minutes), so discovery itself is not the likely bottleneck.
@davidfowl
Yes it would, but this is very similar to the Microsoft Build & Release Management Team deciding that
Write-Host
should not be allowed in PowerShell scripts. I think it is a design decision where they decided that there is no concept of a Console (Host) when running on an agent. That is my guess at least.I like to use the adapter pattern for this issue. I use an
ILogger
, or your favorite logger in my code. I then configure my logger to write to the console for certain classes or certain log types (trace or verbose or debug or whatever). NLog is great for this and has a built in logger for the console (I’m sure most loggers do as well). This keeps my production code working as expected.I then setup my unit tests to call XUnit’s
ITestOutputHelper
for myILogger
calls. This is very flexible and you get what you want in your product code while also getting the output in your unit tests.I know it sounds painful, but you are basically hard coding a dependency with
Console.WriteLine
. Abstract it and you will be ok.I’m not saying that I agree with the decision to disallow the Console from testing, but I’m ok with making my code more flexible.
@bradwilson I added an issue with examples for changes to xunit that would allow ITestOutputHelper to be registered for all tests without the need for explicit constructor injection. The changes don’t affect existing functionally, just provide better subclassing opportunities for those who want/need it. Sorry to partially hijack this issue!
See https://github.com/xunit/xunit/issues/1119
@davkean @bradwilson @Mike-EEE
Mike, thanks for mentioning Frigate. The project is still very early, but if you want to know about it, you can watch the webinar recording from the 19th minute. Don’t hesitate to ping me with questions or feedback. I’m happy to chat about integration with test runners.
I would add one more to that list: not only is discovery really, really slow - to even get to the discovery phase when opening a Solution takes > 1 minute on http://github.com/dotnet/roslyn-project-system. I suspect waiting for output groups from CPS to populate is probably a lot of that - but I’ve not investigated.