Skip to content

Commit e5fe846

Browse files
author
Gaurav Singh
committed
- Created BaseClient with default headers
- Moved create_data() into conftest file - Introduced an assertion helper to abstract common assertions - Added remaining methods to people_client.py - Moved search related methods to a people_helpers.py - Refactored these methods out of the test file - Created APIRequest as a wrapper over requests methods (always wrap third party library if possible)
1 parent 6204734 commit e5fe846

File tree

8 files changed

+94
-84
lines changed

8 files changed

+94
-84
lines changed

clients/people/base_client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class BaseClient:
2+
def __init__(self):
3+
self.headers = {
4+
'Content-Type': 'application/json',
5+
'Accept': 'application/json'
6+
}

clients/people/people_client.py

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,23 @@
11
from json import dumps
22
from uuid import uuid4
33

4-
import requests
5-
from assertpy import assert_that
6-
4+
from clients.people.base_client import BaseClient
75
from config import BASE_URI
8-
from utils.request import get, post
6+
from utils.request import APIRequest
97

108

11-
class PeopleClient:
9+
class PeopleClient(BaseClient):
1210
def __init__(self):
11+
super().__init__()
12+
1313
self.base_url = BASE_URI
14+
self.request = APIRequest()
1415

1516
def create_person(self, body=None):
16-
last_name, response = self.create_person_with_unique_last_name(body)
17-
assert_that(response.status_code, description='Person not created').is_equal_to(requests.codes.no_content)
17+
last_name, response = self.__create_person_with_unique_last_name(body)
1818
return last_name, response
1919

20-
def read_one_person_by_id(self, person_id):
21-
pass
22-
23-
def read_all_persons(self):
24-
return get(self.base_url)
25-
26-
def update_person(self):
27-
pass
28-
29-
def delete_person(self, person_id):
30-
delete_url = f'{BASE_URI}/{person_id}'
31-
32-
33-
def create_person_with_unique_last_name(self, body=None):
20+
def __create_person_with_unique_last_name(self, body=None):
3421
if body is None:
3522
last_name = f'User {str(uuid4())}'
3623
payload = dumps({
@@ -41,10 +28,18 @@ def create_person_with_unique_last_name(self, body=None):
4128
last_name = body['lname']
4229
payload = dumps(body)
4330

44-
headers = {
45-
'Content-Type': 'application/json',
46-
'Accept': 'application/json'
47-
}
48-
49-
response = post(self.base_url, payload, headers)
31+
response = self.request.post(self.base_url, payload, self.headers)
5032
return last_name, response
33+
34+
def read_one_person_by_id(self, person_id):
35+
pass
36+
37+
def read_all_persons(self):
38+
return self.request.get(self.base_url)
39+
40+
def update_person(self):
41+
pass
42+
43+
def delete_person(self, person_id):
44+
url = f'{BASE_URI}/{person_id}'
45+
return self.request.delete(url)

endpoints/__init__.py

Whitespace-only changes.

tests/assertions/people_assertions.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from assertpy import assert_that
2+
3+
4+
def assert_people_have_person_with_first_name(response, first_name):
5+
assert_that(response.as_dict).extracting('fname').is_not_empty().contains(first_name)
6+
7+
8+
def assert_person_is_present(is_new_user_created):
9+
assert_that(is_new_user_created).is_not_empty()

tests/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import random
2+
3+
import pytest
4+
5+
from utils.file_reader import read_file
6+
7+
8+
@pytest.fixture
9+
def create_data():
10+
payload = read_file('create_person.json')
11+
12+
random_no = random.randint(0, 1000)
13+
last_name = f'Olabini{random_no}'
14+
15+
payload['lname'] = last_name
16+
yield payload

tests/helpers/people_helpers.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,10 @@
1+
from jsonpath_ng import parse
2+
3+
14
def search_created_user_in(peoples, last_name):
2-
return [person for person in peoples if person['lname'] == last_name]
5+
return [person for person in peoples if person['lname'] == last_name][0]
6+
7+
8+
def search_nodes_using_json_path(peoples, json_path):
9+
jsonpath_expr = parse(json_path)
10+
return [match.value for match in jsonpath_expr.find(peoples)]

tests/people_test.py

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
import random
2-
from json import loads
3-
4-
import pytest
51
import requests
6-
from assertpy.assertpy import assert_that
7-
from jsonpath_ng import parse
82

93
from clients.people.people_client import PeopleClient
10-
from config import BASE_URI
11-
from tests.helpers.people_helpers import search_created_user_in
12-
from utils.file_reader import read_file
4+
from tests.assertions.people_assertions import *
5+
from tests.helpers.people_helpers import search_created_user_in, search_nodes_using_json_path
136

147
client = PeopleClient()
158

@@ -18,50 +11,35 @@ def test_read_all_has_kent():
1811
response = client.read_all_persons()
1912

2013
assert_that(response.status_code).is_equal_to(requests.codes.ok)
21-
assert_that(response.as_dict).extracting('fname').is_not_empty().contains('Kent')
14+
assert_people_have_person_with_first_name(response, first_name='Kent')
2215

2316

2417
def test_new_person_can_be_added():
2518
last_name, response = client.create_person()
26-
peoples = client.read_all_persons().as_dict
19+
assert_that(response.status_code, description='Person not created').is_equal_to(requests.codes.no_content)
2720

21+
peoples = client.read_all_persons().as_dict
2822
is_new_user_created = search_created_user_in(peoples, last_name)
29-
assert_that(is_new_user_created).is_not_empty()
23+
assert_person_is_present(is_new_user_created)
3024

3125

3226
def test_created_person_can_be_deleted():
33-
persons_last_name = client.create_person()
27+
persons_last_name, _ = client.create_person()
3428

3529
peoples = client.read_all_persons().as_dict
36-
new_person_id = search_created_user_in(peoples, persons_last_name)[0]['person_id']
30+
new_person_id = search_created_user_in(peoples, persons_last_name)['person_id']
3731

3832
response = client.delete_person(new_person_id)
3933
assert_that(response.status_code).is_equal_to(requests.codes.ok)
4034

4135

42-
@pytest.fixture
43-
def create_data():
44-
payload = read_file('create_person.json')
45-
46-
random_no = random.randint(0, 1000)
47-
last_name = f'Olabini{random_no}'
48-
49-
payload['lname'] = last_name
50-
yield payload
51-
52-
5336
def test_person_can_be_added_with_a_json_template(create_data):
5437
client.create_person(create_data)
5538

56-
response = requests.get(BASE_URI)
57-
peoples = loads(response.text)
39+
response = client.read_all_persons()
40+
peoples = response.as_dict
5841

59-
# Get all last names for any object in the root array
60-
# Here $ = root, [*] represents any element in the array
61-
# Read full syntax: https://pypi.org/project/jsonpath-ng/
62-
jsonpath_expr = parse("$.[*].lname")
63-
result = [match.value for match in jsonpath_expr.find(peoples)]
64-
print(result)
42+
result = search_nodes_using_json_path(peoples, json_path="$.[*].lname")
6543

6644
expected_last_name = create_data['lname']
6745
assert_that(result).contains(expected_last_name)

utils/request.py

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,30 @@ class Response:
1111
headers: dict
1212

1313

14-
def __get_responses(response):
15-
status_code = response.status_code
16-
text = response.text
14+
class APIRequest:
15+
def get(self, url):
16+
response = requests.get(url)
17+
return self.__get_responses(response)
1718

18-
try:
19-
as_dict = response.json()
20-
except Exception:
21-
as_dict = {}
19+
def post(self, url, payload, headers):
20+
response = requests.post(url, data=payload, headers=headers)
21+
return self.__get_responses(response)
2222

23-
headers = response.headers
23+
def delete(self, url):
24+
response = requests.delete(url)
25+
return self.__get_responses(response)
2426

25-
return Response(
26-
status_code, text, as_dict, headers
27-
)
27+
def __get_responses(self, response):
28+
status_code = response.status_code
29+
text = response.text
2830

31+
try:
32+
as_dict = response.json()
33+
except Exception:
34+
as_dict = {}
2935

30-
def get(url):
31-
response = requests.get(url)
32-
return __get_responses(response)
36+
headers = response.headers
3337

34-
35-
def post(url, payload, headers):
36-
response = requests.post(url, data=payload, headers=headers)
37-
return __get_responses(response)
38-
39-
40-
def delete(url):
41-
response = requests.delete(url)
42-
return __get_responses(response)
38+
return Response(
39+
status_code, text, as_dict, headers
40+
)

0 commit comments

Comments
 (0)