Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate from (deprecated) nose to pytest #302

Merged
merged 4 commits into from
Dec 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[run]
concurrency = multiprocessing
2 changes: 1 addition & 1 deletion .github/workflows/autopkgtest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ jobs:
dch -v $(git describe --tags) "Autopkgtest CI testing (Jammy)"
- name: Run autopkgtest (incl. build)
run: |
sudo autopkgtest . -U --env=DPKG_GENSYMBOLS_CHECK_LEVEL=0 --env=DEB_BUILD_OPTIONS=nocheck -- lxd autopkgtest/ubuntu/jammy/amd64
sudo autopkgtest . --setup-commands='apt -y install python3-pytest python3-pytest-cov' -U --env=DPKG_GENSYMBOLS_CHECK_LEVEL=0 --env=DEB_BUILD_OPTIONS=nocheck -- lxd autopkgtest/ubuntu/jammy/amd64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this will no longer be required once we update the netplan packaging (dependencies)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct.

2 changes: 1 addition & 1 deletion .github/workflows/build-abi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
sudo sed -i '/deb-src/s/^# //' /etc/apt/sources.list
sudo apt update
#sudo apt install lcov python3-coverage curl
sudo apt install abigail-tools meson
sudo apt install abigail-tools meson python3-coverage python3-pytest python3-pytest-cov
sudo apt build-dep netplan.io

# Runs the build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
echo "APT::Get::Always-Include-Phased-Updates \"true\";" | sudo tee /etc/apt/apt.conf.d/90phased-updates
sudo sed -i '/deb-src/s/^# //' /etc/apt/sources.list
sudo apt update
sudo apt install python3-coverage curl meson gcovr expect
sudo apt install python3-coverage python3-pytest python3-pytest-cov curl meson gcovr expect
sudo apt build-dep netplan.io

