What to cache when building Rust using Gitlab CI or similar

Andy Balaam from Andy Balaam's Blog

When building your project with Gitlab CI or a similar build tool, you can end up spending a lot of time watching your build repeat the same steps over and over. This is especially frustrating when it mostly consists of downloading and compiling the same things we downloaded and compiled last time.

To mitigate this, we can ask Gitlab CI to cache things that will be the same next time.

For a Rust project, the most important thing to cache is target in the local directory.

But, if you are installing tools using rustup or cargo, it will really help if you cache those too. Fortunately, Rust knows where those are by using environment variables, and these are defined in the standard Rust Docker image.

We can make sure we’re caching as much as possible by adding a section like this to .gitlab-ci.yml:

    cache:
        key: shared-cache
        paths:
            - target/
            - $CARGO_HOME/
            - $RUSTUP_HOME/

If you add this to all your jobs, they will share a single cache between them, and cache the local target directory as well as any tools installed with rustup or cargo.

Here is a full example from my Evolve SVGs project:

image: rust:latest

before_script:
    - rustup component add rustfmt
    - rustup target add wasm32-unknown-unknown
    - cargo install trunk wasm-bindgen-cli

pages:
    stage: deploy
    script:
        - echo "Publishing pages to" $CI_PAGES_URL
        - make deploy
        - mv dist public
    artifacts:
      paths:
        - public
    only:
        - main
    cache:
        key: shared-cache
        paths:
            - target/
            - $CARGO_HOME/
            - $RUSTUP_HOME/

test:
    stage: test
    script:
        - make test
    cache:
        key: shared-cache
        paths:
            - target/
            - $CARGO_HOME/
            - $RUSTUP_HOME/

The Sprint Goal?

Allan Kelly from Allan Kelly Associates

Hi Allan, what do you think of this as a Spring Goal?
  • Prototype store locator
  • Deploy product selector to live
  • Fix accessibility defects identified by client
  • Complete visual design of search feature
  • Security fixes & updates
  • Team improvement: refactor VX tables, page template processor”

I answer:

“This looks more like a sprint backlog than a sprint goal.”

This e-mail exchange sums up the problem with the sprint goal, or rather, the sprint goal as it so often ends up being used.

The sprint goal has always been part of Scrum even if it has often been forgotten. The idea behind it was to say: “What is the outcome this team needs to make happen this sprint?” The goal was meant to be a non-trivial thing, a meaningful step forward, an outcome, perhaps a challenge, certainly a rallying point.

However the sprint goal fell into disuse. When I used to run teams I never used it – partly because my teams have never used strict Scrum but also because most of the teams I worked with had multiple things happening. The teams were expected to make progress across a broad front. Conversely the sprint goal focuses the team on a single thing.

My experience was far from unique. And, if I’m being honest, in the days when I gave agile training regularly I never talked about it much. Again, most of the teams I encountered were expected to “deliver stuff” it was more a case of “burning down the backlog.”

When I did see the sprint goal used it was normally used in reverse. Rather than teams setting a goal and asking “What do we need to do to make this happen?” teams would decide on a collection of stories from the backlog and then ask “What is the goal we can write that describes this collection of items?” In such cases the goal might as well be “Do stuff” or perhaps “Do the collection of stories we think we can do.”

The goal was meaningless so why bother?

Yet I detect a change in the air. In the last few years I’ve heard the sprint goal talked about more and I’ve observed teams setting a goal more often. Plus, as I wrote in Succeeding with OKRs in Agile, a sprint goal sits well with OKRs – it also provides a way to cut through the tyranny of the backlog.

Unfortunately I have to report the teams I see setting sprint goals are still setting goals about “Do these stories from the backlog.”

Why is this?

Perhaps it is because the sprint goal is misunderstood or perhaps it is because people are aiming to tick off as many Scrum practices as they can, maybe they feel they must use the goal because Scrum lists it.

I’m sure both of these reasons are at play but I think the main reason is because of backlog fetish and the expectation that teams “do the backlog.” Teams – and especially product owners – don’t have the skills or aren’t being given the authority to make decisions about what to do based on fresh information arriving from customers, analytics and analysis.

That is: most teams are still expected to burn-down the backlog.

Well, it is one way of working, I understand the logic, and burning-down a backlog with Scrum is probably still better than ticking off use cases from a requirements document in a waterfall; but it still leaves so much opportunity unrealised. Things could be so much better if teams really worked to sprint goals and OKRs rather than labouring under the tyranny of the backlog.

So if you want some practical advice: if you are setting sprint goals in reverse just give up, accept that you “do backlog items” and save yourself the time of inventing a goal.

