Time Tortoise: Resolving Dependencies, Part 4

Process Monitor

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

Last week, I upgraded the Time Tortoise projects to .NET Standard 2.0, and also upgraded related NuGet packages that had .NET Standard 2.0 versions. The upgrade was mostly successful, but it broke a few unit tests. In the process of fixing them this week, I had to find yet another technique for resolving dependencies.

« Continue »

Time Tortoise: Using SystemWrapper for Unit Testing, Part 2

Wrapped System

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

With unit testing and code coverage back up and running after my work of the past two weeks, it’s time to update unit tests to get full coverage of recent functional changes. As I mentioned in an earlier post, the SystemWrapper project provides a starting point for mocking system classes when that is required by unit tests. To best use SystemWrapper, this would be a good time to upgrade Time Tortoise to .NET Standard 2.0.

.NET Standard 2.0

When I did my initial .NET Standard upgrade, UWP only supported .NET Standard 1.4. With the release of the Windows 10 Fall Creators Update, UWP now supports .NET Standard 2.0. This greatly increases the number of APIs available, which means that tools like SystemWrapper that were designed for the full .NET Framework will require fewer changes to work with .NET Core.

Since the Time Tortoise projects were already on .NET Standard, moving to .NET Standard 2.0 was fairly straightforward:

  • In the Project Properties for TimeTortoise.UWP, change both the Min version and Target version to Windows 10 Fall Creators Update (10.0; Build 16299). This means that the app will only be available to users on the most recent version of Windows 10. This reduces the potential user base, but one advantage of developing for Windows 10 is that users are encouraged to rapidly adopt new releases.
  • In the Project Properties for all of the .NET Standard class libraries, change the Target framework from .NET Standard 1.4 to .NET Standard 2.0.
  • In NuGet Package Manager, update all NuGet packages. Some packages have new versions that require .NET Standard 2.0.
  • Rebuild the Time Tortoise solution.

Unit Tests

In a perfect world, the upgrade would be complete after the previous steps. But as I have documented at length: using Visual Studio, .NET Core/.NET Standard, and xUnit.NET requires periodic manual attention to keep things running. So I wasn’t surprised that after the .NET Standard upgrade, none of my .NET Core unit tests were discovered.

Fortunately, I now have a tool that speeds up many of the manual steps required to get unit tests working after dependency changes. Using that tool, I made the DLL updates that were required as a result of the framework upgrade.

SystemWrapper

SystemWrapper targets the traditional .NET Framework 4.x. With the Time Tortoise projects targeting .NET Core 2.0, it should be easier to create a “SystemWrapperCore” that can be referenced from Time Tortoise.

Unfortunately, it’s not as easy as creating a few .NET Core 2.0 projects and copying over the SystemWrapper code. There are still .NET Framework APIs that don’t exist in .NET Core 2.0. So there would be some manual work involved in creating a SystemWrapperCore solution.

Rather than do all of the manual work at once, I have decided to start with an empty project and convert classes as I need them. For example, to write a proper unit test for the Daily Summary File feature, I need a mock version of System.IO.FileInfo. SystemWrapper has the appropriate interface, IFileInfo. That interface references IDirectoryInfo, so I had to add that one as well. But IDirectoryInfo uses System.Runtime.Remoting, which is not available in .NET Core. So I had to comment out the using statement, as well as one method definition, CreateObjRef.

I continued that process with IFileStream, IStream, IStreamReader, IStreamWriter, and a few others, before I got to the point where I could compile my minimal version of SystemWrapper. With luck, I’ll be able to gradually add interfaces without running into an object graph that wants to pull in most of the SystemWrapper solution.

(Image credit: Juhan Sonin)

Time Tortoise: Code Coverage for .NET Core Projects

Code Coverage

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

After I switched my Time Tortoise projects to .NET Standard a few weeks ago, I noticed a problem with code coverage results: most projects didn’t have any. Since I find code coverage measurement to be an important part of unit testing, I spent some time investigating and fixing the problem.

Missing Dependencies

Missing or incorrect dependencies have been a common cause of Time Tortoise unit test problems. Last week, I built a tool to simplify the process of dependency investigation. But even with all assembly binding errors resolved, I still wasn’t getting all of my code coverage results.

CodeCoverage.exe

In my code coverage results, I noticed that coverage was only being measured for my test projects. It can be useful to measure coverage for these projects. For example, it’s one way to detect tests that aren’t being run. However, the main purpose of code coverage measurement is to see what percentage of the product code is being exercised when unit tests are run. But I wasn’t getting any results for product code, despite the fact that the code coverage report told me that 100% of my test code was being run.

In searching the Web for answers about code coverage results only showing up for test projects, I came across a Stack Overflow answer that I wrote a few years ago on this subject. Thanks, Stack Overflow, for reminding me of things I used to know, but have since forgotten.

In my answer, I linked to an MSDN blog post called Troubleshooting missing data in Code Coverage Results. It explains how to use CodeCoverage.exe, a tool that comes with Visual Studio, to analyze code coverage results:

  • Find the tool under the Visual Studio install directory. For example: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Dynamic Code Coverage Tools
  • Find the .coverage file for the code coverage run in question. It should be under a TestResults folder at the top level of your project. For example, I have one under TimeTortoise\TestResults\391bea31-6ea2-4351-b63f-cf30aafbe8e8.
  • Run CodeCoverage.exe analyze /include_skipped_modules my.coverage > analysis.xml.
  • Open analysis.xml and search for the projects that are missing code coverage results.

When I did that, I found these results:

<skipped_module name="timetortoise.client.dll"
path="timetortoise.client.dll" reason="no_symbols" />
<skipped_module name="timetortoise.dal.dll" 
path="timetortoise.dal.dll" reason="no_symbols" />
<skipped_module name="timetortoise.model.dll" 
path="timetortoise.model.dll" reason="no_symbols" />
<skipped_module name="timetortoise.server.dll" 
<skipped_module name="timetortoise.testhelper.dll" 
path="timetortoise.testhelper.dll" reason="no_symbols" />
<skipped_module name="timetortoise.viewmodel.dll" 
path="timetortoise.viewmodel.dll" reason="no_symbols" />

The no_symbols reason means “PDBs (symbol files) are unavailable/missing.” But I checked the output directory, and every Time Tortoise DLL has a corresponding PDB. So something else must be going on.

Portable PDBs

Searching for answers more specifically related to .NET Core/.NET Standard led me to a Visual Studio Developer Community thread with the answer: .NET Core projects generate portable PDBs, but code coverage requires full PDBs. This is issue #800 on the vstest GitHub site.

Fortunately, there’s an easy workaround to use until the issue is resolved: add <DebugType>Full</DebugType> to PropertyGroup in the appropriate csproj files. So my PropertyGroup section looks like this:

<PropertyGroup>
  <TargetFramework>netstandard1.4</TargetFramework>
  <DebugType>Full</DebugType>
</PropertyGroup>

With this simple change, I’m once again getting code coverage results for all of my .NET Core/.NET Standard projects, along with the benefits of that project type.

Time Tortoise: An Assembly Binding Log Parser

Assembly Binding Log Parser

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

I have written before about the .NET Assembly Binding Log Viewer (part 2, part 3) and how to use it to resolve problems with dependencies that have a version mismatch or are missing entirely.

The Log Viewer, which is installed with Visual Studio, is a simple tool for managing a set of logging-related registry keys and the log files in a specified directory. When logging is enabled, the system writes log files to the directory. These log files are in HTML format, but don’t have much in the way of formatting. So though the information they contain is invaluable, it’s not presented in the most understandable way.

Since I found myself spending a lot of time looking through these files to resolve dependency issues, I decided it would be worth writing a simple tool to display the log files in a more useful format.

« Continue »

Time Tortoise: Self-Hosting Cheat Sheet

Packaging

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

It’s November, which means there are only two months left in my Time Tortoise project. That doesn’t mean I’ll stop working on it completely next year, but I won’t be writing about it much on this blog since I’ll be starting another project. To find out more about that project, look for the Subscribe option on this page.

With the main project wrapping up, it’s important to focus on the most important remaining work. A good way to do that is to self-host, or use the app for real time tracking. I wrote about the idea of self-hosting earlier this year. Today’s post is a cheat sheet for the self-hosting process.

« Continue »

Time Tortoise: Resolving Dependencies, Part 3

Test Discovery

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

I found an interesting technique this week related to the NuGet/xUnit.net dependency issue that I have written about previously. It doesn’t solve the dependency problem, but it’s another tool that can be used when Visual Studio or xUnit fail to discover unit tests.

« Continue »

Time Tortoise: Using SystemWrapper for Unit Testing

System Wrapper

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

An ongoing challenge when writing unit tests is isolating the class under test from the classes that it depends on. When you’re the one writing the dependencies, you can write them in a way that is friendly to unit testing. But when the dependencies are part of the framework you’re using, you have less control over the design. For .NET programmers who value unit testing, there’s a library called SystemWrapper whose purpose is to make .NET Framework apps more testable.

« Continue »

Time Tortoise: Upgrading to .NET Standard

.NET Standard Class Library

This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.

In January of this year, when I first started experimenting with the code that would become Time Tortoise, I was using Visual Studio 2015 for my development environment. When Visual Studio 2017 was released, I upgraded. Well, technology moves on, and while VS2017 remains my environment of choice, it’s time for a .NET upgrade.

« Continue »