# Runs the unit tests with coverage
Expand Down
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ PYCODE = netplan/ $(wildcard src/*.py) $(wildcard tests/*.py) $(wildcard tests/g
# Order: Fedora/Mageia/openSUSE || Debian/Ubuntu || null
PYFLAKES3 ?= $(shell command -v pyflakes-3 || command -v pyflakes3 || echo true)
PYCODESTYLE3 ?= $(shell command -v pycodestyle-3 || command -v pycodestyle || command -v pep8 || echo true)
NOSETESTS3 ?= $(shell command -v nosetests-3 || command -v nosetests3 || echo true)
PYTEST3 ?= $(shell command -v pytest-3 || command -v pytest3 || echo true)
PYCOVERAGE ?= $(shell command -v python3-coverage || echo true)

default: netplan/_features.py generate netplan-dbus dbus/io.netplan.Netplan.service doc/netplan.html doc/netplan.5 doc/netplan-generate.8 doc/netplan-apply.8 doc/netplan-try.8 doc/netplan-dbus.8 doc/netplan-get.8 doc/netplan-set.8

Expand Down Expand Up @@ -87,14 +88,14 @@ clean:

check: default linting
PYTHONPATH=. LD_LIBRARY_PATH=. tests/cli.py
PYTHONPATH=. LD_LIBRARY_PATH=. $(NOSETESTS3) -v --with-coverage
PYTHONPATH=. LD_LIBRARY_PATH=. $(PYCOVERAGE) run -a -m pytest -s -v --cov-append
tests/validate_docs.sh

linting:
$(PYFLAKES3) $(PYCODE)
$(PYCODESTYLE3) --max-line-length=130 $(PYCODE)

coverage: | pre-coverage c-coverage python-coverage
coverage: | pre-coverage c-coverage python-coverage-combine python-coverage

pre-coverage:
rm -f .coverage
Expand All @@ -112,6 +113,9 @@ c-coverage:
lcov --remove generate.info "/usr*" -o generate.info
genhtml -o test-coverage/C/ -t "generate test coverage" generate.info

python-coverage-combine:
python3-coverage combine -a

python-coverage:
python3-coverage html -d test-coverage/python --omit=/usr* || true
python3-coverage xml --omit=/usr* || true
Expand Down
4 changes: 1 addition & 3 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

- integrate 'netplan try' in tmux/screen

- replace nose for python tests with something else, preserving coverage reports

- add automated integration tests for WPA Enterprise / 802.1x that can run self-contained

# After soname bump (ABI break)
Expand All @@ -48,4 +46,4 @@

- move tunnel_ttl into tunnel struct

- store match.driver as a list rather than a string
sil2100 marked this conversation as resolved.
Show resolved Hide resolved
- store match.driver as a list rather than a string
14 changes: 10 additions & 4 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ bash_completions_dir = completions.get_variable(pkgconfig: 'completionsdir', def
# Order: Fedora/Mageia/openSUSE || Debian/Ubuntu
pyflakes = find_program('pyflakes-3', 'pyflakes3', required: false)
pycodestyle = find_program('pycodestyle-3', 'pycodestyle', 'pep8', required: false)
nose = find_program('nosetests-3', 'nosetests3')
pytest = find_program('pytest-3', 'pytest3') # also requires the pytest-cov plugin
pycoverage = find_program('python3-coverage')
pandoc = find_program('pandoc', required: false)
find = find_program('find')

Expand Down Expand Up @@ -61,6 +62,7 @@ test_env = [
'LD_LIBRARY_PATH=' + join_paths(meson.current_build_dir(), 'src'),
'NETPLAN_GENERATE_PATH=' + join_paths(meson.current_build_dir(), 'src', 'generate'),
'NETPLAN_DBUS_CMD=' + join_paths(meson.current_build_dir(), 'dbus', 'netplan-dbus'),
'COVERAGE_PROCESS_START=' + join_paths(meson.current_source_dir(), '.coveragerc'),
]
#FIXME: exclude doc/env/
test('linting',
Expand All @@ -78,8 +80,8 @@ test('legacy-tests',
env: test_env)
#TODO: split out dbus tests into own test() instance, to run in parallel
test('unit-tests',
nose,
args: ['-v', '--with-coverage', meson.current_source_dir()],
pycoverage,
args: ['run', '-a', '-m', 'pytest', '-s', '-v', '--cov-append', meson.current_source_dir()],
timeout: 600,
env: test_env)

Expand All @@ -94,7 +96,6 @@ if get_option('b_coverage')
gcovr = find_program('gcovr')
ninja = find_program('ninja')
grep = find_program('grep')
pycoverage = find_program('python3-coverage')
test('coverage-c-output',
find_program('ninja'),
args: ['-C', meson.current_build_dir(), 'coverage'],
Expand All @@ -105,6 +106,11 @@ if get_option('b_coverage')
args: ['^TOTAL.*100%$', join_paths(meson.current_build_dir(), 'meson-logs', 'coverage.txt')],
priority: -99, # run last
is_parallel: false)
test('coverage-py-combine',
pycoverage,
args: ['combine', '-a', meson.current_build_dir()],
priority: -99, # run last
is_parallel: false)
test('coverage-py-output',
pycoverage,
args: ['html', '-d', join_paths(meson.current_build_dir(),
Expand Down
2 changes: 2 additions & 0 deletions sitecustomize.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import coverage
coverage.process_startup()
3 changes: 2 additions & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ parts:
- python3-coverage
- python3-yaml
- python3-netifaces
- python3-nose
- python3-pytest
- python3-pytest-cov
- pyflakes3
- pep8
- systemd
Expand Down
38 changes: 19 additions & 19 deletions tests/dbus/test_dbus.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def test_netplan_apply_in_snap_uses_dbus(self):
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
self.assertEqual(p.stdout.read(), b"")
self.assertEqual(p.stderr.read(), b"")
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "apply"],
])

Expand All @@ -135,7 +135,7 @@ def test_netplan_apply_in_snap_calls_busctl(self):
p.wait(10)
self.assertEqual(p.stdout.read(), b"")
self.assertEqual(p.stderr.read(), b"")
self.assertEquals(self.mock_busctl_cmd.calls(), [
self.assertEqual(self.mock_busctl_cmd.calls(), [
["busctl", "call", "--quiet", "--system",
"io.netplan.Netplan", # the service
"/io/netplan/Netplan", # the object
Expand Down Expand Up @@ -181,7 +181,7 @@ def test_netplan_generate_in_snap_calls_busctl(self):
p.wait(10)
self.assertEqual(p.stdout.read(), b"")
self.assertEqual(p.stderr.read(), b"")
self.assertEquals(self.mock_busctl_cmd.calls(), [
self.assertEqual(self.mock_busctl_cmd.calls(), [
["busctl", "call", "--quiet", "--system",
"io.netplan.Netplan", # the service
"/io/netplan/Netplan", # the object
Expand Down Expand Up @@ -217,7 +217,7 @@ def test_netplan_generate_in_snap_calls_busctl_err(self):
def test_netplan_dbus_noroot(self):
# Process should fail instantly, if not: kill it after 5 sec
r = subprocess.run(NETPLAN_DBUS_CMD, timeout=5, capture_output=True)
self.assertEquals(r.returncode, 1)
self.assertEqual(r.returncode, 1)
self.assertIn(b'Failed to acquire service name', r.stderr)

def test_netplan_dbus_happy(self):
Expand All @@ -231,15 +231,15 @@ def test_netplan_dbus_happy(self):
output = subprocess.check_output(BUSCTL_NETPLAN_APPLY)
self.assertEqual(output.decode("utf-8"), "b true\n")
# one call to netplan apply in total
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "apply"],
])

# and again!
output = subprocess.check_output(BUSCTL_NETPLAN_APPLY)
self.assertEqual(output.decode("utf-8"), "b true\n")
# and another call to netplan apply
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "apply"],
["netplan", "apply"],
])
Expand All @@ -255,7 +255,7 @@ def test_netplan_dbus_generate(self):
output = subprocess.check_output(BUSCTL_NETPLAN_CMD)
self.assertEqual(output.decode("utf-8"), "b true\n")
# one call to netplan apply in total
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "generate"],
])

Expand Down Expand Up @@ -297,7 +297,7 @@ def test_netplan_dbus_config(self):
]
out = subprocess.check_output(BUSCTL_NETPLAN_CMD, universal_newlines=True)
self.assertIn(r's ""', out) # No output as 'netplan get' is actually mocked
self.assertEquals(self.mock_netplan_cmd.calls(), [[
self.assertEqual(self.mock_netplan_cmd.calls(), [[
"netplan", "get", "all", "--root-dir={}".format(tmpdir)
]])

Expand Down Expand Up @@ -332,7 +332,7 @@ def test_netplan_dbus_config_set(self):
]
out = subprocess.check_output(BUSCTL_NETPLAN_CMD)
self.assertEqual(b'b true\n', out)
self.assertEquals(self.mock_netplan_cmd.calls(), [[
self.assertEqual(self.mock_netplan_cmd.calls(), [[
"netplan", "set", "ethernets.eth42.dhcp6=true",
"--root-dir={}".format(tmpdir)
]])
Expand All @@ -353,7 +353,7 @@ def test_netplan_dbus_config_get(self):
]
out = subprocess.check_output(BUSCTL_NETPLAN_CMD, universal_newlines=True)
self.assertIn(r's "network:\n eth42:\n dhcp6: true\n"', out)
self.assertEquals(self.mock_netplan_cmd.calls(), [[
self.assertEqual(self.mock_netplan_cmd.calls(), [[
"netplan", "get", "all", "--root-dir={}".format(tmpdir)
]])

Expand Down Expand Up @@ -405,8 +405,8 @@ def test_netplan_dbus_config_apply(self):
]
out = subprocess.check_output(BUSCTL_NETPLAN_CMD)
self.assertEqual(b'b true\n', out)
self.assertEquals(self.mock_netplan_cmd.calls(),
[["netplan", "apply", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])
self.assertEqual(self.mock_netplan_cmd.calls(),
[["netplan", "apply", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])
time.sleep(1) # Give some time for 'Apply' to clean up
self.assertFalse(os.path.isdir(tmpdir))

Expand Down Expand Up @@ -491,8 +491,8 @@ def test_netplan_dbus_config_try_cancel(self):
self.assertIn('Unknown object \'/io/netplan/Netplan/config/{}\''.format(cid), err)

# Verify 'netplan try' has been called
self.assertEquals(self.mock_netplan_cmd.calls(),
[["netplan", "try", "--timeout=3", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])
self.assertEqual(self.mock_netplan_cmd.calls(),
[["netplan", "try", "--timeout=3", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])

def test_netplan_dbus_config_try_cb(self):
self.mock_netplan_cmd.touch(self._netplan_try_stamp)
Expand Down Expand Up @@ -533,8 +533,8 @@ def test_netplan_dbus_config_try_cb(self):
self.assertIn('Unknown object \'/io/netplan/Netplan/config/{}\''.format(cid), err)

# Verify 'netplan try' has been called
self.assertEquals(self.mock_netplan_cmd.calls(),
[["netplan", "try", "--timeout=1", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])
self.assertEqual(self.mock_netplan_cmd.calls(),
[["netplan", "try", "--timeout=1", "--state=%s/run/netplan/config-BACKUP" % self.tmp]])

def test_netplan_dbus_config_try_apply(self):
self.mock_netplan_cmd.touch(self._netplan_try_stamp)
Expand Down Expand Up @@ -668,7 +668,7 @@ def test_netplan_dbus_config_set_invalidate(self):
self.assertEqual(b'b true\n', out)

# Verify that Set()/Apply() was only called by one config object
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "set", "ethernets.eth0.dhcp4=true", "--origin-hint=70-snapd",
"--root-dir={}/run/netplan/config-{}".format(self.tmp, cid)],
["netplan", "set", "ethernets.eth0.dhcp4=yes", "--origin-hint=70-snapd",
Expand Down Expand Up @@ -738,7 +738,7 @@ def test_netplan_dbus_config_set_uninvalidate(self):
self.assertEqual(b'b true\n', out)

# Verify the call stack
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "set", "ethernets.eth0.dhcp4=true", "--origin-hint=70-snapd",
"--root-dir={}/run/netplan/config-{}".format(self.tmp, cid)],
["netplan", "set", "ethernets.eth0.dhcp4=false", "--origin-hint=70-snapd",
Expand Down Expand Up @@ -788,7 +788,7 @@ def test_netplan_dbus_config_set_uninvalidate_timeout(self):
self.assertEqual(b'b true\n', out)

# Verify the call stack
self.assertEquals(self.mock_netplan_cmd.calls(), [
self.assertEqual(self.mock_netplan_cmd.calls(), [
["netplan", "set", "ethernets.eth0.dhcp4=true", "--origin-hint=70-snapd",
"--root-dir={}/run/netplan/config-{}".format(self.tmp, cid)],
["netplan", "try", "--timeout=1", "--state=%s/run/netplan/config-BACKUP" % self.tmp],
Expand Down
2 changes: 1 addition & 1 deletion tests/generator/test_tunnels.py
Original file line number Diff line number Diff line change
Expand Up @@ -1432,7 +1432,7 @@ def test_vxlan_uuid(self):
m = re.search('uuid=([0-9a-fA-F-]{36})\n', f.read())
self.assertTrue(m)
uuid = m.group(1)
self.assertNotEquals(uuid, "00000000-0000-0000-0000-000000000000")
self.assertNotEqual(uuid, "00000000-0000-0000-0000-000000000000")

self.assert_nm({'vx0': '''[connection]
id=netplan-vx0
Expand Down
2 changes: 1 addition & 1 deletion tests/generator/test_vlans.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def test_vlan_parent_match(self):
m = re.search('uuid=([0-9a-fA-F-]{36})\n', f.read())
self.assertTrue(m)
uuid = m.group(1)
self.assertNotEquals(uuid, "00000000-0000-0000-0000-000000000000")
self.assertNotEqual(uuid, "00000000-0000-0000-0000-000000000000")

self.assert_nm({'en-v': '''[connection]
id=netplan-en-v
Expand Down
4 changes: 2 additions & 2 deletions tests/generator/test_wifis.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ def test_wifi(self):
freqs = freqs[1].split('\n')[0]
self.assertEqual(len(freqs.split(' ')), len(freqs_5GHz))
for freq in freqs_5GHz:
self.assertRegexpMatches(new_config, '{}[ 0-9]*{}[ 0-9]*\n'.format(network, freq))
self.assertRegex(new_config, '{}[ 0-9]*{}[ 0-9]*\n'.format(network, freq))

network = 'ssid="{}"\n freq_list='.format('band-no-channel')
freqs_24GHz = [2412, 2417, 2422, 2427, 2432, 2442, 2447, 2437, 2452, 2457, 2462, 2467, 2472, 2484]
freqs = new_config.split(network)
freqs = freqs[1].split('\n')[0]
self.assertEqual(len(freqs.split(' ')), len(freqs_24GHz))
for freq in freqs_24GHz:
self.assertRegexpMatches(new_config, '{}[ 0-9]*{}[ 0-9]*\n'.format(network, freq))
self.assertRegex(new_config, '{}[ 0-9]*{}[ 0-9]*\n'.format(network, freq))

self.assertIn('''
network={
Expand Down
4 changes: 2 additions & 2 deletions tests/test_cli_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,14 @@ def test_clear_virtual_links_no_delta(self, mock):
['br0', 'vlan2'],
devices=['br0', 'vlan2', 'eth0'])
mock.assert_not_called()
self.assertEquals(res, [])
self.assertEqual(res, [])

@patch('subprocess.check_call')
def test_clear_virtual_links_no_devices(self, mock):
with self.assertLogs('', level='INFO') as ctx:
res = NetplanApply.clear_virtual_links(['br0', 'br1'],
['br0'])
self.assertEquals(res, [])
self.assertEqual(res, [])
self.assertEqual(ctx.output, ['WARNING:root:Cannot clear virtual links: no network interfaces provided.'])
mock.assert_not_called()

Expand Down
12 changes: 6 additions & 6 deletions tests/test_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ def test_nonblocking_io(self):
self.terminal.enable_nonblocking_io()
flags = fcntl.fcntl(self.terminal.fd, fcntl.F_GETFL)
self.assertTrue(flags & os.O_NONBLOCK)
self.assertNotEquals(flags, orig_flags)
self.assertNotEqual(flags, orig_flags)
self.terminal.disable_nonblocking_io()
flags = fcntl.fcntl(self.terminal.fd, fcntl.F_GETFL)
self.assertFalse(flags & os.O_NONBLOCK)
self.assertEquals(flags, orig_flags)
self.assertEqual(flags, orig_flags)

def test_save(self):
self.terminal.enable_nonblocking_io()
flags = self.terminal.orig_flags
self.terminal.save()
self.terminal.disable_nonblocking_io()
self.assertNotEquals(flags, self.terminal.orig_flags)
self.assertNotEqual(flags, self.terminal.orig_flags)
self.terminal.reset()
flags = fcntl.fcntl(self.terminal.fd, fcntl.F_GETFL)
self.assertEquals(flags, self.terminal.orig_flags)
self.assertEqual(flags, self.terminal.orig_flags)
self.terminal.disable_nonblocking_io()
self.terminal.save()

Expand All @@ -69,10 +69,10 @@ def test_save_and_restore_with_dict(self):
self.terminal.save(orig_settings)
self.terminal.disable_nonblocking_io()
flags = fcntl.fcntl(self.terminal.fd, fcntl.F_GETFL)
self.assertNotEquals(flags, orig_settings.get('flags'))
self.assertNotEqual(flags, orig_settings.get('flags'))
self.terminal.reset(orig_settings)
flags = fcntl.fcntl(self.terminal.fd, fcntl.F_GETFL)
self.assertEquals(flags, orig_settings.get('flags'))
self.assertEqual(flags, orig_settings.get('flags'))
self.terminal.disable_nonblocking_io()

def test_reset(self):
Expand Down
Loading