Modified: trunk/Tools/ChangeLog (276511 => 276512)
--- trunk/Tools/ChangeLog 2021-04-23 19:21:24 UTC (rev 276511)
+++ trunk/Tools/ChangeLog 2021-04-23 19:34:35 UTC (rev 276512)
@@ -1,3 +1,25 @@
+2021-04-23 Sam Sneddon <gsnedd...@apple.com>
+
+ Add a conftest.py to run existing webkitpy tests in pytest
+ https://bugs.webkit.org/show_bug.cgi?id=224687
+
+ Reviewed by Jonathan Bedard.
+
+ * Scripts/webkitpy/common/system/executive_unittest.py:
+ (ExecutiveTest.serial_test_run_in_parallel): Deal with the fact that pytest
+ running the tests might be not be the same version as the autoinstalled version,
+ and not API compatible.
+ * Scripts/webkitpy/conftest.py: Added.
+ (pytest_configure): Define the markers the plugins in conftest use
+ (pytest_addoption): Add --run-integration to allow them to be disabled by default.
+ (pytest_pycollect_makeitem): Rename serial/integration tests so pytest finds them.
+ (pytest_collection_modifyitems): Mark tests as skipped when needed per the above.
+ * Scripts/webkitpy/pytest.ini: Added.
+ * Scripts/webkitpy/test/main_unittest.py:
+ (TestStubs): Stop these from being picked up by pytest as tests.
+ * Scripts/webkitpy/test/markers.py: Fix this so pytest is technically optional,
+ even though it is always present because of the autoinstalled copy.
+
2021-04-23 Aakash Jain <aakash_j...@apple.com>
Make report-non-inclusive-language ignore .db files
Modified: trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py (276511 => 276512)
--- trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py 2021-04-23 19:21:24 UTC (rev 276511)
+++ trunk/Tools/Scripts/webkitpy/common/system/executive_unittest.py 2021-04-23 19:34:35 UTC (rev 276512)
@@ -250,9 +250,19 @@
cmd_line = [sys.executable, '-c', 'import time; time.sleep(%f); print("hello")' % DELAY_SECS]
cwd = os.getcwd()
commands = [tuple([cmd_line, cwd])] * NUM_PROCESSES
- start = time.time()
- command_outputs = Executive().run_in_parallel(commands, processes=NUM_PROCESSES)
- done = time.time()
+
+ try:
+ # we overwrite __main__ to be this to avoid any issues with
+ # multiprocessing's spawning caused by multiple versions of pytest on
+ # sys.path
+ old_main = sys.modules["__main__"]
+ sys.modules["__main__"] = sys.modules[__name__]
+ start = time.time()
+ command_outputs = Executive().run_in_parallel(commands, processes=NUM_PROCESSES)
+ done = time.time()
+ finally:
+ sys.modules["__main__"] = old_main
+
self.assertTrue(done - start < NUM_PROCESSES * DELAY_SECS)
self.assertEqual([output[1] for output in command_outputs], [b'hello\n'] * NUM_PROCESSES)
self.assertEqual([], multiprocessing.active_children())
Added: trunk/Tools/Scripts/webkitpy/conftest.py (0 => 276512)
--- trunk/Tools/Scripts/webkitpy/conftest.py (rev 0)
+++ trunk/Tools/Scripts/webkitpy/conftest.py 2021-04-23 19:34:35 UTC (rev 276512)
@@ -0,0 +1,110 @@
+# Copyright (C) 2021 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import warnings
+import types
+import sys
+
+import pytest
+
+
+def pytest_configure(config):
+ config.addinivalue_line("markers", "serial: tests that must be run in serial")
+ config.addinivalue_line("markers", "integration: integration tests")
+
+
+def pytest_addoption(parser):
+ parser.addoption(
+ "--run-integration",
+ action=""
+ default=False,
+ help="run integration tests",
+ )
+
+
+@pytest.hookimpl(tryfirst=True)
+def pytest_pycollect_makeitem(collector, name, obj):
+ try:
+ ut = sys.modules["unittest"]
+ if not issubclass(obj, ut.TestCase):
+ return None
+ except Exception:
+ return None
+
+ if getattr(obj, "__pytest_no_rewrite__", False):
+ return None
+
+ for attr_name in set(dir(obj)):
+ serial = False
+ integration = False
+ if attr_name.startswith("serial_integration_test_"):
+ serial = True
+ integration = True
+ elif attr_name.startswith("serial_test_"):
+ serial = True
+ elif attr_name.startswith("integration_test_"):
+ integration = True
+ else:
+ continue
+
+ method = getattr(obj, attr_name)
+ if not callable(method):
+ continue
+
+ new_attr_name = "test_" + attr_name
+
+ existing_attr = getattr(obj, new_attr_name, None)
+ if existing_attr:
+ if method != existing_attr:
+ warnings.warn(
+ "attribute %r already defined on %r; %r might hide %r"
+ % (new_attr_name, obj, method, existing_attr)
+ )
+
+ if sys.version_info < (3,) and isinstance(method, types.MethodType):
+ method = method.im_func
+
+ if serial:
+ method = pytest.mark.serial(method)
+
+ if integration:
+ method = pytest.mark.integration(method)
+
+ setattr(obj, new_attr_name, method)
+
+ return None
+
+
+def pytest_collection_modifyitems(config, items):
+ if hasattr(config, "workerinput"):
+ skip_serial = pytest.mark.skip(reason="cannot run in parallel")
+ for item in items:
+ if "serial" in item.keywords:
+ item.add_marker(skip_serial)
+
+ if not config.getoption("--run-integration"):
+ skip_integration = pytest.mark.skip(
+ reason="need --run-integration option to run"
+ )
+ for item in items:
+ if "integration" in item.keywords:
+ item.add_marker(skip_integration)
Added: trunk/Tools/Scripts/webkitpy/pytest.ini (0 => 276512)
--- trunk/Tools/Scripts/webkitpy/pytest.ini (rev 0)
+++ trunk/Tools/Scripts/webkitpy/pytest.ini 2021-04-23 19:34:35 UTC (rev 276512)
@@ -0,0 +1,14 @@
+[pytest]
+python_files=*_unittest.py *_integrationtest.py
+xfail_strict=true
+addopts = -rfEX --strict-markers -k 'not scm_unittest'
+
+filterwarnings =
+ ignore:invalid escape sequence.*:DeprecationWarning
+ ignore:Please use assert.* instead.:DeprecationWarning
+ ignore:The 'warn' method is deprecated, use 'warning' instead:DeprecationWarning
+ ignore:cannot collect test class 'Test[^']*' because it has a __init__ constructor:pytest.PytestCollectionWarning
+ ignore:the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses:DeprecationWarning
+ ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.[0-9]+ it will stop working:DeprecationWarning
+ ignore:The readPlist function is deprecated, use load\(\) instead:DeprecationWarning
+ ignore:inspect.getargspec\(\) is deprecated since Python 3.0, use inspect.signature\(\) or inspect.getfullargspec\(\):DeprecationWarning
Modified: trunk/Tools/Scripts/webkitpy/test/main_unittest.py (276511 => 276512)
--- trunk/Tools/Scripts/webkitpy/test/main_unittest.py 2021-04-23 19:21:24 UTC (rev 276511)
+++ trunk/Tools/Scripts/webkitpy/test/main_unittest.py 2021-04-23 19:34:35 UTC (rev 276512)
@@ -38,6 +38,8 @@
class TestStubs(unittest.TestCase):
+ __pytest_no_rewrite__ = True
+
def test_empty(self):
pass
Modified: trunk/Tools/Scripts/webkitpy/test/markers.py (276511 => 276512)
--- trunk/Tools/Scripts/webkitpy/test/markers.py 2021-04-23 19:21:24 UTC (rev 276511)
+++ trunk/Tools/Scripts/webkitpy/test/markers.py 2021-04-23 19:34:35 UTC (rev 276512)
@@ -22,7 +22,12 @@
import unittest
+try:
+ import pytest
+except ImportError:
+ pass
+
def xfail(*args, **kwargs):
"""a pytest.mark.xfail-like wrapper for unittest.expectedFailure