Skip to content

Commit

Permalink
[py] Lay groundwork for running large tests with python
Browse files Browse the repository at this point in the history
Turns out we need a custom runner. Implementing this as a macro that
generates the runner for us.
  • Loading branch information
shs96c committed Nov 11, 2019
1 parent 5a20d44 commit 23a7d77
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 13 deletions.
1 change: 1 addition & 0 deletions common/src/web/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ filegroup(
"//dotnet/test/common:__pkg__",
"//java/client/test/org/openqa/selenium/environment:__pkg__",
"//javascript/node/selenium-webdriver:__pkg__",
"//py:__pkg__",
],
)
1 change: 1 addition & 0 deletions java/server/src/org/openqa/selenium/grid/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ java_binary(
],
visibility = [
"//:__pkg__",
"//py:__pkg__",
],
)

Expand Down
98 changes: 86 additions & 12 deletions py/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
load("//py:defs.bzl", "pytest_test")
load("//:copy_file.bzl", "copy_file")

genrule(
copy_file(
name = "get-attribute",
srcs = ["//javascript/webdriver/atoms:get-attribute.js"],
outs = ["selenium/webdriver/remote/getAttribute.js"],
cmd = "cp $< $@",
src = "//javascript/webdriver/atoms:get-attribute.js",
out = "selenium/webdriver/remote/getAttribute.js",
)

genrule(
copy_file(
name = "is-displayed",
srcs = ["//javascript/atoms/fragments:is-displayed.js"],
outs = ["selenium/webdriver/remote/isDisplayed.js"],
cmd = "cp $< $@",
src = "//javascript/atoms/fragments:is-displayed.js",
out = "selenium/webdriver/remote/isDisplayed.js",
)

copy_file(
name = "firefox-driver-prefs",
src = "//third_party/js/selenium:webdriver_json",
out = "selenium/webdriver/firefox/webdriver_prefs.json",
)

py_library(
name = "main",
srcs = glob(["selenium/**/*.py"]),
data = [
":firefox-driver-prefs",
":get-attribute",
":is-displayed",
],
Expand All @@ -28,18 +35,85 @@ py_library(
visibility = ["//visibility:public"],
)

py_test(
py_library(
name = "init-tree",
testonly = True,
srcs = [
"conftest.py",
"test/__init__.py",
"test/selenium/__init__.py",
"test/selenium/webdriver/__init__.py",
"test/selenium/webdriver/chrome/__init__.py",
"test/selenium/webdriver/common/__init__.py",
"test/selenium/webdriver/common/conftest.py",
"test/selenium/webdriver/common/network.py",
"test/selenium/webdriver/common/webserver.py",
"test/selenium/webdriver/firefox/__init__.py",
"test/selenium/webdriver/firefox/conftest.py",
"test/selenium/webdriver/marionette/__init__.py",
"test/selenium/webdriver/marionette/conftest.py",
"test/selenium/webdriver/safari/conftest.py",
"test/selenium/webdriver/support/__init__.py",
"test/selenium/webdriver/support/conftest.py",
],
deps = [
":webserver",
],
data = [
"setup.cfg",
],
imports = ["."],
)

pytest_test(
name = "unit",
size = "small",
python_version = "PY2",
args = [
"-n=auto",
],
srcs = glob([
"test/unit/**/*.py",
]) + [ "test/runner/run_pytest.py" ],
main = "test/runner/run_pytest.py",
]),
deps = [
":init-tree",
":main",
"//third_party/py:pytest",
],
legacy_create_init = False,
)

py_library(
name = "webserver",
testonly = True,
srcs = [
"test/selenium/webdriver/common/network.py",
"test/selenium/webdriver/common/webserver.py",
],
data = [
"//common/src/web",
"//java/server/src/org/openqa/selenium/grid:selenium_server_deploy.jar",
],
deps = [],
)

pytest_test(
name = "large-tests",
size = "large",
srcs = glob([
"test/selenium/webdriver/common/**/*.py",
"test/selenium/webdriver/support/**/*.py",
]),
args = ["--driver=Firefox"],
python_version = "PY2",
tags = [
"no-sandbox",
],
deps = [
":init-tree",
":main",
":webserver",
"//third_party/py:pytest",
]
)

py_binary(
Expand Down
2 changes: 2 additions & 0 deletions py/defs.bzl
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
load("//py:import.bzl", _py_import = "py_import")
load("//py/private:pytest.bzl", _pytest_test = "pytest_test")

py_import = _py_import
pytest_test = _pytest_test
Empty file added py/private/BUILD.bazel
Empty file.
76 changes: 76 additions & 0 deletions py/private/pytest.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
load("@rules_python//python:defs.bzl", "PyInfo", "PyRuntimeInfo", "py_test")

def _stringify(paths):
return "[%s]" % (", ".join(["\"%s\"" % path for path in paths]))

def _pytest_runner_impl(ctx):
if len(ctx.attr.srcs) == 0:
fail("No test files specified.")

runner = ctx.actions.declare_file(ctx.attr.name)
ctx.actions.write(
runner,
"""
if __name__ == "__main__":
import sys
import pytest
args = sys.argv[1:] + ["-ra", "-s", "--instafail"] + %s + %s
sys.exit(pytest.main(args))""" % (_stringify(ctx.attr.args), _stringify([src.path for src in ctx.files.srcs])),
is_executable = True)

return [
DefaultInfo(
files = depset([runner]),
executable = runner,
),
]

_pytest_runner = rule(
_pytest_runner_impl,
attrs = {
"srcs": attr.label_list(
allow_files = [".py"],
),
"deps": attr.label_list(
providers = [
PyInfo,
],
),
"args": attr.string_list(
default = [],
),
"python_version": attr.string(
values = ["PY2", "PY3"],
default = "PY3",
),
},
toolchains = [
"@rules_python//python:toolchain_type",
]
)

def pytest_test(name, srcs, deps = None, args = None, python_version = None, **kwargs):
runner_target = "%s-runner.py" % name

_pytest_runner(
name = runner_target,
testonly = True,
srcs = srcs,
deps = deps,
args = args,
python_version = python_version,
)

py_test(
name = name,
python_version = python_version,
srcs = srcs + [runner_target],
deps = deps,
main = runner_target,
legacy_create_init = False,
imports = ["."],
**kwargs,
)

2 changes: 1 addition & 1 deletion py/test/runner/run_pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
with open("pytest.ini", "w") as ini_file:
ini_file.write("[pytest]\n")
ini_file.write("addopts = -r=a\n")
ini_file.write("rootdir = py")
ini_file.write("rootdir = py\n")
ini_file.write("python_files = test_*.py *_tests.py\n")

raise SystemExit(pytest.main())
1 change: 1 addition & 0 deletions third_party/js/selenium/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ copy_file(
"//dotnet/src/webdriver:__pkg__",
"//java/client/src/org/openqa/selenium/firefox:__pkg__",
"//java/client/test/org/openqa/selenium/environment:__pkg__",
"//py:__pkg__",
],
)
56 changes: 56 additions & 0 deletions third_party/py/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
load("//py:defs.bzl", "py_import")

py_import(
name = "apipkg",
wheel = "apipkg-1.4-py2.py3-none-any.whl",
)

py_import(
name = "execnet",
wheel = "execnet-1.4.1-py2.py3-none-any.whl",
deps = [
":apipkg",
],
)

py_import(
name = "mock",
wheel = "mock-2.0.0-py2.py3-none-any.whl",
deps = [
":pbr",
":six",
]
)

py_import(
name = "pbr",
wheel = "pbr-2.0.0-py2.py3-none-any.whl",
)

py_import(
name = "py",
wheel = "py-1.4.32-py2.py3-none-any.whl",
Expand All @@ -10,7 +37,10 @@ py_import(
wheel = "pytest-3.0.3-py2.py3-none-any.whl",
deps = [
":py",
":pytest-instafail",
":pytest-mock",
# ":pytest-timeout",
":pytest-xdist",
],
visibility = [
"//visibility:public",
Expand All @@ -20,6 +50,32 @@ py_import(
py_import(
name = "pytest-mock",
wheel = "pytest_mock-1.5.0-py2.py3-none-any.whl",
deps = [
"mock",
],
)

py_import(
name = "pytest-instafail",
wheel = "pytest-instafail-0.3.0.tar.gz",
)

py_import(
name = "pytest-timeout",
wheel = "pytest_timeout-1.2.0-py2.py3-none-any.whl",
)

py_import(
name = "pytest-xdist",
wheel = "pytest-xdist-1.15.0.tar.gz",
deps = [
":execnet",
],
)

py_import(
name = "six",
wheel = "six-1.11.0.tar.gz",
)

py_import(
Expand Down
Binary file not shown.

0 comments on commit 23a7d77

Please sign in to comment.