Skip to content

Add filterable sequential test groups#448

Merged
Bodigrim merged 7 commits intoUnkindPartition:masterfrom
Raveline:add-filterable-sequential-test-groups
Aug 3, 2025
Merged

Add filterable sequential test groups#448
Bodigrim merged 7 commits intoUnkindPartition:masterfrom
Raveline:add-filterable-sequential-test-groups

Conversation

@Raveline
Copy link
Copy Markdown
Contributor

@Raveline Raveline commented Jul 3, 2025

This is an attempt to address the use case reported in #445.

Rationale

There are many scenarios where one would want sequentialTestGroups (as in: don't run these tests in parallel) and still want the ability to filter them, particularly when working on a single test at the bottom of a long sequential group.
Furthermore, as answered by @Bodigrim, the current behaviour is not obvious from documentation (it is implied by the README in "Dependencies", in a list of caveat about patterns. Adding a dedicated utility for sequential groups that can be filtered make the intent more obvious. I would hazard that the crux of the matter is that two very different concerns were mixed:

  • should the test be run in parallel or not;
  • are there dependencies between tests;

One could want to have sequential tests in the absence of actual dependencies but simply, for instance, to avoid race conditions. Currently, one has to either use "after" or renounce the ability to filter.

Constraint

Though ideally the filtering behaviour should be controlled by a specific option and not through the Sequential / Parallel nature of the tests, I couldn't find a way to do it without breaking the current API which I think should be avoided at all costs. Hence the addition of a new constructor for ExecutionMode.

I'm not 100% sold on my own proposal, because (a) "filterableSequentialTestGroup" is certainly descriptive but it's a bit too long a name (b) it doesn't clearly separate two very different concerns (c) it leads to some annoying repetition in code (see the changes in Tast/Run.hs.

However, it works, changes are little, intent is clear, and it fixes an issue that was raised several times (see also #411).

Considering this issue is rather blocking for me currently, I'm more than willing to apply any requested changes or explore any other direction to have sequential tests be filterable.

@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Jul 3, 2025

@martijnbastiaan may I ask you to review this as the original author of sequential test groups?

@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Jul 3, 2025

@Raveline I'd like to wait a little bit hoping for someone to come up with a more elegant solutions, but that's not too bad. Luckily ExecutionMode is not exported, so this is not a breaking change.

If I forget about this PR, please ping me in a week from now.

@martijnbastiaan
Copy link
Copy Markdown
Contributor

You're right, those two concerns did get mixed.

One could want to have sequential tests in the absence of actual dependencies but simply, for instance, to avoid race conditions.

I think the name nonParallelTestGroup or anyOrderTestGroup would probably be better in that case. This leaves the door open for a test order randomization to detect implicit/accidental test dependencies. The name filterableSequentialTestGroup implies that they really should run in order. What do you think @Bodigrim @Raveline?

@martijnbastiaan
Copy link
Copy Markdown
Contributor

I wonder if this models what we want and sets us up for sensible naming?

data ExecutionMode = Dependent | NonDependent ExecutionOrder
data ExecutionOrder = NoOrder | AnyOrder | InOrder

-- testGroup          => NonDependent NoOrder
-- anyOrderTestGroup  => NonDependent AnyOrder
-- inOrderTestGroup   => NonDependent InOrder  (renamed from `filterableSequentialTestGroup`)
-- dependentTestGroup => Dependent             (renamed from `sequentialTestGroup`)
Name Filterable Parallelizable Sequential
NonDependent NoOrder X X
NonDependent AnyOrder X
NonDependent InOrder X X
Dependent X

I'm not asking for this to happen in this PR, but I'm curious to hear your thoughts.

@Raveline
Copy link
Copy Markdown
Contributor Author

Raveline commented Jul 5, 2025

@martijnbastiaan : I didn't think about this notion of order, but you are right, it is connected to the notion of filterable. If @Bodigrim is ok with the model you proposed, I'll be more than happy to try my hand at implementing it (minus the renaming of sequentialTestGroup, which I think we should keep as is for backwards compatibility reasons).

@martijnbastiaan
Copy link
Copy Markdown
Contributor

Yeah, just blindly renaming existing functions is a no-go, agreed. I'd be in favor of deprecating it to prevent misunderstandings like #443, but in the end that's up to @Bodigrim. I'll get to reviewing the PR properly once we decide what to do.

@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Jul 5, 2025

I'm fine with deprecating sequentialTestGroup and introducing dependentTestGroup instead.

Given that there is no anyOrderTestGroup at the moment, I'd use only two options data ExecutionOrder = NoSpecificOrder | SequentialOrder. Although I'm really bad with naming, so keen to hear what others think about it. CC @andreasabel @VictorCMiraldo.

@andreasabel
Copy link
Copy Markdown
Collaborator

@martijnbastiaan wrote:

data ExecutionOrder = NoOrder | AnyOrder | InOrder

A priori, I would not understand the difference between NoOrder and AnyOrder. Linguistically, "no (particular) order" and "any order" seem to say the same thing.
@Bodigrim wrote:

data ExecutionOrder = NoSpecificOrder | SequentialOrder

This is linguistically clear.

@martijnbastiaan
Copy link
Copy Markdown
Contributor

Agreed, "no order" and "any order" are linguistically the same. My 2ct would be that I'd much rather have:

data ExecutionMode = Dependent | NonDependent Parallel
data Parallel = Parallel | NonParallel

As mentioned before, this leaves the door open for test order randomization. I doubt anyone really needs sequential execution for non-dependent test cases.

@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Jul 7, 2025

Could "NonDependent" poissbly be "Independent"?..

Anyway, we are not going to expose these data types, so naming can be adjusted later. I'm roughly on board with the plan.

@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Jul 8, 2025

One thing we need to spell out in the documentation: all the notion of sequencing / depending is just a hint to the default TestManager. Other test managers (such as tasty-rerun) may and (unfortunately) will ignore the additional semantics.

@Raveline
Copy link
Copy Markdown
Contributor Author

Where would you put the comment explaining this, @Bodigrim ? On the documentation for Ingredients, or in the functions declaring test groups ?

@Bodigrim
Copy link
Copy Markdown
Collaborator

On the functions please.

-- order, all dependencies will be run (overriding filter).
-- For parallel execution, see 'testGroup'.
--
-- Note that this is will only work when used with a `TestManager`. If you use
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"with the default TestManager"
(everything is a TestManager, launchTestTree is the default one)

@Raveline Raveline force-pushed the add-filterable-sequential-test-groups branch from ac2a884 to a40a635 Compare July 12, 2025 05:52
Copy link
Copy Markdown
Collaborator

@Bodigrim Bodigrim left a comment

Choose a reason for hiding this comment

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

@martijnbastiaan could you please review?

sequence trees
Sequential depType ->
snd <$> mapAccumM (goSeqGroup depType) mempty trees
(Independent Parallel) -> sequence trees
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Redundant brackets, I think.

--
-- Note that this is will only work when used with the default `TestManager`.
-- If you use another manager, like `tasty-rerun` for instance, sequentiality
-- will be ignored.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"might be possibly ignored", please, here and below.

--
-- @since 1.5
sequentialTestGroup :: TestName -> DependencyType -> [TestTree] -> TestTree
sequentialTestGroup nm depType = setSequential . TestGroup nm . map setParallel
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

So, are we going to deprecate this one and introduce a better name?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well, I didn't want to do it in advance, not knowing if there was a deprecation strategy in place. Just in case, I've added deprecation (and proper renaming in tests) in my last commit.

@Raveline Raveline force-pushed the add-filterable-sequential-test-groups branch from a40a635 to e9c0d44 Compare July 15, 2025 07:47
Copy link
Copy Markdown
Contributor

@martijnbastiaan martijnbastiaan left a comment

Choose a reason for hiding this comment

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

Thanks @Raveline!

Let's not forget to close #443 and #445 after.

Comment on lines +342 to +344
-- | Create a named group of test cases or other groups. Tests are executed in
-- order, all dependencies will be run (overriding filter).
-- For parallel execution, see 'testGroup'.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
-- | Create a named group of test cases or other groups. Tests are executed in
-- order, all dependencies will be run (overriding filter).
-- For parallel execution, see 'testGroup'.
-- | Create a named group of test cases or other groups. Tests are executed in
-- order and each test is considered a dependency of the next one. If a filter
-- is applied, any dependencies are run too, even if they would otherwise not
-- match the filter's criteria.
--
-- For parallel execution, see 'testGroup'. For ordered test execution, but
-- without dependencies, see 'inOrderTestGroup'.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This does not quite resolves #443, I think. What happens if one of sequential tests fails? Does it stop execution of subsequent ones?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I thought that was covered by DependencyType, but after reading it I'm still not really sure what's going on. Do you think this PR should be blocked on that? I'm happy to open a new PR tackling the problem after merging this one -- I feel it's a problem I introduced to begin with.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My understanding is that in a AllSucceed block, you will have the behaviour described by @Bodigrim (but not in an AllFinish one).

I'm not sure there is actually a use-case for this (but I might be lacking imagination !). I think users are more likely to need a "stop at the first failed test" (disregarding any dependency and / or order) flag for the whole runner, which I don't think Tasty offer and would be a neat addition.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do you think this PR should be blocked on that? I'm happy to open a new PR tackling the problem after merging this one -- I feel it's a problem I introduced to begin with.

Sure, no problem.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm happy to open a new PR tackling the problem after merging this one -- I feel it's a problem I introduced to begin with.

@martijnbastiaan just a kind reminder.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It is on my stack, but the stack is big at the moment..

Improve documentation

Co-authored-by: Martijn Bastiaan <[email protected]>
Fix comment

Co-authored-by: ˌbodʲɪˈɡrʲim <[email protected]>
Copy link
Copy Markdown
Collaborator

@andreasabel andreasabel left a comment

Choose a reason for hiding this comment

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

(I just had a brief look at the API and found nothing alienating.)

@Bodigrim Bodigrim merged commit 6cbcdcc into UnkindPartition:master Aug 3, 2025
14 checks passed
@Bodigrim
Copy link
Copy Markdown
Collaborator

Bodigrim commented Aug 3, 2025

Thanks @Raveline!

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.

4 participants