Skip to content

Instantly share code, notes, and snippets.

@MadLittleMods
Last active November 5, 2021 21:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MadLittleMods/4ab08f51609fab759247f299a4e33406 to your computer and use it in GitHub Desktop.
Save MadLittleMods/4ab08f51609fab759247f299a4e33406 to your computer and use it in GitHub Desktop.
Golang: Escape forward slash in test name when using `-run` regex

How to escape a forward slash in a test name when using -run to run a single Go test?

I don't think it's possible. The following are some other articles/blog posts reiterating this point.

The key seems to just not use any forward slashes in test names so you can target them individually no matter what.

Go Subtest Tips by Frew Schmidt

=== RUN   TestLastIndex
=== RUN   TestLastIndex/single
    TestLastIndex/single: prog.go:33: LastIndex([1], 1) = -1, want 0
=== RUN   TestLastIndex/pair
=== RUN   TestLastIndex/pair/different
    TestLastIndex/pair/different: prog.go:33: LastIndex([2 1], 2) = -1, want 0
=== RUN   TestLastIndex/four
=== RUN   TestLastIndex/five
=== RUN   TestLastIndex/six
    TestLastIndex/six: prog.go:33: LastIndex([3 1 2 2 1 1], 3) = -1, want 0
--- FAIL: TestLastIndex (0.00s)
    --- FAIL: TestLastIndex/single (0.00s)
    --- PASS: TestLastIndex/pair (0.00s)
    --- FAIL: TestLastIndex/pair/different (0.00s)
    --- PASS: TestLastIndex/four (0.00s)
    --- PASS: TestLastIndex/five (0.00s)
    --- FAIL: TestLastIndex/six (0.00s)
FAIL

4 tests failed.

Now let’s say you wanted to run just pair/different while you debug it. In this test there’s not a lot of output, but sometimes tests might have tons of lines of output so it can be useful to only run what you must. Here’s some commands you might consider trying to run pair/different:

  • go test -run Index/pair/different
  • go test -run Index/pair\/different
  • go test -run 'Index/pair\/different'
  • go test -run 'Index/pair[/]different'
  • go test -run 'Index/pair.different'

All of these either run both pair and pair/different or they run no subtests at all. The answer comes in the documentation for -run:

        -run regexp                            
            Run only those tests and examples matching the regular expression.
            For tests, the regular expression is split by unbracketed slash (/)
            characters into a sequence of regular expressions, and each part                   
            of a test's identifier must match the corresponding element in                     
            the sequence, if any. Note that possible parents of matches are
            run too, so that -run=X/Y matches and runs and reports the result   
            of all tests matching X, even those without sub-tests matching Y,                  
            because it must run them to look for those sub-tests.  

This explains both of the outcomes in the commands above. When you run go test -run X/Y/Z go creates three regexp objects (one for X, one for Y, and one for Z.) It matches X against the function name of the test; if it matches, it will then run the test. When the test is running, it tries to run all subtests and if the subtest matches Y, the subtest gets run. Finally any subtests of Y named Z will be run, though we happen to not have a third level of nesting here.

This implies two rules for subtests in go. First, do not put / in subtest names. One could argue that testing should actually escape these, but just not using / is simple. If you have a / in a subtest name and the prefix before the matches other tests, you’ll never be able to run the longer named test without also running the prefix. At work I used to have tests that had filenames in the subtest name; because of this I replaced the / with something like !.

Second, if possible, keep the meat of the test in the leaf tests. Anything in non-leaf tests may get run and may produce distracting output.

-- https://blog.afoolishmanifesto.com/posts/golang-subtest-tips/

Using Subtests and Sub-benchmarks by Marcel van Lohuizen (Golang blog)

Perhaps a bit surprising, using -run=TestTime/New_York won’t match any tests. This is because the slash present in the location names is treated as a separator as well. Instead use:

$ go test -run=Time//New_York
--- FAIL: TestTime (0.00s)
    --- FAIL: TestTime/12:31_in_America/New_York (0.00s)
        time_test.go:88: got 07:31; want 7:31

Note the // in the string passed to -run. The / in time zone name America/New_York is handled as if it were a separator resulting from a subtest. The first regular expression of the pattern (TestTime) matches the top-level test. The second regular expression (the empty string) matches anything, in this case the time and the continent part of the location. The third regular expression (New_York) matches the city part of the location.

Treating slashes in names as separators allows the user to refactor hierarchies of tests without the need to change the naming. It also simplifies the escaping rules. The user should escape slashes in names, for instance by replacing them with backslashes, if this poses a problem.

-- https://go.dev/blog/subtests#running-specific-tests-or-benchmarks-h2


  • golang test forward slash in test name "-run"
  • golang test "/" in test name "-run"
  • go test escape "-run"
  • go test parentheses in test name "-run"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment