Skip to content

Commit 928c1b9

Browse files
committed
Testing: Refactor software tests into dedicated directory tests
git mv src/crate/client/test* tests/client/ git mv src/crate/testing/test* tests/testing/
1 parent 915f9a0 commit 928c1b9

30 files changed

+134
-132
lines changed

CHANGES.txt

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Unreleased
1212
"Threads may share the module, but not connections."
1313
- Added ``error_trace`` to string representation of an Error to relay
1414
server stacktraces into exception messages.
15+
- Refactoring: The module namespace ``crate.client.test_util`` has been
16+
renamed to ``crate.testing.util``.
1517

1618
.. _Migrate from crate.client to sqlalchemy-cratedb: https://cratedb.com/docs/sqlalchemy-cratedb/migrate-from-crate-client.html
1719
.. _sqlalchemy-cratedb: https://pypi.org/project/sqlalchemy-cratedb/

DEVELOP.rst

+15-9
Original file line numberDiff line numberDiff line change
@@ -32,34 +32,40 @@ see, for example, `useful command-line options for zope-testrunner`_.
3232

3333
Run all tests::
3434

35-
./bin/test -vvvv
35+
bin/test
3636

3737
Run specific tests::
3838

39-
./bin/test -vvvv -t test_score
39+
# Select modules.
40+
bin/test -t test_cursor
41+
bin/test -t client
42+
bin/test -t testing
43+
44+
# Select doctests.
45+
bin/test -t http.rst
4046

4147
Ignore specific test directories::
4248

43-
./bin/test -vvvv --ignore_dir=testing
49+
bin/test --ignore_dir=testing
4450

4551
The ``LayerTest`` test cases have quite some overhead. Omitting them will save
4652
a few cycles (~70 seconds runtime)::
4753

48-
./bin/test -t '!LayerTest'
54+
bin/test -t '!LayerTest'
4955

50-
Invoke all tests without integration tests (~15 seconds runtime)::
56+
Invoke all tests without integration tests (~10 seconds runtime)::
5157

52-
./bin/test --layer '!crate.testing.layer.crate' --test '!LayerTest'
58+
bin/test --layer '!crate.testing.layer.crate' --test '!LayerTest'
5359

54-
Yet ~130 test cases, but only ~5 seconds runtime::
60+
Yet ~60 test cases, but only ~1 second runtime::
5561

56-
./bin/test --layer '!crate.testing.layer.crate' --test '!LayerTest' \
62+
bin/test --layer '!crate.testing.layer.crate' --test '!LayerTest' \
5763
-t '!test_client_threaded' -t '!test_no_retry_on_read_timeout' \
5864
-t '!test_wait_for_http' -t '!test_table_clustered_by'
5965

6066
To inspect the whole list of test cases, run::
6167

62-
./bin/test --list-tests
68+
bin/test --list-tests
6369

6470
You can run the tests against multiple Python interpreters with `tox`_::
6571

bin/test

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ sys.argv[0] = os.path.abspath(sys.argv[0])
1212

1313
if __name__ == '__main__':
1414
zope.testrunner.run([
15-
'-vvv', '--auto-color',
16-
'--test-path', join(base, 'src')],
17-
)
15+
'-vvvv', '--auto-color',
16+
'--path', join(base, 'tests'),
17+
])

docs/by-example/connection.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ connect()
2121
This section sets up a connection object, and inspects some of its attributes.
2222

2323
>>> from crate.client import connect
24-
>>> from crate.client.test_util import ClientMocked
24+
>>> from crate.testing.util import ClientMocked
2525

2626
>>> connection = connect(client=ClientMocked())
2727
>>> connection.lowest_server_version.version

docs/by-example/cursor.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ up the response for subsequent cursor operations.
2323
>>> from crate.client import connect
2424
>>> from crate.client.converter import DefaultTypeConverter
2525
>>> from crate.client.cursor import Cursor
26-
>>> from crate.client.test_util import ClientMocked
26+
>>> from crate.testing.util import ClientMocked
2727

2828
>>> connection = connect(client=ClientMocked())
2929
>>> cursor = connection.cursor()

src/crate/client/test_util.py

-69
This file was deleted.

src/crate/testing/util.py

