Skip to content

Commit 9fc2353

Browse files
committed
Update contributing guide. Update tests to use default client fixtures.
1 parent fa0c502 commit 9fc2353

File tree

4 files changed

+92
-29
lines changed

4 files changed

+92
-29
lines changed

docs/source/contributors_guide/contributing.rst

+35-12
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,47 @@ You'll see a different output since the documentation is build with
4747
Testing
4848
-------
4949

50-
If you implemented a feature or fixed a bug, please add tests for it.
50+
.. warning::
51+
If you are implementing features or fixing bugs, you are expected to have
52+
all of the three API keys (ATD, Sulu, and RapidAPI) setup and set in you
53+
environment variables - ``JUDGE0_SULU_API_KEY``, ``JUDGE0_RAPID_API_KEY``,
54+
and ``JUDGE0_ATD_API_KEY``.
5155

52-
Unfortunately, at the moment you cannot run full test suite because it requires
53-
access to API keys for all implemented API hubs (ATD, Sulu, and RapidAPI) and
54-
a private Judge0 instance. To partially address this situation, you can run and
55-
test your implemented feature and tests locally and use the GitHub CI pipeline
56-
to run the full test suite.
56+
Every bug fix or new feature should have tests for it. The tests are located in
57+
the ``tests`` directory and are written using `pytest <https://docs.pytest.org/en/stable/>`_.
5758

58-
To run the tests locally, you can use the following command:
59+
While working with the tests, you should use the following fixtures:
5960

60-
.. code-block:: console
61+
* ``default_ce_client`` - a client, chosen based on the environment variables set, that uses the CE flavor of the client.
62+
* ``default_extra_ce_client`` - a client, chosen based on the environment variables set, that uses the Extra CE flavor of the client.
6163

62-
$ pytest -svv tests -k '<test_name>'
64+
The ``default_ce_client`` and ``default_extra_ce_client`` are fixtures that
65+
return a client based on the environment variables set. This enables you to
66+
run the full test suite locally, but also to run the tests on the CI pipeline
67+
without changing the tests.
6368

64-
To make the test compatible with the CI pipeline, you should use one of the
65-
client fixtures:
69+
You can use the fixtures in your tests like this:
6670

6771
.. code-block:: python
6872
6973
def test_my_test(request):
70-
client = request.getfixturevalue("judge0_ce_client") # or judge0_extra_ce_client
74+
client = request.getfixturevalue("default_ce_client") # or default_extra_ce_client
75+
76+
To run the tests locally, you can use the following command:
77+
78+
.. code-block:: console
79+
80+
$ pytest -svv tests -k '<test_name>'
81+
82+
This will enable you to run a single test, without incurring the cost of
83+
running the full test suite. If you want to run the full test suite, you can
84+
use the following command:
85+
86+
.. code-block:: console
87+
88+
$ pytest -svv tests
89+
90+
or you can create a draft PR and let the CI pipeline run the tests for you.
91+
The CI pipeline will run the tests on every PR, using a private instance
92+
of Judge0, so you can be sure that your changes are not breaking the existing
93+
functionality.

tests/conftest.py

+50-10
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,31 @@ def judge0_ce_client():
1313
api_key = os.getenv("JUDGE0_TEST_API_KEY")
1414
api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER")
1515
endpoint = os.getenv("JUDGE0_TEST_CE_ENDPOINT")
16-
client = clients.Client(
17-
endpoint=endpoint,
18-
auth_headers={api_key_header: api_key},
19-
)
20-
return client
16+
17+
if api_key is None or api_key_header is None or endpoint is None:
18+
return None
19+
else:
20+
client = clients.Client(
21+
endpoint=endpoint,
22+
auth_headers={api_key_header: api_key},
23+
)
24+
return client
2125

2226

2327
@pytest.fixture(scope="session")
2428
def judge0_extra_ce_client():
2529
api_key = os.getenv("JUDGE0_TEST_API_KEY")
2630
api_key_header = os.getenv("JUDGE0_TEST_API_KEY_HEADER")
2731
endpoint = os.getenv("JUDGE0_TEST_EXTRA_CE_ENDPOINT")
28-
client = clients.Client(
29-
endpoint=endpoint,
30-
auth_headers={api_key_header: api_key},
31-
)
32-
return client
32+
33+
if api_key is None or api_key_header is None or endpoint is None:
34+
return None
35+
else:
36+
client = clients.Client(
37+
endpoint=endpoint,
38+
auth_headers={api_key_header: api_key},
39+
)
40+
return client
3341

3442

