Skip to content

Commit

Permalink
Merge 33b610e into ffe9f71
Browse files Browse the repository at this point in the history
  • Loading branch information
LilSpazJoekp committed Dec 24, 2022
2 parents ffe9f71 + 33b610e commit 1c9dab8
Show file tree
Hide file tree
Showing 75 changed files with 6,669 additions and 7,600 deletions.
184 changes: 93 additions & 91 deletions .github/workflows/ci.yml
Expand Up @@ -3,117 +3,119 @@ jobs:
needs: test-multi-python
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
- name: Coveralls Finished
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
parallel-finished: true
lint-multi-os:
name: Lint ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-lint-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-lint-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
# Pin pip to 21.x for now to avoid error in pre-commit action on Win
python -m pip install --upgrade pip==21.* setuptools wheel
pip install --upgrade .[lint]
- name: Run pre-commit hooks
uses: pre-commit/action@v2.0.3
- name: Run sphinx
run: sphinx-build -W --keep-going docs/ /tmp/foo
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-lint-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-lint-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install .[lint]
- name: Run pre-commit hooks
uses: pre-commit/action@v2.0.3
- name: Run sphinx
run: sphinx-build -W --keep-going docs/ /tmp/foo
strategy:
matrix:
os: [macOS-latest, ubuntu-latest, windows-latest]
os: [ macOS-latest, ubuntu-latest, windows-latest ]
test-multi-os:
name: Test ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
- name: Test with pytest
run: pytest
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
- name: Test with pytest
env:
ENSURE_NO_UNUSED_CASSETTES: 1
run: pytest
strategy:
matrix:
os: [macOS-latest, ubuntu-latest, windows-latest]
os: [ macOS-latest, ubuntu-latest, windows-latest ]
test-multi-python:
name: Test Python ${{ matrix.python-version }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
pip install .[ci]
- name: Test with pytest
run: coverage run --source praw --module pytest
- env:
COVERALLS_PARALLEL: true
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: Submit to coveralls
run: coveralls --service=github
- name: Check coverage
run: coverage report -m --fail-under=100
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[ci,test]
- name: Test with pytest
run: coverage run --source praw --module pytest
env:
ENSURE_NO_UNUSED_CASSETTES: 1
- name: Submit to coveralls
env:
COVERALLS_PARALLEL: true
COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: coveralls --service=github
- name: Check coverage
run: coverage report -m --fail-under=100
strategy:
matrix:
python-version: [3.7, 3.8, 3.9, '3.10']
python-version: [ 3.7, 3.8, 3.9, '3.10' ]
test-network:
name: Test Network Request
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
- name: Run network test
run: pytest tests/integration/test_github_actions.py::test_github_actions
env:
NETWORK_TEST_CLIENT_ID: ${{ secrets.NETWORK_TEST_CLIENT_ID }}
NETWORK_TEST_CLIENT_SECRET: ${{ secrets.NETWORK_TEST_CLIENT_SECRET }}
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.x
- uses: actions/cache@v1
with:
key: v0-${{ runner.os }}-pip-test-${{ hashFiles('setup.py') }}
path: ~/.cache/pip
restore-keys: |
v0-${{ runner.os }}-pip-test-
v0-${{ runner.os }}-pip-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .[test]
- name: Run network test
run: pytest tests/integration/test_github_actions.py::test_github_actions
env:
NETWORK_TEST_CLIENT_ID: ${{ secrets.NETWORK_TEST_CLIENT_ID }}
NETWORK_TEST_CLIENT_SECRET: ${{ secrets.NETWORK_TEST_CLIENT_SECRET }}
name: CI
on: [pull_request, push]
on: [ pull_request, push ]
21 changes: 20 additions & 1 deletion docs/package_info/contributing.rst
Expand Up @@ -227,6 +227,25 @@ to first delete it, and then rerun the test suite.
Please always verify that only the requests you expect to be made are contained within
your cassette.

If you are using a single cassette for multiple tests, you need to add a
``use_cassette`` pytest mark decorator. If you need specify parameters for the
``Betamax.use_cassette`` method, use the ``recorder_kwargs`` pytest mark decorator. The
``recorder_kwargs`` can be applied to a test class and/or individual test functions. For
example:

.. code-block:: python
@pytest.mark.recorder_kwargs(allow_playback_repeats=True)
class TestClass:
@pytest.mark.recorder_kwargs(match_requests_on=["uri", "method", "body"])
def test_example(self):
...
@pytest.mark.cassette_name("TestClass.test_example")
@pytest.mark.recorder_kwargs(match_requests_on=["uri", "method", "body"])
def test_example__different_assertion(self):
...
Documentation
-------------

Expand Down Expand Up @@ -260,7 +279,7 @@ the ``AUTHORS.rst`` file.
CHANGES.rst
~~~~~~~~~~~

For feature additions, bugfixes, or code removal please add an appropriate entry to
For feature additions, bug fixes, or code removal please add an appropriate entry to
``CHANGES.rst``. If the ``Unreleased`` section does not exist at the top of
``CHANGES.rst`` please add it. See `commit 280525c16ba28cdd69cdbb272a0e2764b1c7e6a0`_
for an example.
Expand Down
104 changes: 25 additions & 79 deletions tests/conftest.py
@@ -1,120 +1,66 @@
"""Prepare py.test."""
import json
import os
import socket
import time
from base64 import b64encode
from functools import wraps
from sys import platform
from urllib.parse import quote_plus

import betamax
import pytest
from betamax.cassette.cassette import Cassette, dispatch_hooks
from betamax.serializers import JSONSerializer


# Prevent calls to sleep
def _sleep(*args):
raise Exception("Call to sleep")
@pytest.fixture(autouse=True)
def patch_sleep(monkeypatch):
"""Auto patch sleep to speed up tests."""

def _sleep(*_, **__):
"""Dud sleep function."""
return

time.sleep = _sleep
monkeypatch.setattr(time, "sleep", value=_sleep)


def b64_string(input_string):
"""Return a base64 encoded string (not bytes) from input_string."""
return b64encode(input_string.encode("utf-8")).decode("utf-8")
@pytest.fixture
def image_path():
"""Return path to image."""

def _get_path(name):
"""Return path to image."""
return os.path.join(os.path.dirname(__file__), "integration", "files", name)

def env_default(key):
"""Return environment variable or placeholder string."""
return os.environ.get(f"prawtest_{key}", f"placeholder_{key}")
return _get_path


def filter_access_token(interaction, current_cassette):
"""Add Betamax placeholder to filter access token."""
request_uri = interaction.data["request"]["uri"]
response = interaction.data["response"]
if "api/v1/access_token" not in request_uri or response["status"]["code"] != 200:
return
body = response["body"]["string"]
try:
token = json.loads(body)["access_token"]
except (KeyError, TypeError, ValueError):
return
current_cassette.placeholders.append(
betamax.cassette.cassette.Placeholder(
placeholder="<ACCESS_TOKEN>", replace=token
)
def pytest_configure(config):
pytest.placeholders = Placeholders(placeholders)
config.addinivalue_line(
"markers", "cassette_name: Name of cassette to use for test."
)
config.addinivalue_line(
"markers", "recorder_kwargs: Arguments to pass to the recorder."
)


os.environ["praw_check_for_updates"] = "False"


placeholders = {
x: env_default(x)
x: os.environ.get(f"prawtest_{x}", f"placeholder_{x}")
for x in (
"auth_code client_id client_secret password redirect_uri test_subreddit"
" user_agent username refresh_token"
).split()
}


placeholders["basic_auth"] = b64_string(
f"{placeholders['client_id']}:{placeholders['client_secret']}"
)


class PrettyJSONSerializer(JSONSerializer):
name = "prettyjson"

def serialize(self, cassette_data):
return f"{json.dumps(cassette_data, sort_keys=True, indent=2, separators=(',', ': '))}\n"


betamax.Betamax.register_serializer(PrettyJSONSerializer)
with betamax.Betamax.configure() as config:
config.cassette_library_dir = "tests/integration/cassettes"
config.default_cassette_options["serialize_with"] = "prettyjson"
config.before_record(callback=filter_access_token)
for key, value in placeholders.items():
if key == "password":
value = quote_plus(value)
config.define_cassette_placeholder(f"<{key.upper()}>", value)


def add_init_hook(original_init):
"""Wrap an __init__ method to also call some hooks."""

@wraps(original_init)
def wrapper(self, *args, **kwargs):
original_init(self, *args, **kwargs)
dispatch_hooks("after_init", self)

return wrapper


Cassette.__init__ = add_init_hook(Cassette.__init__)


def init_hook(cassette):
if cassette.is_recording():
pytest.set_up_record() # dynamically defined in __init__.py


Cassette.hooks["after_init"].append(init_hook)
placeholders["basic_auth"] = b64encode(
f"{placeholders['client_id']}:{placeholders['client_secret']}".encode("utf-8")
).decode("utf-8")


class Placeholders:
def __init__(self, _dict):
self.__dict__ = _dict


def pytest_configure():
pytest.placeholders = Placeholders(placeholders)


if platform == "darwin": # Work around issue with betamax on OS X
socket.gethostbyname = lambda x: "127.0.0.1"

0 comments on commit 1c9dab8

Please sign in to comment.