Better software through software architecture and devops


Monthly Archives: February 2024

  • Code on a laptop screen with dark theme

    Metrics are only useful if they help you improve. Code coverage KPIs are most often circumvented. Liberal use of the ExcludeFromCodeCoverage attribute is to be avoided.

    Abuse of the ExcludeFromCodeCoverage attribute

    I once worked on project that had a mandatory code coverage target. If your commit didn’t maintain the overall coverage ratio of 75% then it was rejected. The reasoning came from good intentions; a high code coverage is good therefore we will create the mandate that is must be high. It had some unfortunate side effects though. The first unintended consequence is that developers only wrote enough tests to keep the value above the target instead of considering how they needed to test their code. The second consequence was the proliferation of [ExcludeFromCodeCoverage] attributes adoring all sorts of classes.

    The attribute was originally designed for generated code but more recently I’ve seen it be applied where the code that is hard to test or too simple to test. Ultimately this hides code from testing metrics. Your code coverage metric is no longer accurate nor useful.

    Yeah, we are at 85% code coverage ignoring the code we excluded because it was hard to test.

    My immediate response to this is “How come it isn’t 100% then?”

    I would much rather have a lower, but accurate, code coverage metric so I consider the use of this attribute harmful on any code that isn’t generated.

    I wish code analysis tools like SonarCube or the Roslyn analyzers treated this attribute like SuppressMessageAttribute - the Justification property should be filled out when applied. Better still, just fix the issue and avoid the need to use either of them.

    Why should I test properties?

    The consensus on Should you Unit Test simple properties? seems pretty much for testing and you can use the examples here to test yours. I prefer property based testing though because it can find edge cases you didn’t think of. There is a great intro at Property-Based Testing with C# using FsCheck. Your code will effectively look like:

    public Property Set_Then_Get_Returns_Same(string exampleValue)
        var target = new ClassYouWantToTest();
        target.PropertyToTest = exampleValue;
        return (target.PropertyToTest == exampleValue).ToProperty();

    FsCheck will generate a bunch of random values to try this test with so these 4 lines of code are resulting in hundreds of unique tests for this property including, for this example: blank string, null value, very short, very long, non-printing, accent characters, etc.

    Why should I test … something else?

    I will come back and add more examples as I encounter them.


    • Code coverage metrics are only useful if they help improve the software quality.
    • Mandatory targets can lead to harmful practices such as excluding code from testing or writing superficial tests.
    • ExcludeFromCodeCoverage attributes should be treated in the same way as SuppressMessage - they hide warnings that should really be fixed.

    Photo by Luca Bravo on Unsplash

    This entry was posted in code  and tagged #metrics #testing #csharp  on .
    Discuss this on Twitter or LinkedIn
  • Red Arrows flying over Bournemouth Pier

    If you already know how to code in one language then using GitHub CoPilot Chat can be super helpful as a virtual colleague when you are working in new or unfamiliar territory.

    I have a little confession to make, this blog site hasn’t entirely been written by me. I mean I did a lot of the typing but I’ve had a little help from Github CoPilot.

    By trade I’m more on the backend side of things with C#, APIs and databases. I understand Typescript, HTML and CSS but its not natural for me to write. In the office I would find someone with complimentary skills to help out but this kind of personal project doesn’t have that luxury.

    GitHub CoPilot normally sits monitoring your code as you type offering completion suggestions which is do find a little annoying since they tend to pop up just as you are typing and then disappear. Maybe one day I’ll get use to it in the same way I have intellisense. Until then I far prefer the newer CoPilot Chat - its a tool window that sits next to your code and you chat to it like you would IM a colleague. The clever part is it can reference the code you are looking at.

    Initially I just created an empty folder and run git init to initialize a blank repository. Lets kick off with a starter to get things going.

    First step to creating an Astro site

    This doesn’t look right; the Astro Docs say its far simpler to call npm create astro@latest instead. They may be equivalent but for now I’m going to trust the documentation. In fact I got pretty far with the docs and their Build a Blog Tutorial. Whilst I was doing this I pretty much forgot about CoPilot Chat since the panel isn’t always visible. I did get stuck later on though - trying to complete the archive list on the right I couldn’t work out how to sort based on year and month. I figured it would be an idiomatic thing in JavaScript so asked:

    How to sort by year and month descending

    Notice how the code I was looking at has been used as a reference. Here is another example when I was building the monthly archive:

    How to map date to year and month

    I really like how the code comes with an explanation. This is teaching me as I work. The next challenge was to convert a month ordinal into a name for display.

    Public code block

    Now this is frustrating. It seems that since I get my CoPilot license through my work at Avanade, they have flipped a switch to ensure I don’t copy any public code and open them up to legal issues. I can see the rationale but I’m just trying to learn here. I did wonder if the typo in the question had reduced the set of results coming back and that’s why it thought I might be copying.

    Correcting the typo did work.

    Convert month ordinal to name

    This tool is super helpful when things aren’t working too. For example, first time I viewed the archive list there were duplicates in the month names. Psychic debugging tells me that there is probably a duplicate for every individual post in that month because the Set class wasn’t working as expected so I asked why.

    Why are there duplicate months

    Ah, in JavaScript, Dates are objects not values and compared by reference.

    Similarly I had a warning about a possible null value. In C# I would use a null coalescing operator ?? with a default value. I want to know the JavaScript equivalent and could have asked but thought it best to just ask for the outcome I wanted.

    Can draft default to false

    For the last example I have, I had used CoPilot to help me build a simple search form that would submit the query by opening a new window on Bing with the search as a query parameter. I also appended to restrict the results back to this blog. Hard coded would have worked but I knew I already had the site name in the config and it would be better if loaded from there.

    Lookup site in config

    This is really useful because this isn’t just about writing JavaScript, it tells me how to use the libraries I have included in the project. Alas it doesn’t work though but not for long:

    Why won't the form submit

    I used Co-Pilot to fix a lot of additional issues along the way but mostly boring TypeScript warnings so won’t inflict those on you.

    So would I recommend this approach?

    Absolutely, if you are a beginner or someone with skills in a different software area it can save a whole pile of time iterating whilst you find a solution. It will save you time looking up stuff on the web but just be aware that it might not always give you the best solution. It’s a tool not a replacement but a lot less annoying than tapping your coworkers on the shoulder to ask dumb questions. Don’t leave your brain at home though.

    This entry was posted in code  and tagged #astro #javascript #typescript #github-copilot #copilot-chat #gen-ai  on .
    Discuss this on Twitter or LinkedIn