unittests now use a mock ray implementation#127
Conversation
For the unit tests, a mock implementation of 'ray' is introduced, as a replacement for the now-obsolete local mode of the actual 'ray' library.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdds a lightweight mock Ray package for tests: a core mock API with serialization and remote dispatch, an ActorPool utility, and test wiring to use the mock instead of initializing real Ray. ChangesMock Ray Testing Framework
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/conftest.py (1)
27-30: ⚡ Quick winAdd a fail-fast check to ensure the mock
raypackage is importedWithin this repo, only
tests/conftest.pyimportsray, so normal pytest collection shouldn’t preload the real Ray before the mock-path insertion. Still, adding the guard prevents silent fallback ifraywas imported earlier by external code/plugins, keeping the PR’s test wiring robust.Suggested guard
_TESTS_DIR = os.path.dirname(os.path.abspath(__file__)) -sys.path.insert(0, os.path.join(_TESTS_DIR, "_mock-site-packages")) +_MOCK_SITE_PACKAGES = os.path.join(_TESTS_DIR, "_mock-site-packages") +sys.path.insert(0, _MOCK_SITE_PACKAGES) import ray # noqa: E402 + +if not os.path.realpath(getattr(ray, "__file__", "")).startswith(os.path.realpath(_MOCK_SITE_PACKAGES)): + raise RuntimeError(f"Expected mock ray from {_MOCK_SITE_PACKAGES}, got {getattr(ray, '__file__', None)}")🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/conftest.py` around lines 27 - 30, After inserting the mock path into sys.path, ensure the imported ray is the mock by verifying its module origin; in tests/conftest.py after sys.path.insert(...) and the import ray statement, check ray.__file__ or importlib.util.find_spec("ray").origin contains "_mock-site-packages" or the _TESTS_DIR path and if not raise a clear ImportError (or call pytest.exit) so the test run fails fast when the real Ray is loaded instead of the mock.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/_mock-site-packages/ray/util.py`:
- Around line 40-76: The mock eagerly materializes results but should preserve
Ray semantics by returning iterators: change ActorPool.map to be a generator
that yields each processed result lazily (for each object compute i_actor =
i_obj % len(self.__actors), call fn(actor, obj) and yield get(...) immediately
rather than appending to a list), and change map_unordered to return a generator
that yields results in a shuffled order without precomputing all outputs (e.g.,
determine the sequence of actor/object pairs, shuffle the sequence using
self.__generator.shuffle, then iterate that shuffled sequence yielding
get(fn(actor,obj)) for each); update usages of map/map_unordered to expect
iterators instead of lists and keep references to __actors, __generator, fn, and
get to locate the implementation.
---
Nitpick comments:
In `@tests/conftest.py`:
- Around line 27-30: After inserting the mock path into sys.path, ensure the
imported ray is the mock by verifying its module origin; in tests/conftest.py
after sys.path.insert(...) and the import ray statement, check ray.__file__ or
importlib.util.find_spec("ray").origin contains "_mock-site-packages" or the
_TESTS_DIR path and if not raise a clear ImportError (or call pytest.exit) so
the test run fails fast when the real Ray is loaded instead of the mock.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 40afff65-58b3-48f5-a1e0-201d37e01e03
📒 Files selected for processing (4)
tests/_mock-site-packages/ray/__init__.pytests/_mock-site-packages/ray/core.pytests/_mock-site-packages/ray/util.pytests/conftest.py
| def map(self, fn: Callable[[_RemoteInstance, Any], Any], objects: Sequence[Any]) -> list: | ||
| """ | ||
| Pair actors with objects, and for each pair, call `fn(actor, object)`. | ||
|
|
||
| Args: | ||
| fn: The function which specifies how an object is to be used | ||
| with its associated actor. | ||
| objects: A sequence (e.g. list or tuple) of object to be processed | ||
| by the pool of actors. | ||
|
|
||
| Returns: | ||
| Processed counterparts of the objects, as a list of the same length | ||
| as `objects`. | ||
| """ | ||
| num_actors = len(self.__actors) | ||
| result = [] | ||
| for i_obj, obj in enumerate(objects): | ||
| i_actor = i_obj % num_actors | ||
| actor = self.__actors[i_actor] | ||
| result.append(fn(actor, obj)) | ||
| return get(result) | ||
|
|
||
| def map_unordered(self, fn: Callable[[_RemoteInstance, Any], Any], objects: Sequence[Any]) -> list: | ||
| """ | ||
| Like the `map` method, but the results are shuffled. | ||
|
|
||
| The reasoning behind the shuffling is to mimic the fact that | ||
| `map_unordered` of the actual 'ray' library returns the processed | ||
| results in an undeterministic order. | ||
|
|
||
| Also note that, for reproducibility during tests, the shuffling | ||
| depends on a constant random seed, which is stored by class-level | ||
| constant `SEED`. | ||
| """ | ||
| result = self.map(fn, objects) | ||
| self.__generator.shuffle(result) | ||
| return result |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and display the full ActorPool mock implementation
FILE="tests/_mock-site-packages/ray/util.py"
echo "== $FILE =="
nl -ba "$FILE" | sed -n '1,220p'
# Find usages of ActorPool.map/map_unordered in the repo
echo "== rg usages of ActorPool.map / map_unordered =="
rg -n "ActorPool\.map_unordered|ActorPool\.map\(" . || true
# Also search for 'map_unordered(' and 'map(' where it might be called on ActorPool instance variable
echo "== rg for '.map_unordered(' =="
rg -n "\.map_unordered\(" . || true
echo "== rg for '.map(' (narrowed to ActorPool variable patterns) =="
rg -n "\.map\(" . | head -n 200 || trueRepository: nnaisense/evotorch
Length of output: 167
🌐 Web query:
Ray ActorPool.map returns generator iterator return type map_unordered unordered iterator yields results as they complete
💡 Result:
In Ray, both ray.util.ActorPool.map and ray.util.ActorPool.map_unordered return a Python generator iterator [1][2][3]. The key distinction between the two methods lies in the ordering of the returned results [1][2]: - ray.util.ActorPool.map returns an ordered iterator that yields results corresponding to the input list order, as they finish [1]. - ray.util.ActorPool.map_unordered returns an unordered iterator that yields results as they complete [2][4]. Because map_unordered does not enforce any ordering constraints, it can be more efficient than map in scenarios where tasks have variable execution times, as it allows results to be processed as soon as they become available rather than waiting for preceding tasks in the input sequence to complete [2][4]. For both methods, it is important to note that you must iterate over the returned iterator to actually trigger and consume the computation [1][5]. If you simply call the method without iterating, the tasks may not be fully executed or the results may not be retrieved as expected [1].
Citations:
- 1: https://docs.ray.io/en/latest/ray-core/api/doc/ray.util.ActorPool.map.html
- 2: https://docs.ray.io/en/latest/ray-core/api/doc/ray.util.ActorPool.map_unordered.html
- 3: https://docs.ray.io/en/releases-2.35.0/ray-core/actors/actor-utils.html
- 4: https://docs.ray.io/en/latest/_modules/ray/util/actor_pool.html
- 5: https://docs.ray.io/en/releases-2.3.1/ray-core/api/doc/ray.util.ActorPool.html
🌐 Web query:
rAY util ActorPool map_unordered documentation returns generator iterator list
💡 Result:
Ray’s ray.util.ActorPool.map_unordered(...) returns an iterator (a generator object) that yields results “as they finish”, i.e., unordered with respect to the input order. [1] Concretely, the implementation defines an inner get_generator() that does while self.has_next(): yield self.get_next_unordered() and then returns get_generator(); so you can iterate it directly or consume it (e.g., list(pool.map_unordered(...))). [2] The docs for map_unordered describe this as “returning an unordered iterator” whose yielded results are produced as tasks complete, which may be more efficient than ordered map() when some computations take longer. [1]
Citations:
- 1: https://docs.ray.io/en/latest/ray-core/api/doc/ray.util.ActorPool.map_unordered.html
- 2: https://docs.ray.io/en/latest/_modules/ray/util/actor_pool.html
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and display the full ActorPool mock implementation
FILE="tests/_mock-site-packages/ray/util.py"
echo "== $FILE =="
nl -ba "$FILE" | sed -n '1,220p'
# Find usages of ActorPool.map/map_unordered in the repo
echo "== rg usages of ActorPool.map / map_unordered =="
rg -n "ActorPool\.map_unordered|ActorPool\.map\(" . || true
# Also search for 'map_unordered(' and 'map(' where it might be called on ActorPool instance variable
echo "== rg for '.map_unordered(' =="
rg -n "\.map_unordered\(" . || true
echo "== rg for '.map(' (narrowed to ActorPool variable patterns) =="
rg -n "\.map\(" . | head -n 200 || trueRepository: nnaisense/evotorch
Length of output: 167
Preserve Ray iterator semantics in the ActorPool mock.
Ray’s ray.util.ActorPool.map / map_unordered return iterator/generator objects (lazy; results are produced as the iterator is consumed, with map_unordered yielding as tasks complete). This mock eagerly materializes a full list in map, and map_unordered shuffles only after fully realizing the list, so partial iteration / next(...)-style consumption won’t match Ray behavior. https://docs.ray.io/en/latest/ray-core/api/doc/ray.util.ActorPool.map.html https://docs.ray.io/en/latest/ray-core/api/doc/ray.util.ActorPool.map_unordered.html
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/_mock-site-packages/ray/util.py` around lines 40 - 76, The mock eagerly
materializes results but should preserve Ray semantics by returning iterators:
change ActorPool.map to be a generator that yields each processed result lazily
(for each object compute i_actor = i_obj % len(self.__actors), call fn(actor,
obj) and yield get(...) immediately rather than appending to a list), and change
map_unordered to return a generator that yields results in a shuffled order
without precomputing all outputs (e.g., determine the sequence of actor/object
pairs, shuffle the sequence using self.__generator.shuffle, then iterate that
shuffled sequence yielding get(fn(actor,obj)) for each); update usages of
map/map_unordered to expect iterators instead of lists and keep references to
__actors, __generator, fn, and get to locate the implementation.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #127 +/- ##
==========================================
- Coverage 75.43% 75.36% -0.08%
==========================================
Files 59 59
Lines 9556 9556
==========================================
- Hits 7209 7202 -7
- Misses 2347 2354 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
For the unit tests, a mock implementation of
rayis introduced, as a replacement for the now-obsolete local mode of the actualraylibrary.Summary by CodeRabbit
New Features
Tests