Skip to content

Conversation

richardboehme
Copy link
Contributor

This is a first shot at allowing parallel coverage collection. The advantage of the DRb-based approach is that we do not need to detect if coverage is collected in parallel or not, it should just work theoretically. This also means that this should run with all tools that run tests in parallel on the same machine, but I only tested it with the framework that should not be named here.

There are probably more sophisticated ways of doing this so please let me know if we should adjust anything! I'm looking forward to any feedback on this one!

Closes #394

@richardboehme richardboehme requested a review from ahx as a code owner September 29, 2025 19:01
@ahx
Copy link
Owner

ahx commented Sep 29, 2025

Nice! Thanks for the PR, Richard. I will take a look in the next days and will see if I can test it. Thanks for your interest in this project and the work on the issue and this PR.

@richardboehme
Copy link
Contributor Author

Nice! Thanks for the PR, Richard. I will take a look in the next days and will see if I can test it. Thanks for your interest in this project and the work on the issue and this PR.

Of course! Thank you so much for creating and maintaining it 🙏

# is wrapped in a CoveredResponse data object.
tracker&.track_response(
oad.key,
CoveredResponse.new(
Copy link
Owner

Choose a reason for hiding this comment

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

👍🏼

plan = Plan.for(oad, skip_response:, skip_route:)
[oad.key, plan]
end
tracker = Tracker.new(Test.definitions, skip_response:, skip_route:)
Copy link
Owner

Choose a reason for hiding this comment

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

I am looking for code to distinguish the main process from "remote" process… but that is not needed here, because Test.start only run in the main process?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I assume here that Coverage.start (or Test.setup) is called in the main process. The issue is I'm not sure how to differentiate between main and worker process without storing the main process PID somewhere (which requires that some code is expected to run in the main process anyway).

Do you consider the Coverage module to be public API? In the Test module we at least safe-guard against multiple calls to setup which also prevents multiple calls to Coverage.start.

Copy link
Owner

@ahx ahx Sep 30, 2025

Choose a reason for hiding this comment

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

Do you consider the Coverage module to be public API?

Good question. I think I started out with Test::Coverage being public API, but added Test.setup after that. So I think Coverage should be considered private. …which could make some class methods on Coverage obsolete.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you want to we can add something like Test.in_main_process? and guard Coverage.start with this. However, this would still require that Test.setup is called in the main process, which would then set the PID. What do you think? Alternatively we could also return early from Coverage.start if @drb_uri is non-nil?

…which could make some class methods on Coverage obsolete.

I thought about this as well while exchanging the current_run Hash with the Tracker class. For example, the current_run method is currently only used in specs. Same for the plans or the reset method.

Copy link
Owner

@ahx ahx Oct 1, 2025

Choose a reason for hiding this comment

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

If you want to we can add something like Test.in_main_process? and guard […] What do you think? Alternatively we could also return early from Coverage.start if @drb_uri is non-nil?

Hey @richardboehme, I think both approaches are fine. I don't have a strong opinion on this things right now. Maybe the second variant is simpler and respects the lines between Test and Coverage? Do you want to add that guard in this PR?

I thought about this as well while exchanging the current_run Hash with the Tracker class.

I will have removed Coverage.current_run, .plans, .install, .uninstall in another PR. #401

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay I added a small guard on top of the Coverage.start method!

@ahx
Copy link
Owner

ahx commented Oct 1, 2025

I think is this great and would like to merge it. Just 👋🏼 whenever you think this is ready to go. 👍🏼

@richardboehme
Copy link
Contributor Author

I think is this great and would like to merge it. Just 👋🏼 whenever you think this is ready to go. 👍🏼

Thank you, I think this is ready to merge now!

end

def start(skip_response: nil, skip_route: nil)
return if @drb_uri
Copy link
Owner

Choose a reason for hiding this comment

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

👍🏼

@ahx ahx merged commit e60e199 into ahx:main Oct 3, 2025
@richardboehme richardboehme deleted the drb-parallel branch October 3, 2025 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Usage of coverage with Rails parallel tests

2 participants