4

Say you have a function like this:

@ray.remote
def remote_function():
    return 1

You maybe can test it like:

def test_remote_function():
    ray.init()
    x=ray.get(remote_function.remote())
    assert x==1

But that means initializing ray without actually needing it (I just want to test the function itself). It does not even have to be async or threaded in my case.

What I do atm is accessing its protected, wrapped function:

def test_remote_function():
    assert remote_function._function() == 1

but that feels hacky and the linter disobeys me for it :)

What I'd like is a pytest fixture like so:

def test_remote_function(ray):
    x=ray.get(remote_function.remote())
    assert x==1

or

def test_remote_function(ray_sync):
    x=ray.get(remote_function.remote())
    assert x==1

to explicitely make it sync (not use ray actually).

I've seen that ray's internal tests have some sort of pytest fixtures, but not exposed, I guess.

Does anyone know a better way?

tteneder
  • 321
  • 2
  • 8
  • 2
    Why not initialize Ray in your test? Is the reason to avoid the overhead from calling `ray.init()`? A couple suggestions. First, you can call `ray.init(num_cpus=1)` to avoid starting too many unnecessary worker processes. Second, you can define a module-level pytest fixture that initializes Ray once so that you don't initialize Ray for every single test. You can also add `ray.shutdown()` to the fixture to shutdown Ray when the tests are all over. – Robert Nishihara Feb 19 '20 at 01:51

1 Answers1

6

A solution based on Robert Nishihara's comment:

@pytest.fixture(scope="module")
def ray_fix():
    ray.init(num_cpus=1)
    yield None
    ray.shutdown()

used it like:

def test_remote_function(ray_fix):
    x=ray.get(remote_function.remote())
    assert x==1

This way ray is still used/initialized, but only once per module.

In my case this added ~ 2 seconds total test duration, which is negligible.

Would be great if ray came with a set of default pytest fixtures.

Thanks for the hint!

tteneder
  • 321
  • 2
  • 8
  • a more robust solution is to check the state before commands: `if not ray.is_initialized(): ray.init() ` `if ray.is_initialized(): ray.shutdown()` ` – Glauco Sep 06 '22 at 12:47