And if you are not setting a sprint goal: have a serious talk about it as a team, examine what having a sprint goal would mean and how you might work differently. Then experiment with using a sprint goal for a few sprints.

This advice goes doubly if you are a Product Owner, seriously using sprint goals is going to relieve you of a lot of backlog administration but means you will need to think hard about goals and what will really improve your product.


Subscribe to my blog newsletter and download Continuous Digital for free

(normal price $9.99/£9.95/€9.95)

The post The Sprint Goal? appeared first on Allan Kelly Associates.

Mutation testing: its days in the limelight are over

Derek Jones from The Shape of Code

How good a job does a test suite do in detecting coding mistakes in the program it tests?

Mutation testing provides one answer to this question. The idea behind mutation testing is to make a small change to the source code of the program under test (i.e., introduce a coding mistake), and then run the test suite through the mutated program (ideally one or more tests fail, as-in different behavior should be detected); rinse and repeat. The mutation score is the percentage of mutated programs that cause a test failure.

While Mutation testing is 50-years old this year (although the seminal paper/a> did not get published until 1978), the computing resources needed to research it did not start to become widely available until the late 1980s. From then, Until fuzz testing came along, mutation testing was probably the most popular technique studied by testing researchers. A collected bibliography of mutation testing lists 417 papers and 16+ PhD thesis (up to May 2014).

Mutation testing has not been taken up by industry because it tells managers what they already know, i.e., their test suite is not very good at finding coding mistakes.

Researchers concluded that the reason industry had not adopted mutation testing was that it was too resource intensive (i.e., mutate, compile, build, and run tests requires successively more resources). If mutation testing was less resource intensive, then industry would use it (to find out faster what they already knew).

Creating a code mutant is not itself resource intensive, e.g., randomly pick a point in the source and make a random change. However, the mutated source may not compile, or the resulting mutant may be equivalent to one created previously (e.g., the optimised compiled code is identical), or the program takes ages to compile and build; techniques for reducing the build overhead include mutating the compiler intermediate form and mutating the program executable.

Some changes to the source are more likely to be detected by a test suite than others, e.g., replacing <= by > is more likely to be detected than replacing it by < or ==. Various techniques for context dependent mutations have been proposed, e.g., handling of conditionals.

While mutation researchers were being ignored by industry, another group of researchers were listening to industry's problems with testing; automatic test case generation took off. How might different test case generators be compared? Mutation testing offers a means of evaluating the performance of tools arrived on the scene (in practice, many researchers and tool vendors cite statement or block coverage numbers).

Perhaps industry might have to start showing some interest in mutation testing.

A fundamental concern is the extent to which mutation operators modify source in a way that is representative of the kinds of mistakes made by programmers.

The competent programmer hypothesis is often cited, by researchers, as the answer to this question. The hypothesis is that competent programmers write code/programs that is close to correct; the implied conclusion being that mutations, which are small changes, must therefore be like programmer mistakes (the citation often given as the source of this hypothesis discusses data selection during testing, but does mention the term competent programmer).

Until a few years ago, most analysis of fixes of reported faults looked at what coding constructs were involved in correcting the source code, e.g., 296 mistakes in TeX reported by Knuth. This information can be used to generate a probability table for selecting when to mutate one token into another token.

Studies of where the source code was changed, to fix a reported fault, show that existing mutation operators are not representative of a large percentage of existing coding mistakes; for instance, around 60% of 290 source code fixes to AspectJ involved more than one line (mutations usually involve a single line of source {because they operate on single statements and most statements occupy one line}), another study investigating many more fixes found only 10% of fixes involved one line, and similar findings for a study of C, Java, Python, and Haskell (a working link to the data, which is a bit of a mess).

These studies, which investigated the location of all the source code that needs to be changed, to fix a mistake, show that existing mutation operators are not representative of most human coding mistakes. To become representative, mutation operators need to be capable of making coupled changes across multiple lines/functions/methods and even files.

While arguments over the validity of the competent programmer hypothesis rumble on, the need for multi-line changes remains.

Given the lack of any major use-cases for mutation testing, it does not look like it is worth investing lots of resources on this topic. Researchers who have spent a large chunk of their career working on mutation testing will probably argue that you never know what use-cases might crop up in the future. In practice, mutation research will probably fade away because something new and more interesting has come along, i.e., fuzz testing.

There will always be niche use-cases for mutation. For instance, how likely is it that a random change to the source of a formal proof will go unnoticed by its associated proof checker (i.e., the proof checking tool output remains unchanged)?

A study based on mutating the source of Coq verification projects found that 7% of mutations had no impact on the results.

