Skip to content

Commit 9ff4f8d

Browse files
committed
tests: convert tests from python-nose to pytest
- As python-nose is deprecated, move all tests to pytest. - Add tox to run the tests. - Add flake8 as linter - Run tox during CI. Signed-off-by: Jean-Louis Dupond <jean-louis@dupond.be>
1 parent f42aeee commit 9ff4f8d

29 files changed

Lines changed: 398 additions & 419 deletions

.github/workflows/build.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,24 @@ jobs:
5555
libxml2-devel \
5656
libxslt-devel \
5757
python3-devel \
58-
python3-nose \
58+
python3-nose2 \
5959
python3-pip \
6060
python3-pycurl \
6161
python3-pygments \
6262
python3-wheel \
63+
tox \
6364
rpm-build \
6465
tar \
6566
-y
6667
6768
- name: Checkout sources
6869
uses: ovirt/checkout-action@main
6970

71+
- name: Run pytest
72+
run: |
73+
bash .automation/generate-setup-files.sh
74+
tox
75+
7076
- name: Run build for version
7177
run: |
7278
.automation/build-rpm.sh $ARTIFACTS_DIR

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22
PKG-INFO
33
setup.py
44
version.py
5-
lib/ovirtsdk4/__pycache__/
5+
__pycache__
6+
.tox
7+
/build
8+
/dist
9+
*.so
10+
.vscode
11+
*.egg-info

lib/ovirtsdk4/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ def _get_sso_response(self, url, params=''):
689689

690690
# Prepare headers:
691691
header_lines = [
692-
'User-Agent: PythonSDK/%s' % version.VERSION,
692+
'User-Agent: PythonSDK/%s' % get_version(),
693693
'Accept: application/json'
694694
]
695695
curl.setopt(pycurl.HTTPHEADER, header_lines)

setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
[nosetests]
2-
where=tests
1+
[unittest]
2+
start-dir = tests

tests/server.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
import ssl
2525

2626
try:
27-
from http.server import HTTPServer, BaseHTTPRequestHandler
27+
from http.server import HTTPServer
2828
from http.server import SimpleHTTPRequestHandler
2929
except ImportError:
30-
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
30+
from BaseHTTPServer import HTTPServer
3131
from SimpleHTTPServer import SimpleHTTPRequestHandler
3232

3333
from threading import Thread
@@ -101,7 +101,8 @@ def _handle_request(handler):
101101
authorization = handler.headers.get('Authorization')
102102
if authorization != "Bearer %s" % self.TOKEN:
103103
handler.send_response(401)
104-
handler.wfile.write('')
104+
handler.end_headers()
105+
handler.wfile.write('401 - Unauthorized'.encode('utf-8'))
105106
else:
106107
sleep(delay)
107108
handler.send_response(code)
@@ -116,7 +117,7 @@ def _handle_request(handler):
116117
] = _handle_request
117118

118119
def set_json_response(self, path, code, body):
119-
def _handle_request(handler):
120+
def _handle_request(handler):
120121
handler.send_response(code)
121122
handler.send_header('Content-Type', 'application/json')
122123
handler.end_headers()
@@ -128,10 +129,13 @@ def _handle_request(handler):
128129

