Skip to content

Commit 7fa6bc0

Browse files
authored
Fix functional test suite on Python 3 and modern pytest (#883)
1 parent 0d16933 commit 7fa6bc0

7 files changed

Lines changed: 51 additions & 64 deletions

File tree

docs/FUNCTIONAL_TESTING.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
**Note: The current implementation of functional tests is broken and requires updating.**
2-
31
## Functional testing
42

53
During functional testing the program is tested as a whole. This is much like if the testing were made by a human. Although the user interface parts are not tested the core of the program is tested and how the different program components work together. When functional tests succeed that means that the tested scenarios will most likely work properly when the program is run by real users. The quality of total testing obviously depends on the amount and quality of individual tests.
@@ -28,11 +26,11 @@ Technically NServ is integrated into NZBGet as a sub-module. NServ is automatica
2826

2927
## Testing framework
3028

31-
Functional tests for NZBGet are written in python language. We are using testing framework [py.test](https://pytest.org) to organize test execution and collect test results. Therefore in order to run functional tests py.test [must be installed](https://docs.pytest.org/en/latest/getting-started.html) on your system.
29+
Functional tests for NZBGet are written in python language (Python 3). We are using testing framework [pytest](https://pytest.org) to organize test execution and collect test results. Therefore in order to run functional tests pytest [must be installed](https://docs.pytest.org/en/latest/getting-started.html) on your system.
3230

3331
## Running tests
3432

35-
Functional tests and supporting modules are stored in directory `tests/functional`. To run tests open command prompt in this directory and execute `py.test` as explained below.
33+
Functional tests and supporting modules are stored in directory `tests/functional`. To run tests open command prompt in this directory and execute `pytest` as explained below.
3634

3735
### Configuring tests
3836

@@ -55,33 +53,37 @@ All settings in the ini-file are optional.
5553
When executing the tests for the first time the test scripts prepare test files and put them into directory `tests/testdata/nserv.temp`. These files take several gigabytes and may need several minutes to generate. When starting tests for the first time it’s recommended to add parameter `-s` to see additional progress logging during preparation stage:
5654

5755
```bash
58-
py.test -v -s
56+
pytest -v -s
5957
```
6058

6159
### Executing tests
6260

6361
To run all tests use simple command:
6462

6563
```bash
66-
py.test -v
64+
pytest -v
6765
```
6866

6967
To run tests from one test script only pass the specific file name:
7068

7169
```bash
72-
py.test -v parcheck\parcheck_force_test.py
70+
pytest -v parcheck/parcheck_force_test.py
7371
```
7472

7573
To execute only one specific test pass the file name and test function name:
7674

7775
```bash
78-
py.test -v parcheck/parcheck_auto_test.py::test_parchecker_repair
76+
pytest -v parcheck/parcheck_auto_test.py::test_parchecker_repair
7977
```
8078

81-
For more filter possibilities please see [py.test](https://docs.pytest.org/en/latest/usage.html) documentation.
79+
For more filter possibilities please see [pytest](https://docs.pytest.org/en/latest/usage.html) documentation.
8280

8381
### Test failures
8482

8583
Directory used by NZBGet during testing (`tests/testdata/nzbget.temp` by default) is automatically deleted if all tests succeed. If a test fails the directory is kept in order to preserve log-files and queue-files for failure analysis. However during testing NZBGet is started and stopped multiple times. If the failed test wasn’t the last test the preserved NZBGet directory may not contain data of the failed test. In such case it’s better to rerun the specific failed test as the only test (using specific command line).
8684

8785
After test completion NZBGet is terminated. To analyze a test failure it can be useful to have NZBGet running, for example to inspect the state in web-interface. Pass extra parameter `--hold` to achieve this:
86+
87+
```bash
88+
pytest -v parcheck/parcheck_auto_test.py::test_parchecker_repair --hold
89+
```

tests/functional/conftest.py

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,7 @@
44
import time
55
import shutil
66
import base64
7-
import distutils.spawn
8-
try:
9-
from xmlrpclib import ServerProxy # python 2
10-
except ImportError:
11-
from xmlrpc.client import ServerProxy # python 3
7+
from xmlrpc.client import ServerProxy
128

139
nzbget_srcdir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
1410
nzbget_maindir = nzbget_srcdir + '/tests/testdata/nzbget.temp'
@@ -20,13 +16,9 @@
2016
nzbget_bin = nzbget_srcdir + '/nzbget' + exe_ext
2117
nserv_datadir = nzbget_srcdir + '/tests/testdata/nserv.temp'
2218

23-
sevenzip_bin = distutils.spawn.find_executable('7z')
24-
if sevenzip_bin is None:
25-
sevenzip_bin = nzbget_srcdir + '/7z' + exe_ext
19+
sevenzip_bin = shutil.which('7z') or nzbget_srcdir + '/7z' + exe_ext
2620

27-
par2_bin = distutils.spawn.find_executable('par2')
28-
if par2_bin is None:
29-
par2_bin = nzbget_srcdir + '/par2' + exe_ext
21+
par2_bin = shutil.which('par2') or nzbget_srcdir + '/par2' + exe_ext
3022

3123
has_failures = False
3224

@@ -38,30 +30,29 @@ def pytest_addoption(parser):
3830
parser.addini('par2_bin', 'path to par2 binary', default=par2_bin)
3931
parser.addoption("--hold", action="store_true", help="Hold at the end of test (keep NZBGet running)")
4032

41-
def check_config():
33+
@pytest.fixture(scope='session')
34+
def check_config(request):
4235
global nzbget_bin
43-
nzbget_bin = pytest.config.getini('nzbget_bin')
36+
nzbget_bin = request.config.getini('nzbget_bin')
4437
if not os.path.exists(nzbget_bin):
4538
pytest.exit('Could not find nzbget binary at ' + nzbget_bin + '. Alternative path can be set via pytest ini option "nzbget_bin".')
4639

4740
global sevenzip_bin, par2_bin
48-
sevenzip_bin = pytest.config.getini('sevenzip_bin')
49-
par2_bin = pytest.config.getini('par2_bin')
41+
sevenzip_bin = request.config.getini('sevenzip_bin')
42+
par2_bin = request.config.getini('par2_bin')
5043
if not os.path.exists(sevenzip_bin):
5144
pytest.exit('Could not find 7-zip binary in search path or at ' + sevenzip_bin + '. Alternative path can be set via pytest ini option "sevenzip_bin".')
5245
if not os.path.exists(par2_bin):
5346
pytest.exit('Could not find par2 binary in search path or at ' + par2_bin + '. Alternative path can be set via pytest ini option "par2_bin".')
5447

5548
global nserv_datadir
56-
nserv_datadir = pytest.config.getini('nserv_datadir')
49+
nserv_datadir = request.config.getini('nserv_datadir')
5750

5851
global nzbget_maindir
59-
nzbget_maindir = pytest.config.getini('nzbget_maindir')
52+
nzbget_maindir = request.config.getini('nzbget_maindir')
6053
global nzbget_configfile
6154
nzbget_configfile = nzbget_maindir + '/nzbget.conf'
6255

63-
pytest.check_config = check_config
64-
6556
class NServ:
6657

6758
def __init__(self):
@@ -72,9 +63,7 @@ def finalize(self):
7263

7364
@pytest.fixture(scope='session')
7465

75-
def nserv(request):
76-
check_config()
77-
66+
def nserv(request, check_config):
7867
instance = NServ()
7968
request.addfinalizer(instance.finalize)
8069
return instance
@@ -91,7 +80,7 @@ def __init__(self, options, session):
9180
self.wait_until_started()
9281

9382
def finalize(self):
94-
if pytest.config.getoption("--hold"):
83+
if self.session.config.getoption("--hold"):
9584
print('\nNZBGet is still running, press Ctrl+C to quit')
9685
time.sleep(100000)
9786
self.process.kill()
@@ -172,7 +161,7 @@ def wait_until_started(self):
172161
print('Started')
173162

174163
def append_nzb(self, nzb_name, nzb_content, unpack = None, dupekey = '', dupescore = 0, dupemode = 'FORCE', params = None):
175-
nzbcontent64 = base64.standard_b64encode(nzb_content)
164+
nzbcontent64 = base64.standard_b64encode(nzb_content.encode()).decode()
176165
if params is None:
177166
params = []
178167
if unpack == True:
@@ -210,13 +199,11 @@ def wait_nzb(self, nzb_name):
210199
return hist
211200

212201
def clear(self):
213-
self.api.editqueue('HistoryFinalDelete', 0, '', range(1, 1000));
202+
self.api.editqueue('HistoryFinalDelete', 0, '', list(range(1, 1000)))
214203

215204
@pytest.fixture(scope='module')
216205

217-
def nzbget(request):
218-
check_config()
219-
206+
def nzbget(request, check_config):
220207
instance = Nzbget(getattr(request.module, 'nzbget_options', []), request.session)
221208
request.addfinalizer(instance.finalize)
222209
return instance

tests/functional/download/conftest.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,23 @@ def pytest_addoption(parser):
1010

1111

1212
@pytest.fixture(scope='session', autouse=True)
13-
def prepare_testdata(request):
13+
def prepare_testdata(request, check_config):
1414
print('Preparing test data for "download"')
15-
pytest.check_config()
1615

17-
nserv_datadir = pytest.config.getini('nserv_datadir')
18-
nzbget_bin = pytest.config.getini('nzbget_bin')
19-
sevenzip_bin = pytest.config.getini('sevenzip_bin')
16+
nserv_datadir = request.config.getini('nserv_datadir')
17+
nzbget_bin = request.config.getini('nzbget_bin')
18+
sevenzip_bin = request.config.getini('sevenzip_bin')
2019

2120
if not os.path.exists(nserv_datadir):
2221
print('Creating nserv datadir')
2322
os.makedirs(nserv_datadir)
2423

2524
if not os.path.exists(nserv_datadir + '/medium.nzb'):
26-
sizemb = int(pytest.config.getini('sample_medium'))
25+
sizemb = int(request.config.getini('sample_medium'))
2726
create_test_file(nserv_datadir + '/medium', sevenzip_bin, sizemb, 50)
2827

2928
if not os.path.exists(nserv_datadir + '/large.nzb'):
30-
sizemb = int(pytest.config.getini('sample_large'))
29+
sizemb = int(request.config.getini('sample_large'))
3130
create_test_file(nserv_datadir + '/large', sevenzip_bin, sizemb, 50)
3231

3332
if not os.path.exists(nserv_datadir + '/medium.nzb') or not os.path.exists(nserv_datadir + '/large.nzb'):
@@ -56,7 +55,7 @@ def create_test_file(bigdir, sevenzip_bin, sizemb, partmb):
5655
os.makedirs(bigdir)
5756

5857
f = open(bigdir + '/' + str(sizemb) + 'mb.dat', 'wb')
59-
for n in xrange(sizemb // partmb):
58+
for n in range(sizemb // partmb):
6059
print('Writing block %i from %i' % (n + 1, sizemb // partmb))
6160
f.write(os.urandom(partmb * 1024 * 1024))
6261
f.close()

tests/functional/download/dupecheck_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ def test_dupecheck_small_id(nserv, nzbget):
1414
hist = nzbget.download_nzb('small.nzb', dupemode = 'SCORE')
1515
assert hist['Status'] == 'SUCCESS/HEALTH'
1616
nzb_content = nzbget.load_nzb('small.nzb')
17-
nzbcontent64 = base64.standard_b64encode(nzb_content)
17+
nzbcontent64 = base64.standard_b64encode(nzb_content.encode()).decode()
1818
id = nzbget.api.append('small.copy2.nzb', nzbcontent64, 'test', 0, False, False, '', 0, 'SCORE', [])
1919
assert id > 0

tests/functional/download/unpack_test.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55

66
@pytest.fixture(scope='session', autouse=True)
7-
def prepare_testdata(request):
7+
def prepare_testdata(request, check_config):
88
print('Preparing test data for "unpack"')
99

10-
nserv_datadir = pytest.config.getini('nserv_datadir')
11-
nzbget_bin = pytest.config.getini('nzbget_bin')
12-
sevenzip_bin = pytest.config.getini('sevenzip_bin')
13-
par2_bin = pytest.config.getini('par2_bin')
10+
nserv_datadir = request.config.getini('nserv_datadir')
11+
nzbget_bin = request.config.getini('nzbget_bin')
12+
sevenzip_bin = request.config.getini('sevenzip_bin')
13+
par2_bin = request.config.getini('par2_bin')
1414

1515
if not os.path.exists(nserv_datadir):
1616
print('Creating nserv datadir')
@@ -60,8 +60,8 @@ def create_test_file(bigdir, sevenzip_bin, sizemb, partmb):
6060
os.makedirs(bigdir)
6161

6262
f = open(bigdir + '/' + str(sizemb) + 'mb.dat', 'wb')
63-
for n in xrange(sizemb / partmb):
64-
print('Writing block %i from %i' % (n + 1, sizemb / partmb))
63+
for n in range(sizemb // partmb):
64+
print('Writing block %i from %i' % (n + 1, sizemb // partmb))
6565
f.write(os.urandom(partmb * 1024 * 1024))
6666
f.close()
6767

tests/functional/parcheck/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55

66

77
@pytest.fixture(scope='session', autouse=True)
8-
def prepare_testdata(request):
8+
def prepare_testdata(request, check_config):
99
print('Preparing test data for "parcheck"')
1010

11-
nserv_datadir = pytest.config.getini('nserv_datadir')
12-
nzbget_bin = pytest.config.getini('nzbget_bin')
11+
nserv_datadir = request.config.getini('nserv_datadir')
12+
nzbget_bin = request.config.getini('nzbget_bin')
1313

1414
if not os.path.exists(nserv_datadir):
1515
print('Creating nserv datadir')

tests/functional/rename/conftest.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@
44
import pytest
55

66
@pytest.fixture(scope='session', autouse=True)
7-
def prepare_testdata(request):
7+
def prepare_testdata(request, check_config):
88
print('Preparing test data for "rename"')
9-
pytest.check_config()
109

11-
nserv_datadir = pytest.config.getini('nserv_datadir')
12-
nzbget_bin = pytest.config.getini('nzbget_bin')
13-
sevenzip_bin = pytest.config.getini('sevenzip_bin')
14-
par2_bin = pytest.config.getini('par2_bin')
10+
nserv_datadir = request.config.getini('nserv_datadir')
11+
nzbget_bin = request.config.getini('nzbget_bin')
12+
sevenzip_bin = request.config.getini('sevenzip_bin')
13+
par2_bin = request.config.getini('par2_bin')
1514

1615
if not os.path.exists(nserv_datadir):
1716
print('Creating nserv datadir')
@@ -190,8 +189,8 @@ def create_test_file(bigdir, sevenzip_bin, sizemb, partmb):
190189
os.makedirs(bigdir)
191190

192191
f = open(bigdir + '/' + str(sizemb) + 'mb.dat', 'wb')
193-
for n in xrange(sizemb / partmb):
194-
print('Writing block %i from %i' % (n + 1, sizemb / partmb))
192+
for n in range(sizemb // partmb):
193+
print('Writing block %i from %i' % (n + 1, sizemb // partmb))
195194
f.write(os.urandom(partmb * 1024 * 1024))
196195
f.close()
197196

0 commit comments

Comments
 (0)