Automatically enabling multiple Emacs minor modes via a major mode hook

Timo Geusch from The Lone C++ Coder&#039;s Blog

In Emacs, I usually end up enabling the same set of minor modes when I use one of my “writing modes”, namely modes like markdown-mode and org-mode. Enabling a single minor mode automatically is generally pretty easy via the appropriate mode hook, but enabling more than one minor mode requires one more level of indirection. Of course it does, because everything in computer science requires one more level of indirection :).

Testing rounded data for a circular uniform distribution

Derek Jones from The Shape of Code

Circular statistics deals with analysis of measurements made using a circular scale, e.g., minutes past the hour, days of the week. Wikipedia uses the term directional statistics, the traditional use being measurements of angles, e.g., wind direction.

Package support for circular statistics is rather thin on the ground. R’s circular package is one of the best, and the book “Circular Statistics in R” provides the only best introduction to the subject.

Circular statistics has a few surprises for those new to the subject (apart from a few name changes, e.g., the von Mises distribution is effectively the ‘circular Normal distribution’), including:

  • the mean value contains two components, a direction and a length, e.g., mean wind direction and strength,
  • there are several definitions of variance, with angular variance having a value between 0 and 2, and circular variance having a value between 0 and 1. The circular standard deviation is not the square root of variance, but rather: sqrt{-2 log R}, where R is the mean length.

The basic techniques used in circular statistics are still relatively new, compared to the more well known basic statistical techniques. For instance, it was recently discovered that having more measurements may reduce the reliability of the Rao spacing test (used to test whether a sample has a uniform circular distribution); generally, having more measurements improves the reliability of a statistical test.

The plot below shows Rose diagrams for the number of commits in each 3-hour period of a day for Linux and FreeBSD (mean direction and length in green; code+data):

Project actual/estimate ratio against percent complete.

The Linux kernel source has far fewer commits at the weekend, compared to working days. Given the number of people whose job is to work on the Linux kernel, compared to the number of people doing it out of interest, this difference is not surprising. The percentage of people working on OpenBSD as a job is small, and there does not appear to be a big difference between weekends and workdays. There is a lot of variation in the number of commits during each 3-hour period of a day, but the number of commits per day does not vary so much; the number of OpenBSD commits per day of week is:

            Mon   Tue   Wed   Thu   Fri   Sat   Sun 
          26909 26144 25705 25104 24765 22812 24304 

Does this distribution of commits per day have a uniform distribution (to some confidence level)?

Like all measurements, those made on a circular scale are rounded to some number of digits. Measurements may also be rounded, or binned, to particular units of the scale, e.g., measured to the nearest degree, or nearest minute.

A recent paper, by Landler, Ruxton and Malkemper, found that for samples containing around five hundred or more measurements, rounding to the nearest degree was sufficient to cause the Rao spacing test to almost always report non-uniformity, i.e., for non-trivial samples the rounding was sufficient to cause the test to detect non-uniformity (things worked as expected for samples containing fewer than 100 measurements).

Landler et al found that adding a small amount of noise (drawn from a von Mises distribution) to the rounded measurements appeared to ‘fix’ the incorrect behavior, i.e., rejecting the hypothesis of a uniform distribution, when a uniform distribution may be present.

The rao.spacing.test function, in the circular package, rejected that null hypothesis that the OpenBSD daily data has a uniform distribution. However, when noise is added to each day value (i.e., adding a random fraction to the day values, using rvonmises(length(c_per_day), circular(0), 2.0)), the call to rao.spacing.test failed to reject the null hypothesis of uniformity at the 0.05 level (i.e., the daily distribution is probably uniform).

How many research results are affected by this discovery?

I very rarely encounter the use of circular statistics (even though they should probably have been used in places), but then I spend my time reading software engineering papers, whose use of statistics tends to be primitive. I plan to include a brief mention of the use of the Rao spacing test with binned data in the addendum to my Evidence-based software engineering book (which includes the above example).

Out Of The Ordinary – a.k.

a.k. from thus spake a.k.

Several years ago we saw how to use the trapezium rule to approximate integrals. This works by dividing the interval of integration into a set of equally spaced values, evaluating the function being integrated, or integrand, at each of them and calculating the area under the curve formed by connecting adjacent points with straight lines to form trapeziums.
This was an improvement over an even more rudimentary scheme which instead placed rectangles spanning adjacent values with heights equal to the values of the function at their midpoints to approximate the area. Whilst there really wasn't much point in implementing this since it offers no advantage over the trapezium rule, it is a reasonable first approach to approximating the solutions to another type of problem involving calculus; ordinary differential equations, or ODEs.