+71
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,74 @@
1+
# -*- coding: utf-8; -*-
2+
#
3+
# Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
4+
# license agreements. See the NOTICE file distributed with this work for
5+
# additional information regarding copyright ownership. Crate licenses
6+
# this file to you under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License. You may
8+
# obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15+
# License for the specific language governing permissions and limitations
16+
# under the License.
17+
#
18+
# However, if you have executed another commercial license agreement
19+
# with Crate these terms will supersede the license and you may use the
20+
# software solely pursuant to the terms of the relevant commercial agreement.
21+
import unittest
22+
23+
24+
class ClientMocked(object):
25+
26+
active_servers = ["http://localhost:4200"]
27+
28+
def __init__(self):
29+
self.response = {}
30+
self._server_infos = ("http://localhost:4200", "my server", "2.0.0")
31+
32+
def sql(self, stmt=None, parameters=None, bulk_parameters=None):
33+
return self.response
34+
35+
def server_infos(self, server):
36+
return self._server_infos
37+
38+
def set_next_response(self, response):
39+
self.response = response
40+
41+
def set_next_server_infos(self, server, server_name, version):
42+
self._server_infos = (server, server_name, version)
43+
44+
def close(self):
45+
pass
46+
47+
48+
class ParametrizedTestCase(unittest.TestCase):
49+
"""
50+
TestCase classes that want to be parametrized should
51+
inherit from this class.
52+
53+
https://eli.thegreenplace.net/2011/08/02/python-unit-testing-parametrized-test-cases
54+
"""
55+
def __init__(self, methodName="runTest", param=None):
56+
super(ParametrizedTestCase, self).__init__(methodName)
57+
self.param = param
58+
59+
@staticmethod
60+
def parametrize(testcase_klass, param=None):
61+
""" Create a suite containing all tests taken from the given
62+
subclass, passing them the parameter 'param'.
63+
"""
64+
testloader = unittest.TestLoader()
65+
testnames = testloader.getTestCaseNames(testcase_klass)
66+
suite = unittest.TestSuite()
67+
for name in testnames:
68+
suite.addTest(testcase_klass(name, param=param))
69+
return suite
70+
71+
172
class ExtraAssertions:
273
"""
374
Additional assert methods for unittest.

tests/__init__.py

Whitespace-only changes.
File renamed without changes.

tests/client/__init__.py

Whitespace-only changes.

src/crate/client/test_support.py renamed to tests/client/layer.py

+12-22
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434

3535
import stopit
3636

37-
from crate.testing.layer import CrateLayer
38-
from crate.testing.settings import \
39-
crate_host, crate_path, crate_port, \
40-
crate_transport_port, docs_path, localhost
4137
from crate.client import connect
38+
from crate.testing.layer import CrateLayer
39+
from .settings import \
40+
assets_path, crate_host, crate_path, crate_port, \
41+
crate_transport_port, localhost
4242

4343

4444
makeSuite = unittest.TestLoader().loadTestsFromTestCase
@@ -104,15 +104,15 @@ def setUpCrateLayerBaseline(test):
104104
with connect(crate_host) as conn:
105105
cursor = conn.cursor()
106106

107-
with open(docs_path('testing/testdata/mappings/locations.sql')) as s:
107+
with open(assets_path('mappings/locations.sql')) as s:
108108
stmt = s.read()
109109
cursor.execute(stmt)
110110
stmt = ("select count(*) from information_schema.tables "
111111
"where table_name = 'locations'")
112112
cursor.execute(stmt)
113113
assert cursor.fetchall()[0][0] == 1
114114

115-
data_path = docs_path('testing/testdata/data/test_a.json')
115+
data_path = assets_path('import/test_a.json')
116116
# load testing data into crate
117117
cursor.execute("copy locations from ?", (data_path,))
118118
# refresh location table so imported data is visible immediately
@@ -145,10 +145,8 @@ def tearDownDropEntitiesBaseline(test):
145145
class HttpsTestServerLayer:
146146
PORT = 65534
147147
HOST = "localhost"
148-
CERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__),
149-
"pki/server_valid.pem"))
150-
CACERT_FILE = os.path.abspath(os.path.join(os.path.dirname(__file__),
151-
"pki/cacert_valid.pem"))
148+
CERT_FILE = assets_path("pki/server_valid.pem")
149+
CACERT_FILE = assets_path("pki/cacert_valid.pem")
152150

153151
__name__ = "httpsserver"
154152
__bases__ = tuple()
@@ -237,18 +235,10 @@ def setUpWithHttps(test):
237235
test.globs['pprint'] = pprint
238236
test.globs['print'] = cprint
239237

240-
test.globs['cacert_valid'] = os.path.abspath(
241-
os.path.join(os.path.dirname(__file__), "pki/cacert_valid.pem")
242-
)
243-
test.globs['cacert_invalid'] = os.path.abspath(
244-
os.path.join(os.path.dirname(__file__), "pki/cacert_invalid.pem")
245-
)
246-
test.globs['clientcert_valid'] = os.path.abspath(
247-
os.path.join(os.path.dirname(__file__), "pki/client_valid.pem")
248-
)
249-
test.globs['clientcert_invalid'] = os.path.abspath(
250-
os.path.join(os.path.dirname(__file__), "pki/client_invalid.pem")
251-
)
238+
test.globs['cacert_valid'] = assets_path("pki/cacert_valid.pem")
239+
test.globs['cacert_invalid'] = assets_path("pki/cacert_invalid.pem")
240+
test.globs['clientcert_valid'] = assets_path("pki/client_valid.pem")
241+
test.globs['clientcert_invalid'] = assets_path("pki/client_invalid.pem")
252242

253243

254244
def _execute_statements(statements, on_error="ignore"):

src/crate/testing/settings.py renamed to tests/client/settings.py

+8-15
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,20 @@
2121
# software solely pursuant to the terms of the relevant commercial agreement.
2222
from __future__ import absolute_import
2323

24-
import os
24+
from pathlib import Path
2525

2626

27-
def docs_path(*parts):
28-
return os.path.abspath(
29-
os.path.join(
30-
os.path.dirname(os.path.dirname(__file__)), *parts
31-
)
32-
)
27+
def assets_path(*parts) -> str:
28+
return str((project_root() / "tests" / "assets").joinpath(*parts).absolute())
3329

3430

35-
def project_root(*parts):
36-
return os.path.abspath(
37-
os.path.join(docs_path("..", ".."), *parts)
38-
)
31+
def crate_path() -> str:
32+
return str(project_root() / "parts" / "crate")
3933

4034

41-
def crate_path(*parts):
42-
return os.path.abspath(
43-
project_root("parts", "crate", *parts)
44-
)
35+
def project_root() -> Path:
36+
return Path(__file__).parent.parent.parent
37+
4538

4639

4740
crate_port = 44209

src/crate/client/test_connection.py renamed to tests/client/test_connection.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
from urllib3 import Timeout
44

5-
from .connection import Connection
6-
from .http import Client
5+
from crate.client.connection import Connection
6+
from crate.client.http import Client
77
from crate.client import connect
88
from unittest import TestCase
99

10-
from ..testing.settings import crate_host
10+
from .settings import crate_host
1111

1212

1313
class ConnectionTest(TestCase):

src/crate/client/test_cursor.py renamed to tests/client/test_cursor.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
from crate.client import connect
3434
from crate.client.converter import DataType, DefaultTypeConverter
3535
from crate.client.http import Client
36-
from crate.client.test_util import ClientMocked
36+
from crate.testing.util import ClientMocked
3737

3838

3939
class CursorTest(TestCase):
File renamed without changes.

src/crate/client/test_http.py renamed to tests/client/test_http.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
import uuid
4444
import certifi
4545

46-
from .http import Client, CrateJsonEncoder, _get_socket_opts, _remove_certs_for_non_https
47-
from .exceptions import ConnectionError, ProgrammingError, IntegrityError
46+
from crate.client.http import Client, CrateJsonEncoder, _get_socket_opts, _remove_certs_for_non_https
47+
from crate.client.exceptions import ConnectionError, ProgrammingError, IntegrityError
4848

4949
REQUEST = 'crate.client.http.Server.request'
5050
CA_CERT_PATH = certifi.where()

src/crate/client/tests.py renamed to tests/client/tests.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import doctest
22
import unittest
33

4-
from crate.client.test_connection import ConnectionTest
5-
from crate.client.test_cursor import CursorTest
6-
from crate.client.test_http import HttpClientTest, KeepAliveClientTest, ThreadSafeHttpClientTest, ParamsTest, \
4+
from .test_connection import ConnectionTest
5+
from .test_cursor import CursorTest
6+
from .test_http import HttpClientTest, KeepAliveClientTest, ThreadSafeHttpClientTest, ParamsTest, \
77
RetryOnTimeoutServerTest, RequestsCaBundleTest, TestUsernameSentAsHeader, TestCrateJsonEncoder, \
88
TestDefaultSchemaHeader
9-
from crate.client.test_support import makeSuite, setUpWithHttps, HttpsTestServerLayer, setUpCrateLayerBaseline, \
9+
from .layer import makeSuite, setUpWithHttps, HttpsTestServerLayer, setUpCrateLayerBaseline, \
1010
tearDownDropEntitiesBaseline, ensure_cratedb_layer
1111

1212

tests/testing/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)