Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Commit

Permalink
Merge 19b60ad into 27aaa73
Browse files Browse the repository at this point in the history
  • Loading branch information
ovv committed Jul 24, 2019
2 parents 27aaa73 + 19b60ad commit 67d2820
Show file tree
Hide file tree
Showing 13 changed files with 779 additions and 387 deletions.
4 changes: 4 additions & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ no_lines_before=FIRSTPARTY
skip=docs/conf.py
skip_glob=.tox,.eggs,build
not_skip=__init__.py
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Quickstart
from slack.io.sync import SlackAPI
session = requests.session()
slack_client = SlackAPI(token=TOKEN, session=session)
client = SlackAPI(token=TOKEN, session=session)
data = client.query(slack.methods.AUTH_TEST)
pprint.pprint(data)
Expand Down
74 changes: 34 additions & 40 deletions docs/testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,15 @@ Available fixtures
This fixture can be parametrized to return one or more available event from :class:`slack.tests.data.Events`
and :class:`slack.tests.data.Messages`.

.. code:: python
@pytest.mark.parametrize('slack_event', ('channel_deleted', 'simple'), indirect=True)
def test_events(slack_event):
assert True
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST EVENTS
:end-before: # END: TEST EVENTS

To only get :class:`slack.tests.data.Messages` members you can parametrize the test that way:

.. code:: python
@pytest.mark.parametrize("slack_event", {**slack.tests.data.Messages.__members__}, indirect=True)
async def test_messages(self, slack_event):
assert slack_event["event"]["type"] == "message"
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST MESSAGES
:end-before: # END: TEST MESSAGES


.. function:: slack.tests.plugin.slack_action
Expand All @@ -47,11 +43,9 @@ Available fixtures
This fixture can be parametrized to return one or more available action
from :class:`slack.tests.data.InteractiveMessage` or :class:`slack.tests.data.DialogSubmission`.

.. code:: python
@pytest.mark.parametrize('slack_action', ('button_ok', 'button_cancel'), indirect=True)
def test_actions(slack_action):
assert True
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST ACTIONS
:end-before: # END: TEST ACTIONS


.. function:: slack.tests.plugin.slack_command
Expand All @@ -60,11 +54,9 @@ Available fixtures

This fixture can be parametrized to return one or more available command from :class:`slack.tests.data.Commands`.

.. code:: python
@pytest.mark.parametrize('slack_command', ('text', 'no_text'), indirect=True)
def test_commands(slack_command):
assert True
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST COMMANDS
:end-before: # END: TEST COMMANDS


.. function:: slack.tests.plugin.slack_client
Expand All @@ -76,33 +68,35 @@ Available fixtures
- body: ``{'ok': True}``
- headers: ``{'content-type': 'application/json; charset=utf-8'}``

This can be parametrize with the ``_request`` parameter.

.. code:: python
Parametrize a reponse:

@pytest.mark.asyncio
@pytest.mark.parametrize('slack_client', ({'_request': {'body': {'ok': True, 'hello': 'world'}}},),
indirect=True)
async def test_client(slack_client):
data = await slack_client.query(slack.methods.AUTH_TEST)
assert data == {'ok': True, 'hello': 'world'}
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST CLIENT CUSTOM BODY
:end-before: # END: TEST CLIENT CUSTOM BODY

The ``body`` parameter of a request can be a string corresponding to one of the methods available
in :class:`slack.tests.data.Methods`.

For multiple requests you can set the ``_request`` parameter to a ``list``.
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST CLIENT BODY
:end-before: # END: TEST CLIENT BODY

Parametrize multiple responses:

.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST CLIENT STATUS
:end-before: # END: TEST CLIENT STATUS

.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST CLIENT ITER
:end-before: # END: TEST CLIENT ITER

Parametrize multiple run:

.. code:: python
.. literalinclude:: ../slack/tests/test_examples.py
:start-after: # START: TEST CLIENT MULTIPLE RUN
:end-before: # END: TEST CLIENT MULTIPLE RUN

@pytest.mark.asyncio
@pytest.mark.parametrize('slack_client', ({'_request': [
{'body': 'channels'},
{'status': 500}
]},), indirect=True)
async def test_client(slack_client):
data1 = await slack_client.query(slack.methods.AUTH_TEST)
with pytest.raises(slack.exceptions.HTTPException):
await slack_client.query(slack.methods.AUTH_TEST)

Available data
==============
Expand Down
156 changes: 93 additions & 63 deletions slack/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import copy
import json
import time
import functools
from unittest.mock import Mock

import pytest
import requests
import asynctest
from slack.events import Event, EventRouter, MessageRouter
from slack.events import EventRouter, MessageRouter
from slack.io.abc import SlackAPI
from slack.actions import Action
from slack.actions import Router as ActionRouter
from slack.commands import Router as CommandRouter
from slack.commands import Command

from . import data

try:
from slack.io.requests import SlackAPI as SlackAPIRequest
except ImportError:
SlackAPIRequest = None # type: ignore
SlackAPIRequest = int # type: ignore

TOKEN = "abcdefg"

Expand Down Expand Up @@ -53,83 +49,117 @@ def events(url):
return events


@pytest.fixture(params=(FakeIO,))
def io_client(request):
return request.param
@pytest.fixture(params=({},))
def slack_client(request):

if "status" not in request.param:
request.param["status"] = 200

@pytest.fixture(params=({"token": TOKEN},))
def client(request, io_client):
default_request = {
"status": 200,
"body": {"ok": True},
"headers": {"content-type": "application/json; charset=utf-8"},
}
if "body" not in request.param:
request.param["body"] = {"ok": True}

if "_request" not in request.param:
request.param["_request"] = default_request
elif isinstance(request.param["_request"], dict):
request.param["_request"] = _default_response(request.param["_request"])
elif isinstance(request.param["_request"], list):
for index, item in enumerate(request.param["_request"]):
request.param["_request"][index] = _default_response(item)
else:
raise ValueError("Invalid `_request` parameters: %s", request.param["_request"])
if "headers" not in request.param:
request.param["headers"] = {"content-type": "application/json; charset=utf-8"}

if "token" not in request.param:
request.param["token"] = TOKEN
client_param = request.param.get("client_parameters", {})
if "token" not in client_param:
client_param["token"] = TOKEN

slackclient = io_client(
**{k: v for k, v in request.param.items() if not k.startswith("_")}
)
if "client" in request.param:
client = request.param["client"]
else:
client = FakeIO

if isinstance(request.param["_request"], dict):
return_value = (
request.param["_request"]["status"],
json.dumps(request.param["_request"]["body"]).encode(),
request.param["_request"]["headers"],
slackclient = client(**client_param)

if all(
isinstance(value, list)
for value in (
request.param["status"],
request.param["body"],
request.param["headers"],
)
):
responses = []
for status, body, headers in zip(
request.param["status"], request.param["body"], request.param["headers"]
):
responses.append((status, json.dumps(_fill_body(body)).encode(), headers))

if isinstance(slackclient, SlackAPIRequest):
slackclient._request = Mock(return_value=return_value)
slackclient._request = Mock(side_effect=responses)
else:
slackclient._request = asynctest.CoroutineMock(return_value=return_value)
else:
responses = [
(
response["status"],
json.dumps(response["body"]).encode(),
response["headers"],
slackclient._request = asynctest.CoroutineMock(side_effect=responses)
elif any(
isinstance(value, list)
for value in (
request.param["status"],
request.param["body"],
request.param["headers"],
)
):
if not isinstance(request.param["status"], list):
request.param["status"] = [request.param["status"]]
if not isinstance(request.param["body"], list):
request.param["body"] = [request.param["body"]]
if not isinstance(request.param["headers"], list):
request.param["headers"] = [request.param["headers"]]

responses = list()
for index, _ in enumerate(
max(
request.param["status"],
request.param["body"],
request.param["headers"],
key=lambda x: len(x),
)
for response in request.param["_request"]
]
):
try:
status = request.param["status"][index]
except IndexError:
status = request.param["status"][0]

try:
body = request.param["body"][index]
except IndexError:
body = request.param["body"][0]

try:
headers = request.param["headers"][index]
except IndexError:
headers = request.param["headers"][0]

responses.append((status, json.dumps(_fill_body(body)).encode(), headers))

if isinstance(slackclient, SlackAPIRequest):
slackclient._request = Mock(side_effect=responses)
else:
slackclient._request = asynctest.CoroutineMock(side_effect=responses)
else:
return_value = (
request.param["status"],
json.dumps(_fill_body(request.param["body"])).encode(),
request.param["headers"],
)

if isinstance(slackclient, SlackAPIRequest):
slackclient._request = Mock(return_value=return_value)
else:
slackclient._request = asynctest.CoroutineMock(return_value=return_value)
print(return_value)
return slackclient


def _default_response(response):
default_response = {
"status": 200,
"body": {"ok": True},
"headers": {"content-type": "application/json; charset=utf-8"},
}
response = {**default_response, **response}
if "content-type" not in response["headers"]:
response["headers"]["content-type"] = default_response["headers"][
"content-type"
]
if isinstance(response["body"], str):
response["body"] = copy.deepcopy(data.Methods[response["body"]].value)
return response
def _fill_body(body):
if isinstance(body, str):
body = copy.deepcopy(data.Methods[body].value)
return body


@pytest.fixture(
params={**data.Events.__members__, **data.Messages.__members__} # type: ignore
)
def event(request):
def slack_event(request):
if isinstance(request.param, str):
try:
payload = copy.deepcopy(data.Events[request.param].value)
Expand All @@ -142,7 +172,7 @@ def event(request):


@pytest.fixture(params={**data.Messages.__members__}) # type: ignore
def message(request):
def slack_message(request):
if isinstance(request.param, str):
payload = copy.deepcopy(data.Messages[request.param].value)
else:
Expand Down Expand Up @@ -178,7 +208,7 @@ def message_router():
**data.MessageAction.__members__, # type: ignore
}
)
def action(request):
def slack_action(request):
if isinstance(request.param, str):
try:
payload = copy.deepcopy(data.InteractiveMessage[request.param].value)
Expand Down Expand Up @@ -219,7 +249,7 @@ def action_router():


@pytest.fixture(params={**data.Commands.__members__})
def command(request):
def slack_command(request):
if isinstance(request.param, str):
payload = copy.deepcopy(data.Commands[request.param].value)
else:
Expand Down

0 comments on commit 67d2820

Please sign in to comment.