Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing: Lint for unparallelized tests without explicit reason #4746

Merged
merged 4 commits into from
Nov 4, 2022

Conversation

jdtzmn
Copy link
Contributor

@jdtzmn jdtzmn commented Nov 3, 2022

Summary

This PR starts the process of improving unit test parallelization by enabling the paralleltest linter within golang ci. Fixing missing t.Parallel's will require careful consideration and so, in this initial PR, packages currently failing the paralleltest linter are excluded.

Future PRs will incrementally add the t.Parallel() flag to tests in existing packages and disable that package's exclusion within .golangci.yml. As a result, tests added to that package in the future will fail the linter if the parallel signal is not present and a reason is not given as to why it is missing. For more information regarding the process of finding and fixing incorrect tests within a particular package, refer to the additional information below.

Additional Information

A large part of the work related to this PR involved brainstorming a path toward fixing unparallelized tests within existing packages. I've listed some additional information and answers to common questions below.

I want to start fixing missing instances of `t.Parallel` in a specific package. How can I find all the parlleltest errors associated with that package?

1. Adjust the .golangci.yml configuration file to not exclude the particular package.

For example, to reveal errors within the ledger package, remove ledger from the exclusion filter:

path: (data|ledger|logging).*_test.go becomes path: (data|logging).*_test.go

2. Temporarily disable the new-from-rev configuration within .golangci.yml by commenting it out.

A majority of the tests without t.Parallel() were committed before the set revision so we must disable this configuration to let through every instance of the error within the particular package.

3. Lint and filter by paralleltest errors specifically

> make lint | grep paralleltest

We must filter specifically for paralleltest errors here because many more errors will creep through once we ignore the new-from-rev argument.

How can I mark tests to show that they shouldn't be run in parallel?

If you find yourself in a situation where using t.Parallel() is impossible, put a //nolint:paralleltest comment on the line where the error is caught and be sure to include an explanation for why the test could not be parallelized.

For an example of how this looks in practice, please refer to examples in this commit.

Will new tests in excluded packages be caught by the linter?

Unfortunately, new tests without the parallel flag will not be caught by the linter as I could not find any way within the golangci lint configuration to demarcate that specific linters should be run against particular revisions. In other words, the new-from-rev flag applies to all linters and cannot be set individually.

This is why future PRs that fix existing errors within packages will be necessary to make enabling this linter worthwhile. Once existing tests missing the parallel flag have been fixed, the exclusion rule for that package can be removed and new tests after that point will be caught.

Test Plan

These are primarily linter changes that do not benefit from tests.

@jdtzmn jdtzmn self-assigned this Nov 3, 2022
@codecov
Copy link

codecov bot commented Nov 3, 2022

Codecov Report

Merging #4746 (0e01e02) into master (06f9109) will decrease coverage by 0.05%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master    #4746      +/-   ##
==========================================
- Coverage   54.62%   54.57%   -0.06%     
==========================================
  Files         414      414              
  Lines       53514    53514              
==========================================
- Hits        29231    29203      -28     
- Misses      21859    21881      +22     
- Partials     2424     2430       +6     
Impacted Files Coverage Δ
ledger/tracker.go 74.89% <0.00%> (-2.98%) ⬇️
network/wsPeer.go 66.50% <0.00%> (-2.67%) ⬇️
crypto/merkletrie/trie.go 66.42% <0.00%> (-2.19%) ⬇️
crypto/merkletrie/node.go 91.62% <0.00%> (-1.87%) ⬇️
data/transactions/verify/txn.go 76.19% <0.00%> (-0.96%) ⬇️
catchup/service.go 68.88% <0.00%> (-0.50%) ⬇️
ledger/acctupdates.go 69.05% <0.00%> (-0.25%) ⬇️
network/wsNetwork.go 65.34% <0.00%> (-0.19%) ⬇️
ledger/blockqueue.go 88.50% <0.00%> (+2.87%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@cce
Copy link
Contributor

cce commented Nov 3, 2022

If you want custom control of rules just for a single linter, you could theoretically set up a separate .golangci-paralleltest.yml configuration and add it to make lint as a second pass, and to reviewdog as an additional pass..

t.Run(fmt.Sprintf("unified=%t", unified), func(t *testing.T) {
// t.Parallel() NO! unified variable is actually shared

t.Run(fmt.Sprintf("unified=%t", unified), func(t *testing.T) { //nolint:paralleltest // NO t.Parallel(). unified variable is actually shared
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this linter actually complain about every t.Run too? Or just top-level func Test*?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also t.Run(). For a full list of the errors it catches: https://github.com/kunwardeep/paralleltest#examples

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I see it does.

Copy link
Contributor

@michaeldiamant michaeldiamant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jdtzmn Thanks for getting the process started!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants