Skip to content

Commit abc7a02

Browse files
committed
test: add testsuite for README code, fix messages, align example outputs
1 parent aba2e67 commit abc7a02

9 files changed

Lines changed: 131 additions & 13 deletions
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"orders" database created.
2-
You have created the document:
2+
You have created the document. Response body:
33
{
4-
"_id": "example",
5-
"_rev": "1-1b403633540686aa32d013fda9041a5d",
6-
"name": "Bob Smith",
7-
"joined": "2019-01-24T10:42:99.000Z"
4+
"ok": true,
5+
"id": "example",
6+
"rev": "1-1b403633540686aa32d013fda9041a5d"
87
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Cannot delete document because either "orders" database or "example" document was not found.
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
Server Version: 2.1.1
1+
Server Version: 3.2.1
22
Document count in "orders" database is 1.
33
Document retrieved from database:
44
{
55
"_id": "example",
66
"_rev": "1-1b403633540686aa32d013fda9041a5d",
77
"name": "Bob Smith",
8-
"joined": "2019-01-24T10:42:99.000Z"
8+
"joined": "2019-01-24T10:42:59.000Z"
99
}

‎test/examples/output/update_doc.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
You have updated the document:
12
{
23
"_id": "example",
34
"_rev": "2-4e2178e85cffb32d38ba4e451f6ca376",
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
You have updated the document:
2+
{
3+
"_id": "example",
4+
"_rev": "3-4f1787d7a0520f825bd36822d7be627a",
5+
"name": "Bob Smith",
6+
"address": "19 Front Street, Darlington, DL5 1TY"
7+
}

‎test/examples/src/create_db_and_doc.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
import json
18+
1719
from ibm_cloud_sdk_core import ApiException
1820
from ibmcloudant.cloudant_v1 import CloudantV1, Document
1921

@@ -65,7 +67,5 @@
6567
"""
6668
# =====================================================================
6769

68-
# Keeping track of the revision number of the document object
69-
# is necessary for further UPDATE/DELETE operations:
70-
example_document.rev = create_document_response["rev"]
71-
print(f'You have created the document:\n{example_document}')
70+
response_body = json.dumps(create_document_response, indent=2)
71+
print(f'You have created the document. Response body:\n{response_body}')

‎test/examples/src/delete_doc.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,5 @@
4343
except ApiException as ae:
4444
if ae.status_code == 404:
4545
print('Cannot delete document because either ' +
46-
f'"{example_db_name}" database or "{example_doc_id}"' +
46+
f'"{example_db_name}" database or "{example_doc_id}" ' +
4747
'document was not found.')

‎test/examples/src/test_readme.py‎

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# © Copyright IBM Corporation 2025. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
# Testsuite for the examples in the README file.
17+
18+
import unittest
19+
import subprocess
20+
import sys
21+
import os
22+
import requests
23+
from pathlib import Path
24+
25+
parent_dir = Path(__file__).resolve().parent.parent
26+
27+
28+
class TestReadmeExamples(unittest.TestCase):
29+
30+
@classmethod
31+
def setUpClass(cls):
32+
"""Set up test environment before all tests"""
33+
# Get WireMock URL from environment
34+
wiremock_url = os.environ.get('WIREMOCK_URL')
35+
36+
# Reset WireMock scenarios
37+
requests.post(f"{wiremock_url}/__admin/scenarios/reset")
38+
39+
# Set authentication environment variables
40+
os.environ['CLOUDANT_URL'] = wiremock_url
41+
os.environ['CLOUDANT_AUTH_TYPE'] = 'noauth'
42+
43+
def run_example_and_check_output(self, script_path, expected_output_path):
44+
env = os.environ.copy()
45+
46+
# Ensure the subprocess uses the same site-packages
47+
python_path = sys.path.copy()
48+
if 'PYTHONPATH' in env:
49+
python_path.append(env['PYTHONPATH'])
50+
env['PYTHONPATH'] = os.pathsep.join(python_path)
51+
52+
result = subprocess.run(
53+
[sys.executable, str(script_path)],
54+
capture_output=True,
55+
text=True,
56+
timeout=5,
57+
env=env,
58+
)
59+
if result.returncode != 0:
60+
self.fail(f"Script failed with return code {result.returncode}\n"
61+
f"STDOUT:\n{result.stdout}\n"
62+
f"STDERR:\n{result.stderr}")
63+
64+
with open(expected_output_path, 'r') as f:
65+
expected_output = f.read().strip()
66+
67+
actual_output = result.stdout.strip()
68+
69+
self.assertEqual(actual_output, expected_output,
70+
f"Output mismatch.\nExpected:\n{expected_output}\n\nGot:\n{actual_output}")
71+
72+
def test_1_create_db_and_doc_example(self):
73+
"""Creates db and doc for the first time"""
74+
script = parent_dir / "src" / "create_db_and_doc.py"
75+
output = parent_dir / "output" / "create_db_and_doc.txt"
76+
self.run_example_and_check_output(script, output)
77+
78+
def test_2_get_info_from_existing_database_example(self):
79+
"""Gets document from orders database"""
80+
script = parent_dir / "src" / "get_info_from_existing_database.py"
81+
output = parent_dir / "output" / "get_info_from_existing_database.txt"
82+
self.run_example_and_check_output(script, output)
83+
84+
def test_3_update_doc_example_first_time(self):
85+
"""Updates doc for the first time"""
86+
script = parent_dir / "src" / "update_doc.py"
87+
output = parent_dir / "output" / "update_doc.txt"
88+
self.run_example_and_check_output(script, output)
89+
90+
def test_4_update_doc_example_second_time(self):
91+
"""Updates doc for the second time"""
92+
script = parent_dir / "src" / "update_doc.py"
93+
output = parent_dir / "output" / "update_doc2.txt"
94+
self.run_example_and_check_output(script, output)
95+
96+
def test_5_delete_doc_example_existing(self):
97+
"""Deletes existing doc"""
98+
script = parent_dir / "src" / "delete_doc.py"
99+
output = parent_dir / "output" / "delete_doc.txt"
100+
self.run_example_and_check_output(script, output)
101+
102+
def test_6_delete_doc_example_non_existing(self):
103+
"""Deletes non-existing doc"""
104+
script = parent_dir / "src" / "delete_doc.py"
105+
output = parent_dir / "output" / "delete_doc2.txt"
106+
self.run_example_and_check_output(script, output)
107+
108+
109+
if __name__ == '__main__':
110+
unittest.main()

‎test/examples/src/update_doc.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@
8989

9090
except ApiException as ae:
9191
if ae.status_code == 404:
92-
print('Cannot delete document because either ' +
92+
print('Cannot update document because either ' +
9393
f'"{example_db_name}" database or "{example_doc_id}" ' +
9494
'document was not found.')

0 commit comments

Comments
 (0)