Skip to content
This repository was archived by the owner on May 29, 2024. It is now read-only.

Commit 2f6a094

Browse files
committed
Added tests
1 parent 6ddba5d commit 2f6a094

File tree

10 files changed

+297
-25
lines changed

10 files changed

+297
-25
lines changed

Pipfile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ pylint = "*"
1111
twine = ">=1.11.0"
1212
wheel = ">=0.31.0"
1313
setuptools = ">=39.0.1"
14+
tox = ">=3.0.0"
15+
"flake8" = ">=0.6.1"
16+
tox-pyenv = ">=1.1.0"
17+
invoke = ">=0.23.0"
1418

1519
[requires]
1620
python_version = "3.6"
1721

1822
[scripts]
19-
build = "python setup.py sdist bdist_wheel"
20-
deploy = "twine upload dist/*"
23+
test = "invoke test"
24+
build = "invoke build"
25+
release = "invoke release"

Pipfile.lock

Lines changed: 70 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pytest-parallel/__init__.py renamed to pytest_parallel/__init__.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@
66
import platform
77
import threading
88
import collections
9-
import queue as Queue
109
from multiprocessing import Manager, Process
1110

11+
__version__ = '0.0.1'
12+
13+
try:
14+
# py3
15+
import queue as Queue
16+
except Exception:
17+
# py2
18+
import Queue as Queue
19+
1220

1321
def parse_config(config, name):
1422
return getattr(config.option, name, config.getini(name))
@@ -24,8 +32,10 @@ def force(fn):
2432

2533

2634
def pytest_addoption(parser):
27-
workers_help = 'Set the max num of workers (aka processes) to start (int or "auto" - one per core)'
28-
tests_per_worker_help = 'Set the max num of concurrent tests for each worker (int or "auto" - split evenly)'
35+
workers_help = ('Set the max num of workers (aka processes) to start '
36+
'(int or "auto" - one per core)')
37+
tests_per_worker_help = ('Set the max num of concurrent tests for each '
38+
'worker (int or "auto" - split evenly)')
2939