129130
def start_server(self, host='localhost'):
130131
self._httpd = HTTPServer((self.host(), self.port()), TestHandler)
131-
self._httpd.socket = ssl.wrap_socket(
132-
self._httpd.socket,
133-
keyfile=self.__absolute_path('%s.key' % host),
132+
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
133+
context.load_cert_chain(
134134
certfile=self.__absolute_path('%s.crt' % host),
135+
keyfile=self.__absolute_path('%s.key' % host)
136+
)
137+
self._httpd.socket = context.wrap_socket(
138+
self._httpd.socket,
135139
server_side=True
136140
)
137141
# Path handler for username/password authentication service:
@@ -168,7 +172,7 @@ def port(self):
168172
try:
169173
server = HTTPServer(
170174
(self.host(), port),
171-
BaseHTTPRequestHandler
175+
TestHandler
172176
)
173177
self.PORT = port
174178
break

tests/test_affinity_group_reader.py

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919
import ovirtsdk4.types as types
2020

2121
from io import BytesIO
22-
from nose.tools import (
23-
assert_equals,
24-
assert_true,
25-
)
2622
from ovirtsdk4.readers import AffinityGroupReader
2723
from ovirtsdk4.xml import XmlReader
2824

@@ -48,13 +44,10 @@ def test_affinity_group_reader_with_assigned_vms():
4844
result = AffinityGroupReader.read_one(reader)
4945
reader.close()
5046

51-
assert_true(isinstance(result, types.AffinityGroup))
52-
assert_true(len(result.vms) > 0)
53-
assert_equals(
54-
result.vms.href,
55-
'/ovirt-engine/api/clusters/123/affinitygroups/456/vms'
56-
)
57-
assert_equals(result.vms[0].id, '123')
47+
assert isinstance(result, types.AffinityGroup)
48+
assert len(result.vms) > 0
49+
assert result.vms.href == '/ovirt-engine/api/clusters/123/affinitygroups/456/vms'
50+
assert result.vms[0].id == '123'
5851

5952

6053
def test_affinity_group_reader_with_assigned_vms_no_order():
@@ -72,10 +65,7 @@ def test_affinity_group_reader_with_assigned_vms_no_order():
7265
result = AffinityGroupReader.read_one(reader)
7366
reader.close()
7467

75-
assert_true(isinstance(result, types.AffinityGroup))
76-
assert_true(len(result.vms) > 0)
77-
assert_equals(
78-
result.vms.href,
79-
'/ovirt-engine/api/clusters/123/affinitygroups/456/vms'
80-
)
81-
assert_equals(result.vms[0].id, '123')
68+
assert isinstance(result, types.AffinityGroup)
69+
assert len(result.vms) > 0
70+
assert result.vms.href == '/ovirt-engine/api/clusters/123/affinitygroups/456/vms'
71+
assert result.vms[0].id == '123'

tests/test_check_types.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,7 @@
1919
import ovirtsdk4.services as services
2020
import ovirtsdk4.types as types
2121
import unittest
22-
23-
from nose.tools import (
24-
assert_in,
25-
assert_raises,
26-
)
27-
from .server import TestServer
22+
import pytest
2823

2924

3025
class CheckTypesTest(unittest.TestCase):
@@ -35,20 +30,20 @@ def test_service_type_error(self):
3530
generates an informative exception.
3631
"""
3732
vm_service = services.VmService(None, None)
38-
with assert_raises(TypeError) as context:
33+
with pytest.raises(TypeError) as context:
3934
vm_service.start(
4035
use_cloud_init='true',
4136
vm=types.Disk(),
4237
)
43-
message = str(context.exception)
44-
assert_in(
38+
message = str(context.value)
39+
assert (
4540
"The 'use_cloud_init' parameter should be of type 'bool', "
46-
"but it is of type 'str'",
41+
"but it is of type 'str'" in
4742
message
4843
)
49-
assert_in(
44+
assert (
5045
"The 'vm' parameter should be of type 'Vm', but it is of "
51-
"type 'Disk'",
46+
"type 'Disk'" in
5247
message
5348
)
5449

@@ -58,11 +53,11 @@ def test_locator_type_error(self):
5853
generates an informative exception.
5954
"""
6055
vms_service = services.VmsService(None, None)
61-
with assert_raises(TypeError) as context:
56+
with pytest.raises(TypeError) as context:
6257
vms_service.vm_service(types.Vm())
63-
message = str(context.exception)
64-
assert_in(
58+
message = str(context.value)
59+
assert (
6560
"The 'id' parameter should be of type 'str', but it is of "
66-
"type 'Vm'.",
61+
"type 'Vm'." in
6762
message
6863
)

tests/test_cluster_reader.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,6 @@
1919
import ovirtsdk4.types as types
2020

2121
from io import BytesIO
22-
from nose.tools import (
23-
assert_equals,
24-
assert_is_none,
25-
assert_true,
26-
)
2722
from ovirtsdk4.readers import ClusterReader
2823
from ovirtsdk4.xml import XmlReader
2924

@@ -49,9 +44,9 @@ def test_cluster_with_no_rng_sources_and_switch_type():
4944
result = ClusterReader.read_one(reader)
5045
reader.close()
5146

52-
assert_true(isinstance(result, types.Cluster))
53-
assert_equals(result.required_rng_sources, [])
54-
assert_equals(result.switch_type, types.SwitchType.LEGACY)
47+
assert isinstance(result, types.Cluster)
48+
assert result.required_rng_sources == []
49+
assert result.switch_type == types.SwitchType.LEGACY
5550

5651

5752

@@ -67,5 +62,5 @@ def test_unsupported_switch_type_dont_raise_exception():
6762
result = ClusterReader.read_one(reader)
6863
reader.close()
6964

70-
assert_true(isinstance(result, types.Cluster))
71-
assert_is_none(result.switch_type)
65+
assert isinstance(result, types.Cluster)
66+
assert result.switch_type is None

tests/test_cluster_service.py

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@
1818

1919
import unittest
2020

21-
from nose.tools import (
22-
assert_is_not_none,
23-
assert_equal,
24-
)
2521
from .server import TestServer
2622

2723

@@ -44,25 +40,25 @@ def test_get_service(self):
4440
"""
4541
Check that reference to clusters service is not none
4642
"""
47-
assert_is_not_none(self.clusters_service)
43+
assert self.clusters_service is not None
4844

4945
def test_get_list_of_clusters(self):
5046
"""
5147
Test returning empty clusters list
5248
"""
5349
self.server.set_xml_response("clusters", 200, "<clusters/>")
5450
clusters = self.clusters_service.list()
55-
assert_is_not_none(clusters)
56-
assert_equal(clusters, [])
51+
assert clusters is not None
52+
assert clusters == []
5753

5854
def test_get_list_of_clusters_with_search(self):
5955
"""
6056
Test returning empty clusters list
6157
"""
6258
self.server.set_xml_response("clusters", 200, "<clusters/>")
6359
clusters = self.clusters_service.list(search="name=ugly")
64-
assert_is_not_none(clusters)
65-
assert_equal(clusters, [])
60+
assert clusters is not None
61+
assert clusters == []
6662

6763
def test_get_cluster_by_id(self):
6864
"""
@@ -75,5 +71,5 @@ def test_get_cluster_by_id(self):
7571
body="<cluster id=\"123\"><name>testcluster</name></cluster>"
7672
)
7773
cluster = self.clusters_service.cluster_service("123").get()
78-
assert_equal(cluster.id, "123")
79-
assert_equal(cluster.name, "testcluster")
74+
assert cluster.id == "123"
75+
assert cluster.name == "testcluster"

tests/test_connection_create.py

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,8 @@
1818

1919
import ovirtsdk4 as sdk
2020
import unittest
21+
import pytest
2122

22-
from nose.tools import (
23-
assert_true,
24-
raises
25-
)
2623
from .server import TestServer
2724

2825

@@ -38,19 +35,19 @@ def setup_class(cls):
3835
def teardown_class(cls):
3936
cls.server.stop_server()
4037

41-
@raises(sdk.Error)
4238
def test_secure_mode_without_ca(self):
4339
"""
4440
Test connection can be created when no CA is provided
4541
"""
46-
connection = sdk.Connection(
47-
url=self.server.url(),
48-
username=self.server.user(),
49-
password=self.server.password(),
50-
ca_file='ugly.pem'
51-
)
52-
connection.authenticate()
53-
connection.close()
42+
with pytest.raises(sdk.Error):
43+
connection = sdk.Connection(
44+
url=self.server.url(),
45+
username=self.server.user(),
46+
password=self.server.password(),
47+
ca_file='ugly.pem'
48+
)
49+
connection.authenticate()
50+
connection.close()
5451

5552
def test_secure_mode_with_ca(self):
5653
"""
@@ -90,17 +87,17 @@ def test_kerberos_auth(self):
9087
connection.authenticate()
9188
connection.close()
9289

93-
@raises(sdk.Error)
9490
def test_invalid_header(self):
9591
"""
9692
When invalid header is used Error should be raised
9793
"""
98-
request = sdk.http.Request(
99-
method='GET',
100-
headers={'X-header': 'žčě'},
101-
)
102-
connection = self.server.connection()
103-
connection.send(request)
94+
with pytest.raises(sdk.Error):
95+
request = sdk.http.Request(
96+
method='GET',
97+
headers={'X-header': 'žčě'},
98+
)
99+
connection = self.server.connection()
100+
connection.send(request)
104101

105102
def test_valid_header(self):
106103
"""

0 commit comments

Comments
 (0)