-
Notifications
You must be signed in to change notification settings - Fork 231
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
Allow custom scheduler class implementation #89
Conversation
Hi, thanks for the PR! I like the idea; we have prior discussion on how to implement support for customizing test distribution on workers, but alas nobody had the time to implement it yet. I think the solution you are proposing is a good middle ground. Let's see what are other's opinions on this. |
xdist/dsession.py
Outdated
@@ -1,4 +1,5 @@ | |||
import difflib | |||
import importlib |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
importlib
is available only on Python >= 3.1, so unfortunately we can't use it like this. I suggest using __import__
which is available in all Python versions we have to support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I guess I can use __import__
for that case. I thought that pytest
has general workaround for that case, but as I can see it has only specialised methods like import_plugin
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also we should add some documentation for this feature on README
Got it. I'll do that. |
34583ec
to
c5a2275
Compare
this is a nice addition, however we must mark the scheduler api as unstable personally i had a |
Do you mean mark in code or add a notice in README file? |
i think a notice in the readme is a good fit |
Actually, it would be even more native way and would free us from importing classes. @nicoddemus what do you think of adding a hook rather then adding a CLI parameter? |
Wholeheartedly agree! 😁 This makes it easy for plugins to provide a custom scheduler. How about naming it def pytest_xdist_make_scheduler(log, config):
"""Return a scheduler implementation, or None.
""" ( We should document the expected interface, or declare an official interface using the |
Oh in case it wasn't clear, I think the hook should return an instance instead of a class. Implementations should be free to declare any constructor signature and obtain those from the |
Hey @wronglink, thanks for following up! The pytest-2.6 environments failed, probably due to the new way to use hooks. TBH I think we can drop support for pytest-2.6 in the next release and don't worry about it, pytest 2.6.4 was released in Oct 24th, 2014. @RonnyPfannschmidt do you agree? Other than that, there was minor errors in the flakes environment, could please you fix them @wronglink? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also add a new section to the README
, as well as a CHANGELOG
entry.
xdist/newhooks.py
Outdated
|
||
|
||
@pytest.mark.firstresult | ||
def pytest_xdist_make_scheduler(numnodes, log, config): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can drop numnodes
from the hook signature... it can be easily obtained from the config
object.
@nicoddemus I think to add docs as I'm ready to finalise the PR. I'd like to implement something like base scheduler class and clean it interface by getting rid of class EachScheduling:
...
@property
def numnodes(self):
"""Nodes amount in the scheduler."""
return len(self.nodes)
... But I haven't fixed the failing tests, so didn't include that change. |
Sounds good! Do you think we should also create an abstract class using the |
please mark all those apis as provisional, they are supposed to be broken when introducting more formal statemachines |
Ping. 😁 |
whops,. feel free to drop it |
hi strangers! this is cool. i've been following this and the history of the xdist worker scheduling attempts for a little while. are there actionables for this PR? |
Hi there. I'm really sorry I didn't have enough time to make all requested changes for this PR. I'll try to make one more attempt to fix it, but can't give any deadline for this. |
@wronglink no problem at all, we appreciate your efforts here. Would you mind if any of us maintainers pick up from here if we find the time? The PR is nearly ready as it is. |
@nicoddemus for sure, I'll be grateful in that case. BTW I don't mind either someone starts new PR or give access to my fork to keep changes inside one PR. |
d3079a0
to
6200123
Compare
Hello again. I've found some time to continue work. For now, I'm a little bit confused by some part of current scheduler API. I tried to clean up both I ended up with something like this (marked most confusing parts with !): class Scheduler:
# Indicates that all tests are already finished
tests_finished = False
# List of all nodes available for scheduler
nodes = []
# Indicates that tests collection is already finished
# ! need some explanation the difference between this and tests_finished
collection_is_completed = False
# Indicates that scheduller has pending tests. These are tests which have
# not yet been allocated to a chunk for a node to process.
has_pending = False
def add_node(node):
""" Add node to the pool
Called when node is set up and ready
"""
def remove_node(node):
""" Remove node from the pool
Called to clean up nodes when tests are finished or error happens
"""
def add_node_collection(node, ids):
""" Adds tests collection to node.
! don't understand why we add same collection for every node (we also check, that
! each node got same collection) and not simply send it to schedule() method
"""
def mark_test_complete(node, item_index, duration):
""" Mark particular test item as complete
Called when slave reported that test with item_index is complete
"""
def schedule():
""" Initiate schedule of the test collection """ @nicoddemus @RonnyPfannschmidt do you have any comments or suggestions? |
the current collection addition is purely for sanity in future we hope to expand, so different slaves can run different sets of tests (like one folder per slave, one configured backend per slave) it may be necessary to extract a better node concept in future (one of the main reasons why i said to mark those apis provisional is, that we literally have no idea what a good api will be unless we iterate a few time and reflect on what we learn from those iterations) |
a sidenote, the api looks very imperative, the scheduler should be a manager of state that reacts on events - and it may help if the method names reflect those events |
Oh thanks for continuing the work @wronglink!
Just to complement: there have been bugs in the past where nodes ended up with different sets of tests collected, which is problematic because the master sends just the index of the test item to a worker to execute next. @RonnyPfannschmidt I seem to recall there was a reason why we don't send the entire test nodeid (as @wronglink cool that you are cleaning the API, I like the new names so far. I agree that ideally the API would be more reactive like @RonnyPfannschmidt suggested but I understand it's hard for you to find time to work on this feature, so I suggest we try to merge this without too much more change requests. Then we can iterate over it in subsequent PRs, hopefully before publishing it in the next release. |
@nicoddemus we send indexes instead of nodeids because we allow duplicate test id's |
since we do have a structural enhancement and havent declared the api public yet, maybe we should just merge it and iterate on top of it |
after all this pr is good work and puts us in a better spot, even if details may need to cange |
Oh yeah, duplicated ids, thanks.
Agreed, we can iterating on this in other PRs. |
Cool, I'll make another PR to mention this change in CHANGELOG and README.md |
I do -n auto, and one particular test class in my app can't be run in parallel. Does this PR allow me to specify this particular test class to run serially and ignore -n auto? |
@JohnTheodore right, that was one of my purposes. You can look at this gist for inspiration: |
Hi. I've seen several tickets when people need more control over tests scheduling (see #18). I think, it would be much better, if
xdist
would give a a way to implement custom test scheduler class and pass it toDSession
object. I've came up with this:We freeze a schedule interface.
One can have his one scheduler class implementation, available for import.
Python import path should be passed to
xdist
module through optional--dc
command line parameter: