Skip to content

Merge to Master #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
# Python-API-Testing
Testing Python APIs

## Sections.
- Introduction - Brief intro of the article and setup of the application.
- Test Driven Development(TDD) - A bit of explanation on TDD.
- Utilizing Mocks - Explain the concept of mocking and different ways of mocking as follows.
- Using Decorators
- Using a Context Manager
- Using a Patcher
- Mocking the whole function behavior - Demonstrate and explain how its done.
- Mocking third party functions - Demonstrate and explain how to mock out own functions/modules in other functions.
- ~Continuous integration with Circle CI - Brief walk through of how to combine testing and CI to make our development smooth, use case Github and Circle CI.~
- Conclusion - Brief summary touching on mocking and CI.

## Setup.
```sh
$ git clone [email protected]:kimobrian/Python-API-Testing.git
$ cd Python-API-Testing
$ virtualenv -p python3 venv # Create virtual environment
$ source venv/bin/activate # Activate virtual environment
$ pip install -r requirements.txt
```
Empty file added __init__.py
Empty file.
11 changes: 11 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
machine:
python:
version: 3.5.2

dependencies:
override:
- pip install -r requirements.txt

test:
override:
- nose2 --verbose
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
nose2==0.6.5
requests==2.18.4
21 changes: 21 additions & 0 deletions users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import requests
import json

USERS_URL = 'http://jsonplaceholder.typicode.com/users'


def get_users():
"""Get list of users"""
response = requests.get(USERS_URL)
if response.ok:
return response
else:
return None


def get_user(user_id):
"""Get a single user using their ID"""
all_users = get_users().json()
for user in all_users:
if user['id'] == user_id:
return user
Empty file added users_test/__init__.py
Empty file.
103 changes: 103 additions & 0 deletions users_test/test_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import unittest
from users import get_users, get_user
from unittest.mock import patch, Mock


class BasicTests(unittest.TestCase):
@patch('users.requests.get') # Mock 'requests' module 'get' method.
def test_request_response_with_decorator(self, mock_get):
"""Mocking using a decorator"""
mock_get.return_value.status_code = 200 # Mock status code of response.
response = get_users()

# Assert that the request-response cycle completed successfully.
self.assertEqual(response.status_code, 200)

def test_request_response_with_context_manager(self):
"""Mocking using a context manager"""
with patch('users.requests.get') as mock_get:
# Configure the mock to return a response with status code 200.
mock_get.return_value.status_code = 200

# Call the function, which will send a request to the server.
response = get_users()

# Assert that the request-response cycle completed successfully.
self.assertEqual(response.status_code, 200)

def test_request_response_with_patcher(self):
"""Mocking using a patcher"""
mock_get_patcher = patch('users.requests.get')
users = [{
"id": 0,
"first_name": "Dell",
"last_name": "Norval",
"phone": "994-979-3976"
}]

# Start patching 'requests.get'.
mock_get = mock_get_patcher.start()

# Configure the mock to return a response with status code 200.
mock_get.return_value = Mock(status_code=200)
mock_get.return_value.json.return_value = users

# Call the service, which will send a request to the server.
response = get_users()

# Stop patching 'requests'.
mock_get_patcher.stop()

# Assert that the request-response cycle completed successfully.
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), users)

def test_mock_whole_function(self):
"""Mocking a whole function"""
mock_get_patcher = patch('users.requests.get')
users = [{
"id": 0,
"first_name": "Dell",
"last_name": "Norval",
"phone": "994-979-3976"
}]

# Start patching 'requests.get'.
mock_get = mock_get_patcher.start()

# Configure the mock to return a response with status code 200 and a list of users.
mock_get.return_value = Mock(status_code = 200)
mock_get.return_value.json.return_value = users

# Call the service, which will send a request to the server.
response = get_users()

# Stop patching 'requests'.
mock_get_patcher.stop()

# Assert that the request-response cycle completed successfully.
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), users)

@patch('users.get_users')
def test_get_one_user(self, mock_get_users):
"""
Test for getting one user using their userID
Demonstrates mocking third party functions
"""
users = [
{'phone': '514-794-6957', 'first_name': 'Brant',
'last_name': 'Mekhi', 'id': 0},
{'phone': '772-370-0117', 'first_name': 'Thalia',
'last_name': 'Kenyatta', 'id': 1},
{'phone': '176-290-7637', 'first_name': 'Destin',
'last_name': 'Soledad', 'id': 2}
]
mock_get_users.return_value = Mock()
mock_get_users.return_value.json.return_value = users
user = get_user(2)
self.assertEqual(user, users[2])


if __name__ == "__main__":
unittest.main()