Skip to content

Commit 491497f

Browse files
JeanChristopheMorinPersofabalnca45
authored
Introducing "testing" object (#1852)
Signed-off-by: Fabrice Macagno <[email protected]> Signed-off-by: Nathan Cheung <[email protected]> Signed-off-by: Jean-Christophe Morin <[email protected]> Co-authored-by: Fabrice Macagno <[email protected]> Co-authored-by: Nathan Cheung <[email protected]>
1 parent 84c827d commit 491497f

File tree

11 files changed

+200
-3
lines changed

11 files changed

+200
-3
lines changed

docs/source/package_commands.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,19 @@ Following is a list of the objects and functions available.
707707
if test.name == "unit":
708708
info("My unit test is about to run yay")
709709
710+
.. py:attribute:: testing
711+
:type: bool
712+
713+
This boolean variable is ``True`` if a test is occurring (typically done via the :ref:`rez-test` tool),
714+
and ``False`` otherwise.
715+
716+
A package can use this variable to set environment variables that are only relevant during test execution.
717+
718+
.. code-block:: python
719+
720+
if testing:
721+
env.FOO_TEST_DATA_PATH = "{root}/tests/data"
722+
710723
.. py:attribute:: this
711724
712725
The ``this`` object represents the current package. The following attributes are most commonly used

docs/source/package_definition.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ is ``True``:
290290
* **context**: the :class:`~rez.resolved_context.ResolvedContext` instance this package belongs to;
291291
* **system**: see :attr:`system`;
292292
* **building**: see :attr:`building`;
293+
* **testing**: see :attr:`testing`;
293294
* **request**: see :attr:`request`;
294295
* **implicits**: see :attr:`implicits`.
295296

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from build_util import build_directory_recurse
2+
import os.path
3+
4+
5+
def build(source_path, build_path, install_path, targets):
6+
7+
if "install" not in (targets or []):
8+
install_path = None
9+
10+
build_directory_recurse(src_dir="testing_obj",
11+
dest_dir=os.path.join("python", "testing_obj"),
12+
source_path=source_path,
13+
build_path=build_path,
14+
install_path=install_path)
15+
16+
17+
if __name__ == '__main__':
18+
import os, sys
19+
build(
20+
source_path=os.environ['REZ_BUILD_SOURCE_PATH'],
21+
build_path=os.environ['REZ_BUILD_PATH'],
22+
install_path=os.environ['REZ_BUILD_INSTALL_PATH'],
23+
targets=sys.argv[1:]
24+
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name = 'testing obj'
2+
version = '1.0.0'
3+
authors = ["Dan Flashes"]
4+
5+
description = "testing the 'testing' attribute available during rez test"
6+
7+
@late()
8+
def requires():
9+
if in_context() and testing:
10+
return ["floob"]
11+
return ["hello"]
12+
13+
private_build_requires = ["build_util", "python"]
14+
15+
def commands():
16+
env.PYTHONPATH.append('{root}/python')
17+
if testing:
18+
env.CAR_IDEA = "STURDY STEERING WHEEL"
19+
else:
20+
env.SKIP_LUNCH = "False"
21+
22+
build_command = 'python {root}/build.py {install}'
23+
24+
tests = {
25+
"command_as_string_success": {
26+
"command": "exit 0"
27+
},
28+
"command_as_string_fail": {
29+
"command": "exit 1"
30+
},
31+
"check_car_ideas": {
32+
"command": ["python", "-c", "import os; assert os.environ.get('CAR_IDEA') == 'STURDY STEERING WHEEL'"],
33+
"requires": ["python"]
34+
},
35+
"move_meeting_to_noon": {
36+
# We want this test to fail. SKIP_LUNCH should not be set.
37+
# TODO: We should not test for failures here. Testing failures, str vs lsit commands, etc
38+
# should we tested separately.
39+
"command": ["python", "-c", "import os; assert os.environ.get('SKIP_LUNCH') is not None"],
40+
"requires": ["python"]
41+
}
42+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def hello():
2+
return "This shirt was $150 out the door and the pattern's not that complicated"

src/rez/package_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ def _get_context(self, requires, quiet=False):
603603
package_paths=self.package_paths,
604604
buf=(f if quiet else None),
605605
timestamp=self.timestamp,
606+
testing=True,
606607
**self.context_kwargs
607608
)
608609

src/rez/resolved_context.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def __call__(self, state):
163163
return SolverCallbackReturn.keep_going, ''
164164

165165
def __init__(self, package_requests, verbosity=0, timestamp=None,
166-
building=False, caching=None, package_paths=None,
166+
building=False, testing=False, caching=None, package_paths=None,
167167
package_filter=None, package_orderers=None, max_fails=-1,
168168
add_implicit_packages=True, time_limit=-1, callback=None,
169169
package_load_callback=None, buf=None, suppress_passive=False,
@@ -176,6 +176,7 @@ def __init__(self, package_requests, verbosity=0, timestamp=None,
176176
timestamp (float): Ignore packages released after this epoch time. Packages
177177
released at exactly this time will not be ignored.
178178
building (bool): True if we're resolving for a build.
179+
testing (bool): True if we're resolving for a test (rez-test).
179180
caching (bool): If True, cache(s) may be used to speed the resolve. If
180181
False, caches will not be used. If None, :data:`resolve_caching`
181182
is used.
@@ -214,6 +215,7 @@ def __init__(self, package_requests, verbosity=0, timestamp=None,
214215
self.requested_timestamp = timestamp
215216
self.timestamp = self.requested_timestamp or int(time.time())
216217
self.building = building
218+
self.testing = testing
217219
self.implicit_packages = []
218220
self.caching = config.resolve_caching if caching is None else caching
219221
self.verbosity = verbosity
@@ -1553,6 +1555,7 @@ def _add(field):
15531555
timestamp=self.timestamp,
15541556
requested_timestamp=self.requested_timestamp,
15551557
building=self.building,
1558+
testing=self.testing,
15561559
caching=self.caching,
15571560
implicit_packages=list(map(str, self.implicit_packages)),
15581561
package_requests=list(map(str, self._package_requests)),
@@ -1627,6 +1630,7 @@ def _print_version(value):
16271630

16281631
r.timestamp = d["timestamp"]
16291632
r.building = d["building"]
1633+
r.testing = d["testing"]
16301634
r.caching = d["caching"]
16311635
r.implicit_packages = [PackageRequest(x) for x in d["implicit_packages"]]
16321636
r._package_requests = [PackageRequest(x) for x in d["package_requests"]]
@@ -1959,6 +1963,7 @@ def _get_pre_resolve_bindings(self):
19591963
self.pre_resolve_bindings = {
19601964
"system": system,
19611965
"building": self.building,
1966+
"testing": self.testing,
19621967
"request": RequirementsBinding(self._package_requests),
19631968
"implicits": RequirementsBinding(self.implicit_packages),
19641969
"intersects": intersects

src/rez/resolver.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ class Resolver(object):
3737
"""
3838
def __init__(self, context, package_requests, package_paths, package_filter=None,
3939
package_orderers=None, timestamp=0, callback=None, building=False,
40-
verbosity=False, buf=None, package_load_callback=None, caching=True,
41-
suppress_passive=False, print_stats=False):
40+
testing=False, verbosity=False, buf=None, package_load_callback=None,
41+
caching=True, suppress_passive=False, print_stats=False):
4242
"""Create a Resolver.
4343
4444
Args:
@@ -52,6 +52,7 @@ def __init__(self, context, package_requests, package_paths, package_filter=None
5252
prior to each package being loaded. It is passed a single
5353
`Package` object.
5454
building: True if we're resolving for a build.
55+
testing: True if we're resolving for a rez (rez-test).
5556
caching: If True, cache(s) may be used to speed the resolve. If
5657
False, caches will not be used.
5758
print_stats (bool): If true, print advanced solver stats at the end.
@@ -64,6 +65,7 @@ def __init__(self, context, package_requests, package_paths, package_filter=None
6465
self.package_orderers = package_orderers
6566
self.package_load_callback = package_load_callback
6667
self.building = building
68+
self.testing = testing
6769
self.verbosity = verbosity
6870
self.caching = caching
6971
self.buf = buf
@@ -384,6 +386,7 @@ def _memcache_key(self, timestamped=False):
384386
self.package_filter_hash,
385387
self.package_orderers_hash,
386388
self.building,
389+
self.testing,
387390
config.prune_failed_graph]
388391

389392
if timestamped and self.timestamp:

src/rez/serialise.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def _load_file(filepath, format_, update_data_callback, original_filepath=None):
184184
# Default variables to avoid not-defined errors in early-bound attribs
185185
default_objects = {
186186
"building": False,
187+
"testing": False,
187188
"build_variant_index": 0,
188189
"build_variant_requires": []
189190
}

src/rez/tests/test_context.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,26 @@ def test_execute_command(self):
7171
stdout = stdout.strip()
7272
self.assertEqual(stdout, "Hello Rez World!")
7373

74+
def test_resolved_packages_testing_environ(self):
75+
"""Test resolving packages within a testing environment behaves correctly"""
76+
packages_path = self.data_path("builds", "packages")
77+
78+
# Note how we use testing=True
79+
r = ResolvedContext(["testing_obj"], testing=True, package_paths=[packages_path])
80+
resolvedPackages = [x.qualified_package_name for x in r.resolved_packages]
81+
self.assertEqual(resolvedPackages, ["floob", "testing_obj-1.0.0"])
82+
83+
def test_execute_command_testing_environ(self):
84+
"""Test that execute_command properly sets test specific environ dict"""
85+
self.inject_python_repo()
86+
packages_path = self.data_path("builds", "packages")
87+
r = ResolvedContext(
88+
["testing_obj", "python"],
89+
testing=True,
90+
package_paths=[packages_path] + self.settings["packages_path"]
91+
)
92+
self.assertEqual(r.get_environ().get("CAR_IDEA"), "STURDY STEERING WHEEL")
93+
7494
def test_execute_command_environ(self):
7595
"""Test that execute_command properly sets environ dict."""
7696
self.inject_python_repo()

0 commit comments

Comments
 (0)