@@ -645,3 +645,41 @@ def __eq__(self, other):
645
645
646
646
def __ne__ (self , other ):
647
647
return not self .__eq__ (other )
648
+
649
+
650
+ def pytest_collection_modifyitems (config , items ):
651
+ """
652
+ Rearrange test items so that forked tests come before normal tests within their respective modules.
653
+ Swap the last forked test with the last normal test if necessary.
654
+
655
+ Workaround to unpin pytest. See:
656
+ https://github.com/pytest-dev/pytest/issues/9621,
657
+ https://github.com/pytest-dev/pytest-forked/issues/67, and specifically:
658
+ https://github.com/pytest-dev/pytest-forked/issues/67#issuecomment-1964718720
659
+ """
660
+ module_states = {}
661
+
662
+ for idx in range (len (items )):
663
+ item = items [idx ]
664
+ current_module = item .module .__name__
665
+
666
+ if current_module not in module_states :
667
+ module_states [current_module ] = {"forked" : [], "normal" : []}
668
+
669
+ if "forked" in item .keywords :
670
+ module_states [current_module ]["forked" ].append (idx )
671
+ else :
672
+ module_states [current_module ]["normal" ].append (idx )
673
+
674
+ # Swap the last forked test with the last normal test if necessary
675
+ for states in module_states .values ():
676
+ if states ["forked" ] and states ["normal" ]:
677
+ last_forked_idx = states ["forked" ][- 1 ]
678
+ last_normal_idx = states ["normal" ][- 1 ]
679
+
680
+ if last_forked_idx > last_normal_idx :
681
+ # Swap the items
682
+ items [last_forked_idx ], items [last_normal_idx ] = (
683
+ items [last_normal_idx ],
684
+ items [last_forked_idx ],
685
+ )
0 commit comments