openapi/python_examples: Replace TEST_FUNCTIONS with a decorator.

Use a decorator called openapi_test_function instead of the hard-coded
TEST_FUNCTIONS list for increased readability and maintainablity (at
the cost of performance).
This commit is contained in:
Hemanth V. Alluri 2019-08-07 23:33:43 +05:30 committed by Tim Abbott
parent 4c08a840d0
commit c2f9227892
1 changed files with 59 additions and 50 deletions

View File

@ -1,4 +1,4 @@
from typing import Dict, Any, Optional, Iterable
from typing import Dict, Any, Optional, Iterable, Callable
import json
import os
@ -11,6 +11,18 @@ from zulip import Client
ZULIP_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
FIXTURE_PATH = os.path.join(ZULIP_DIR, 'templates', 'zerver', 'api', 'fixtures.json')
TEST_FUNCTIONS = dict() # type: Dict[str, Callable[..., None]]
def openapi_test_function(endpoint: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
""" A very simple decorator that just takes attendance of which openapi test functions are
being used for which endpoint. While this may be slower than hardcoding a dictionary, it's
easier to maintain.
Example usage: @openapi_test_function("/messages/render:post") """
def wrapper(test_func: Callable[..., Any]) -> Callable[..., Any]:
TEST_FUNCTIONS[endpoint] = test_func
return test_func
return wrapper
def load_api_fixtures():
# type: () -> Dict[str, Any]
with open(FIXTURE_PATH, 'r') as fp:
@ -19,6 +31,7 @@ def load_api_fixtures():
FIXTURES = load_api_fixtures()
@openapi_test_function("/users/me/subscriptions:post")
def add_subscriptions(client):
# type: (Client) -> None
@ -97,6 +110,7 @@ def test_authorization_errors_fatal(client, nonadmin_client):
validate_against_openapi_schema(result, '/users/me/subscriptions', 'post',
'400_unauthorized_errors_fatal_true')
@openapi_test_function("/users/{email}/presence:get")
def get_user_presence(client):
# type: (Client) -> None
@ -107,6 +121,7 @@ def get_user_presence(client):
validate_against_openapi_schema(result, '/users/{email}/presence', 'get', '200')
@openapi_test_function("/users/me/presence:post")
def update_presence(client):
# type: (Client) -> None
request = {
@ -119,6 +134,7 @@ def update_presence(client):
assert result['result'] == 'success'
@openapi_test_function("/users:post")
def create_user(client):
# type: (Client) -> None
@ -140,6 +156,7 @@ def create_user(client):
validate_against_openapi_schema(result, '/users', 'post', '400')
@openapi_test_function("/users:get")
def get_members(client):
# type: (Client) -> None
@ -164,6 +181,7 @@ def get_members(client):
validate_against_openapi_schema(result, '/users', 'get', '200')
assert result['members'][0]['avatar_url'] is None
@openapi_test_function("/realm/filters:get")
def get_realm_filters(client):
# type: (Client) -> None
@ -174,6 +192,7 @@ def get_realm_filters(client):
validate_against_openapi_schema(result, '/realm/filters', 'get', '200')
@openapi_test_function("/realm/filters:post")
def add_realm_filter(client):
# type: (Client) -> None
@ -186,6 +205,7 @@ def add_realm_filter(client):
validate_against_openapi_schema(result, '/realm/filters', 'post', '200')
@openapi_test_function("/realm/filters/{filter_id}:delete")
def remove_realm_filter(client):
# type: (Client) -> None
@ -196,6 +216,7 @@ def remove_realm_filter(client):
validate_against_openapi_schema(result, '/realm/filters/{filter_id}', 'delete', '200')
@openapi_test_function("/users/me:get")
def get_profile(client):
# type: (Client) -> None
@ -207,6 +228,7 @@ def get_profile(client):
validate_against_openapi_schema(result, '/users/me', 'get', '200')
@openapi_test_function("/get_stream_id:get")
def get_stream_id(client):
# type: (Client) -> int
@ -220,6 +242,7 @@ def get_stream_id(client):
return result['stream_id']
@openapi_test_function("/streams/{stream_id}:delete")
def delete_stream(client, stream_id):
# type: (Client, int) -> None
result = client.add_subscriptions(
@ -240,6 +263,7 @@ def delete_stream(client, stream_id):
assert result['result'] == 'success'
@openapi_test_function("/streams:get")
def get_streams(client):
# type: (Client) -> None
@ -261,6 +285,7 @@ def get_streams(client):
validate_against_openapi_schema(result, '/streams', 'get', '200')
assert len(result['streams']) == 4
@openapi_test_function("/streams/{stream_id}:patch")
def update_stream(client, stream_id):
# type: (Client, int) -> None
@ -278,6 +303,7 @@ def update_stream(client, stream_id):
validate_against_openapi_schema(result, '/streams/{stream_id}', 'patch', '200')
assert result['result'] == 'success'
@openapi_test_function("/user_groups:get")
def get_user_groups(client):
# type: (Client) -> int
@ -314,6 +340,7 @@ def get_user_agent(client):
result = client.get_user_agent()
assert result.startswith('ZulipPython/')
@openapi_test_function("/users/me/subscriptions:get")
def list_subscriptions(client):
# type: (Client) -> None
# {code_example|start}
@ -327,6 +354,7 @@ def list_subscriptions(client):
streams = [s for s in result['subscriptions'] if s['name'] == 'new stream']
assert streams[0]['description'] == 'New stream for testing'
@openapi_test_function("/users/me/subscriptions:delete")
def remove_subscriptions(client):
# type: (Client) -> None
@ -357,6 +385,7 @@ def remove_subscriptions(client):
validate_against_openapi_schema(result, '/users/me/subscriptions',
'delete', '200')
@openapi_test_function("/users/me/subscriptions/muted_topics:patch")
def toggle_mute_topic(client):
# type: (Client) -> None
@ -401,6 +430,7 @@ def toggle_mute_topic(client):
'/users/me/subscriptions/muted_topics',
'patch', '200')
@openapi_test_function("/mark_all_as_read:post")
def mark_all_as_read(client):
# type: (Client) -> None
@ -411,6 +441,7 @@ def mark_all_as_read(client):
validate_against_openapi_schema(result, '/mark_all_as_read', 'post', '200')
@openapi_test_function("/mark_stream_as_read:post")
def mark_stream_as_read(client):
# type: (Client) -> None
@ -421,6 +452,7 @@ def mark_stream_as_read(client):
validate_against_openapi_schema(result, '/mark_stream_as_read', 'post', '200')
@openapi_test_function("/mark_topic_as_read:post")
def mark_topic_as_read(client):
# type: (Client) -> None
@ -434,6 +466,7 @@ def mark_topic_as_read(client):
validate_against_openapi_schema(result, '/mark_stream_as_read', 'post', '200')
@openapi_test_function("/users/me/subscriptions/properties:post")
def update_subscription_settings(client):
# type: (Client) -> None
@ -456,6 +489,7 @@ def update_subscription_settings(client):
'/users/me/subscriptions/properties',
'POST', '200')
@openapi_test_function("/messages/render:post")
def render_message(client):
# type: (Client) -> None
@ -469,6 +503,7 @@ def render_message(client):
validate_against_openapi_schema(result, '/messages/render', 'post', '200')
@openapi_test_function("/messages:get")
def get_messages(client):
# type: (Client) -> None
@ -489,6 +524,7 @@ def get_messages(client):
validate_against_openapi_schema(result, '/messages', 'get', '200')
assert len(result['messages']) <= request['num_before']
@openapi_test_function("/messages/{message_id}:get")
def get_raw_message(client, message_id):
# type: (Client, int) -> None
@ -502,6 +538,7 @@ def get_raw_message(client, message_id):
validate_against_openapi_schema(result, '/messages/{message_id}', 'get',
'200')
@openapi_test_function("/messages:post")
def send_message(client):
# type: (Client) -> int
@ -564,6 +601,7 @@ def add_reaction(client, message_id):
assert result['result'] == 'success'
@openapi_test_function("/messages/{message_id}/reactions:delete")
def remove_reaction(client, message_id):
# type: (Client, int) -> None
request = {
@ -602,6 +640,7 @@ def test_private_message_invalid_recipient(client):
validate_against_openapi_schema(result, '/messages', 'post',
'400_non_existing_user')
@openapi_test_function("/messages/{message_id}:patch")
def update_message(client, message_id):
# type: (Client, int) -> None
@ -649,6 +688,7 @@ def test_update_message_edit_permission_error(client, nonadmin_client):
fixture = FIXTURES['update-message-edit-permission-error']
test_against_fixture(result, fixture)
@openapi_test_function("/messages/{message_id}:delete")
def delete_message(client, message_id):
# type: (Client, int) -> None
@ -675,6 +715,7 @@ def test_delete_message_edit_permission_error(client, nonadmin_client):
validate_against_openapi_schema(result, '/messages/{message_id}', 'delete',
'400_not_admin')
@openapi_test_function("/messages/{message_id}/history:get")
def get_message_history(client, message_id):
# type: (Client, int) -> None
@ -686,6 +727,7 @@ def get_message_history(client, message_id):
validate_against_openapi_schema(result, '/messages/{message_id}/history',
'get', '200')
@openapi_test_function("/realm/emoji:get")
def get_realm_emoji(client):
# type: (Client) -> None
@ -695,6 +737,7 @@ def get_realm_emoji(client):
validate_against_openapi_schema(result, '/realm/emoji', 'GET', '200')
@openapi_test_function("/messages/flags:post")
def update_message_flags(client):
# type: (Client) -> None
@ -735,6 +778,7 @@ def update_message_flags(client):
validate_against_openapi_schema(result, '/messages/flags', 'post',
'200')
@openapi_test_function("/register:post")
def register_queue(client):
# type: (Client) -> str
@ -748,6 +792,7 @@ def register_queue(client):
validate_against_openapi_schema(result, '/register', 'post', '200')
return result['queue_id']
@openapi_test_function("/events:delete")
def deregister_queue(client, queue_id):
# type: (Client, str) -> None
@ -763,6 +808,7 @@ def deregister_queue(client, queue_id):
result = client.deregister(queue_id)
validate_against_openapi_schema(result, '/events', 'delete', '400')
@openapi_test_function("/server_settings:get")
def get_server_settings(client):
# type: (Client) -> None
@ -773,6 +819,7 @@ def get_server_settings(client):
validate_against_openapi_schema(result, '/server_settings', 'get', '200')
@openapi_test_function("/settings/notifications:patch")
def update_notification_settings(client):
# type: (Client) -> None
@ -787,6 +834,7 @@ def update_notification_settings(client):
validate_against_openapi_schema(result, '/settings/notifications', 'patch', '200')
@openapi_test_function("/user_uploads:post")
def upload_file(client):
# type: (Client) -> None
path_to_file = os.path.join(ZULIP_DIR, 'zerver', 'tests', 'images', 'img.jpg')
@ -803,6 +851,7 @@ def upload_file(client):
validate_against_openapi_schema(result, '/user_uploads', 'post', '200')
@openapi_test_function("/users/me/{stream_id}/topics:get")
def get_stream_topics(client, stream_id):
# type: (Client, int) -> None
@ -813,6 +862,7 @@ def get_stream_topics(client, stream_id):
validate_against_openapi_schema(result, '/users/me/{stream_id}/topics',
'get', '200')
@openapi_test_function("/typing:post")
def set_typing_status(client):
# type: (Client) -> None
@ -838,6 +888,7 @@ def set_typing_status(client):
validate_against_openapi_schema(result, '/typing', 'post', '200')
@openapi_test_function("/realm/emoji/{emoji_name}:post")
def upload_custom_emoji(client):
# type: (Client) -> None
emoji_path = os.path.join(ZULIP_DIR, 'zerver', 'tests', 'images', 'img.jpg')
@ -857,12 +908,14 @@ def upload_custom_emoji(client):
'/realm/emoji/{emoji_name}',
'post', '200')
@openapi_test_function("/users/me/alert_words:get")
def get_alert_words(client):
# type: (Client) -> None
result = client.get_alert_words()
assert result['result'] == 'success'
@openapi_test_function("/users/me/alert_words:post")
def add_alert_words(client):
# type: (Client) -> None
word = ['foo', 'bar']
@ -871,6 +924,7 @@ def add_alert_words(client):
assert result['result'] == 'success'
@openapi_test_function("/users/me/alert_words:delete")
def remove_alert_words(client):
# type: (Client) -> None
word = ['foo']
@ -879,6 +933,7 @@ def remove_alert_words(client):
assert result['result'] == 'success'
@openapi_test_function("/user_groups/create:post")
def create_user_group(client):
# type: (Client) -> None
# {code_example|start}
@ -894,6 +949,7 @@ def create_user_group(client):
assert result['result'] == 'success'
@openapi_test_function("/user_groups/{group_id}:patch")
def update_user_group(client, group_id):
# type: (Client, int) -> None
# {code_example|start}
@ -907,6 +963,7 @@ def update_user_group(client, group_id):
# {code_example|end}
assert result['result'] == 'success'
@openapi_test_function("/user_groups/{group_id}:delete")
def remove_user_group(client, group_id):
# type: (Client, int) -> None
# {code_example|start}
@ -916,6 +973,7 @@ def remove_user_group(client, group_id):
validate_against_openapi_schema(result, '/user_groups/{group_id}', 'delete', '200')
assert result['result'] == 'success'
@openapi_test_function("/user_groups/{group_id}/members:post")
def update_user_group_members(client, group_id):
# type: (Client, int) -> None
request = {
@ -947,57 +1005,8 @@ def test_invalid_stream_error(client):
validate_against_openapi_schema(result, '/get_stream_id', 'get', '400')
TEST_FUNCTIONS = {
'/mark_all_as_read:post': mark_all_as_read,
'/mark_stream_as_read:post': mark_stream_as_read,
'/mark_topic_as_read:post': mark_topic_as_read,
'/messages/render:post': render_message,
'/messages:get': get_messages,
'/messages:post': send_message,
'/messages/{message_id}:get': get_raw_message,
'/messages/{message_id}:patch': update_message,
'/messages/{message_id}:delete': delete_message,
'/messages/{message_id}/history:get': get_message_history,
'/messages/flags:post': update_message_flags,
'/get_stream_id:get': get_stream_id,
'/streams/{stream_id}:delete': delete_stream,
'/streams/{stream_id}:patch': update_stream,
'/streams:get': get_streams,
'/users:post': create_user,
'/users/me:get': get_profile,
'/users/{email}/presence:get': get_user_presence,
'/users/me/presence:post': update_presence,
'/users/me/subscriptions:get': list_subscriptions,
'/users/me/subscriptions:post': add_subscriptions,
'/users/me/subscriptions:delete': remove_subscriptions,
'/users/me/subscriptions/muted_topics:patch': toggle_mute_topic,
'/users/me/subscriptions/properties:post': update_subscription_settings,
'/users:get': get_members,
'/realm/emoji:get': get_realm_emoji,
'/realm/emoji/{emoji_name}:post': upload_custom_emoji,
'/realm/filters:get': get_realm_filters,
'/realm/filters:post': add_realm_filter,
'/realm/filters/{filter_id}:delete': remove_realm_filter,
'/register:post': register_queue,
'/events:delete': deregister_queue,
'/server_settings:get': get_server_settings,
'/settings/notifications:patch': update_notification_settings,
'/user_uploads:post': upload_file,
'/users/me/{stream_id}/topics:get': get_stream_topics,
'/typing:post': set_typing_status,
'/user_groups:get': get_user_groups,
'/user_groups/create:post': create_user_group,
'/user_groups/{group_id}:patch': update_user_group,
'/user_groups/{group_id}:delete': remove_user_group,
'/user_groups/{group_id}/members:post': update_user_group_members,
'/users/me/alert_words:get': get_alert_words,
'/users/me/alert_words:post': add_alert_words,
'/users/me/alert_words:delete': remove_alert_words,
'/messages/{message_id}/reactions:delete': remove_reaction
}
# SETUP METHODS FOLLOW
def test_against_fixture(result, fixture, check_if_equal=[], check_if_exists=[]):
# type: (Dict[str, Any], Dict[str, Any], Optional[Iterable[str]], Optional[Iterable[str]]) -> None
assertLength(result, fixture)