3543
@pytest.fixture(scope="session")
@@ -63,12 +71,44 @@ def rapid_extra_ce_client():
6371
@pytest.fixture(scope="session")
6472
def sulu_ce_client():
6573
api_key = os.getenv("JUDGE0_SULU_API_KEY")
74+
if api_key is None:
75+
pytest.fail(
76+
"Sulu API key is not available for testing. Make sure to have "
77+
"JUDGE0_SULU_API_KEY in your environment variables."
78+
)
79+
6680
client = clients.SuluJudge0CE(api_key)
6781
return client
6882

6983

7084
@pytest.fixture(scope="session")
7185
def sulu_extra_ce_client():
7286
api_key = os.getenv("JUDGE0_SULU_API_KEY")
87+
if api_key is None:
88+
pytest.fail(
89+
"Sulu API key is not available for testing. Make sure to have "
90+
"JUDGE0_SULU_API_KEY in your environment variables."
91+
)
92+
7393
client = clients.SuluJudge0ExtraCE(api_key)
7494
return client
95+
96+
97+
@pytest.fixture(scope="session")
98+
def default_ce_client(judge0_ce_client, sulu_ce_client):
99+
if judge0_ce_client is not None:
100+
return judge0_ce_client
101+
if sulu_ce_client is not None:
102+
return sulu_ce_client
103+
104+
pytest.fail("No default CE client available for testing.")
105+
106+
107+
@pytest.fixture(scope="session")
108+
def default_extra_ce_client(judge0_extra_ce_client, sulu_extra_ce_client):
109+
if judge0_extra_ce_client is not None:
110+
return judge0_extra_ce_client
111+
if sulu_extra_ce_client is not None:
112+
return sulu_extra_ce_client
113+
114+
pytest.fail("No default Extra CE client available for testing.")

tests/test_api_test_cases.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def test_single_test_case_in_iterable(self, test_cases, stdin, expected_output):
207207
def test_test_cases_from_run(
208208
source_code_or_submissions, test_cases, expected_status, request
209209
):
210-
client = request.getfixturevalue("judge0_ce_client")
210+
client = request.getfixturevalue("default_ce_client")
211211

212212
if isinstance(source_code_or_submissions, str):
213213
submissions = judge0.run(
@@ -254,7 +254,7 @@ def test_test_cases_from_run(
254254
],
255255
)
256256
def test_no_test_cases(submissions, expected_status, request):
257-
client = request.getfixturevalue("judge0_ce_client")
257+
client = request.getfixturevalue("default_ce_client")
258258

259259
submissions = judge0.run(
260260
client=client,
@@ -269,7 +269,7 @@ def test_no_test_cases(submissions, expected_status, request):
269269

270270
@pytest.mark.parametrize("n_submissions", [42, 84])
271271
def test_batched_test_cases(n_submissions, request):
272-
client = request.getfixturevalue("judge0_ce_client")
272+
client = request.getfixturevalue("default_ce_client")
273273
submissions = [
274274
Submission(source_code=f"print({i})", expected_output=f"{i}")
275275
for i in range(n_submissions)

tests/test_submission.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def test_from_json():
5252

5353

5454
def test_status_before_and_after_submission(request):
55-
client = request.getfixturevalue("judge0_ce_client")
55+
client = request.getfixturevalue("default_ce_client")
5656
submission = Submission(source_code='print("Hello World!")')
5757

5858
assert submission.status is None
@@ -65,7 +65,7 @@ def test_status_before_and_after_submission(request):
6565

6666

6767
def test_is_done(request):
68-
client = request.getfixturevalue("judge0_ce_client")
68+
client = request.getfixturevalue("default_ce_client")
6969
submission = Submission(source_code='print("Hello World!")')
7070

7171
assert submission.status is None
@@ -77,7 +77,7 @@ def test_is_done(request):
7777

7878

7979
def test_language_before_and_after_execution(request):
80-
client = request.getfixturevalue("judge0_ce_client")
80+
client = request.getfixturevalue("default_ce_client")
8181
code = """\
8282
public class Main {
8383
public static void main(String[] args) {
@@ -97,7 +97,7 @@ def test_language_before_and_after_execution(request):
9797

9898

9999
def test_language_executable(request):
100-
client = request.getfixturevalue("judge0_ce_client")
100+
client = request.getfixturevalue("default_ce_client")
101101
code = b64decode(
102102
"f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAAABAAAAAAABAAAAAAAAAAEAQAAAAAAAAAAAAAEAAOAABAEAABAADAAEAAAAFAAAAABAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAJQAAAAAAAAAlAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHAjVANsAG+GABAAInHDwUx/41HPA8FAGhlbGxvLCB3b3JsZAoALnNoc3RydGFiAC50ZXh0AC5yb2RhdGEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAAGAAAAAAAAAAAAQAAAAAAAABAAAAAAAAAXAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAABEAAAABAAAAAgAAAAAAAAAYAEAAAAAAABgQAAAAAAAADQAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAlEAAAAAAAABkAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAA" # noqa: E501
103103
)

0 commit comments

Comments
 (0)