3040
group = parser.getgroup('pytest-parallel')
3141
group.addoption(
@@ -63,7 +73,7 @@ def __init__(self, queue, session):
6373
threading.Thread.__init__(self)
6474
self.queue = queue
6575
self.session = session
66-
76+
6777
def run(self):
6878
while True:
6979
try:
@@ -139,7 +149,9 @@ class ParallelRunner(object):
139149
def __init__(self, config):
140150
self._manager = Manager()
141151
reporter = config.pluginmanager.getplugin('terminalreporter')
142-
reporter.showfspath = False # prevent mangling the output
152+
153+
# prevent mangling the output
154+
reporter.showfspath = False
143155

144156
# get the number of workers
145157
workers = parse_config(config, 'workers')
@@ -155,62 +167,74 @@ def __init__(self, config):
155167
print('INFO: pytest-parallel forces 1 worker on Windows')
156168
except ValueError:
157169
raise ValueError('workers can only be an integer or "auto"')
158-
170+
159171
self.workers = workers
160172

161173
if self.workers > 1:
162174
# ensure stats are process-safe
163175
reporter.stats = self._manager.dict()
164176
setdefault = reporter.stats.setdefault
177+
165178
def setdefault_proxy(key, default=None):
166179
if isinstance(default, list) and len(default) == 0:
167180
default = force(lambda: self._manager.list())
168181
return force(lambda: setdefault(key, default))
169182
reporter.stats.setdefault = setdefault_proxy
170183

171-
172184
@pytest.mark.tryfirst
173185
def pytest_sessionstart(self, session):
174186
# make the session threadsafe
175187
_pytest.runner.SetupState = ThreadLocalSetupState
176-
188+
177189
# ensure that the fixtures (specifically finalizers) are threadsafe
178190
_pytest.fixtures.FixtureDef = ThreadLocalFixtureDef
179191

180192
# make the environment threadsafe
181193
os.environ = ThreadLocalEnviron(os.environ)
182194

183-
184195
def pytest_runtestloop(self, session):
185196
# get the number of tests per worker
186197
tests_per_worker = parse_config(session.config, 'tests_per_worker')
187198
try:
188199
if tests_per_worker == 'auto':
189200
tests_per_worker = 50
190201
if tests_per_worker:
191-
tests_per_worker = min(int(tests_per_worker), math.ceil(len(session.items)/self.workers))
202+
tests_per_worker = int(tests_per_worker)
203+
evenly_divided = math.ceil(len(session.items)/self.workers)
204+
tests_per_worker = min(tests_per_worker, evenly_divided)
192205
else:
193206
tests_per_worker = 1
194207
except ValueError:
195-
raise ValueError('tests_per_worker can only be an integer or "auto"')
208+
raise ValueError(('tests_per_worker can only be '
209+
'an integer or "auto"'))
196210

197-
worker_noun = 'workers' if self.workers > 1 else 'worker'
198-
test_noun = 'tests' if tests_per_worker > 1 else 'test'
199-
print('pytest-parallel: {} {} (processes), {} {} per worker (threads)'
200-
.format(self.workers, worker_noun, tests_per_worker, test_noun))
211+
if self.workers > 1:
212+
worker_noun, process_noun = ('workers', 'processes')
213+
else:
214+
worker_noun, process_noun = ('worker', 'process')
215+
216+
if tests_per_worker > 1:
217+
test_noun, thread_noun = ('tests', 'threads')
218+
else:
219+
test_noun, thread_noun = ('test', 'thread')
220+
221+
print('pytest-parallel: {} {} ({}), {} {} per worker ({})'
222+
.format(self.workers, worker_noun, process_noun,
223+
tests_per_worker, test_noun, thread_noun))
201224

202225
queue = Queue.Queue() if self.workers == 1 else self._manager.Queue()
203226

204227
for i in range(len(session.items)):
205228
queue.put(i)
206-
229+
207230
if self.workers == 1:
208231
process_with_threads(queue, session, tests_per_worker)
209232
return True
210233

211234
processes = []
212235
for _ in range(self.workers):
213-
process = Process(target=process_with_threads, args=(queue, session, tests_per_worker))
236+
process = Process(target=process_with_threads,
237+
args=(queue, session, tests_per_worker))
214238
process.start()
215239
processes.append(process)
216240
[p.join() for p in processes]

setup.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
1-
from setuptools import setup, find_packages
1+
from setuptools import setup
22
from codecs import open
33
from os import path
4+
import re
45

56
here = path.abspath(path.dirname(__file__))
67

78
# Get the long description from the README file
89
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
910
long_description = f.read()
1011

12+
# Get the version from the module
13+
with open(path.join('pytest_parallel', '__init__.py'), encoding='utf-8') as f:
14+
version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1)
15+
1116
setup(
1217
name='pytest-parallel',
13-
version='0.0.1',
18+
version=version,
1419
license='MIT',
1520
description='a py.test plugin for parallel and concurrent testing',
1621
long_description=long_description,
@@ -19,6 +24,14 @@
1924
author='Browsertron',
2025
author_email='[email protected]',
2126

27+
install_requires=['pytest>=3.0.0'],
28+
packages=['pytest_parallel'],
29+
entry_points={
30+
'pytest11': [
31+
'parallel = pytest_parallel',
32+
]
33+
},
34+
2235
# For a list of valid classifiers, see https://pypi.org/classifiers/
2336
classifiers=[
2437
'Development Status :: 3 - Alpha',
@@ -36,7 +49,4 @@
3649
'Programming Language :: Python :: 3',
3750
'Programming Language :: Python :: 3.6',
3851
],
39-
40-
packages=find_packages(),
41-
install_requires=['pytest>=3.0.0'],
4252
)

tasks.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from invoke import task
2+
from codecs import open
3+
from os import path
4+
import re
5+
6+
with open(path.join('pytest_parallel', '__init__.py'), encoding='utf-8') as f:
7+
version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1)
8+
9+
10+
@task
11+
def test(c):
12+
c.run('tox')
13+
14+
15+
@task
16+
def build(c):
17+
c.run('python setup.py sdist bdist_wheel')
18+
19+
20+
@task
21+
def release(c):
22+
test(c)
23+
build(c)
24+
c.run('git commit -am {}'.format(version))
25+
c.run('git tag {}'.format(version))
26+
c.run('git push')
27+
c.run('git push --tags')
28+
c.run('twine upload dist/*')

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest_plugins = ['pytester']

tests/test_concurrent.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
def test_concurrent_fixture(testdir):
2+
testdir.makepyfile("""
3+
import pytest
4+
import time
5+
from six import print_
6+
7+
@pytest.fixture
8+
def driver(request):
9+
fn_name = request.function.__name__
10+
print_('before sleep', fn_name)
11+
time.sleep(.1)
12+
print_('after sleep', fn_name)
13+
def after():
14+
print_('after test', fn_name)
15+
request.addfinalizer(after)
16+
17+
def test_0(driver):
18+
print_('inside test_0')
19+
time.sleep(.1)
20+
21+
def test_1(driver):
22+
print_('inside test_1')
23+
""")
24+
result = testdir.runpytest(
25+
'-s',
26+
'--tests-per-worker=2'
27+
)
28+
result.stdout.fnmatch_lines([
29+
'pytest-parallel: 1 worker (process), 2 tests per worker (threads)',
30+
'*before sleep test_0',
31+
'*before sleep test_1',
32+
'*after sleep test_0',
33+
'*inside test_0',
34+
'*after sleep test_1',
35+
'*inside test_1',
36+
'*after test test_1',
37+
'*after test test_0'
38+
])
39+
result.assert_outcomes(passed=2)

0 commit comments

Comments
 (0)