Skip to content

Commit 5bf043a

Browse files
authored
Merge pull request #4 from mstred/testing
"Testing" chapter
2 parents 513fa60 + 313cc80 commit 5bf043a

File tree

12 files changed

+516
-16
lines changed

12 files changed

+516
-16
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
**/__pycache__
2+
.coverage
3+
.nox
4+
.pytest_cache

docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ services:
55
image: docker.pkg.github.com/mstred/hypermodern-python/image
66
build: .
77
volumes:
8-
- ${PWD}:/app
8+
- .:/app
99
working_dir: /app

noxfile.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from nox import session as nox_session
2+
3+
4+
@nox_session()
5+
def tests(session):
6+
session.run("poetry", "install", external=True)
7+
session.run("pytest", *(session.posargs or ["--cov", "-m", "not e2e"]))
8+

poetry.lock

Lines changed: 369 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "hypermodern"
3-
version = "0.2.0"
3+
version = "0.3.0"
44
description = ""
55
authors = ["Edson Samuel Jr <[email protected]>"]
66
repository = "https://github.com/mstred/hypermodern-python"
@@ -11,10 +11,26 @@ click = "^7.1.2"
1111
requests = "^2.25.1"
1212

1313
[tool.poetry.dev-dependencies]
14+
coverage = {extras = ["toml"], version = "^5.3"}
15+
nox = "^2020.8.22"
16+
pytest = "^6.2.1"
17+
pytest-cov = "^2.10.1"
18+
pytest-mock = "^3.4.0"
1419

1520
[tool.poetry.scripts]
1621
app = "hypermodern.app:main"
1722

23+
[tool.coverage.paths]
24+
source = ["src", "*/site-packages"]
25+
26+
[tool.coverage.run]
27+
branch = true
28+
source = ["hypermodern"]
29+
30+
[tool.coverage.report]
31+
show_missing = true
32+
fail_under = 100
33+
1834
[build-system]
1935
requires = ["poetry-core>=1.0.0"]
2036
build-backend = "poetry.core.masonry.api"

src/hypermodern/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.2.0"
1+
__version__ = "0.3.0"

src/hypermodern/app.py

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
from textwrap import fill
22

3-
from click import command, secho, version_option
4-
from requests import get
3+
import click
54

65
from hypermodern import __version__ as version
6+
from hypermodern import wikipedia
77

8-
API_URL = "https://en.wikipedia.org/api/rest_v1/page/random/summary"
98

10-
@command()
11-
@version_option(version)
12-
def main():
13-
secho(f"Hello, this is hypermodern {version}!", fg="green")
9+
@click.command()
10+
@click.option(
11+
"--language",
12+
"-l",
13+
default="en",
14+
help="Choose an ISO-639 code for language",
15+
metavar="LANG",
16+
show_default=True
17+
)
18+
@click.version_option(version)
19+
def main(language):
20+
click.secho(f"Hello, this is hypermodern {version}!", fg="green")
1421

15-
with get(API_URL) as response:
16-
response.raise_for_status()
17-
data = response.json()
22+
data = wikipedia.get_random_page(language=language)
1823

19-
secho(data["title"], fg="yellow")
20-
secho(fill(data["extract"]))
24+
click.secho(data["title"], fg="yellow")
25+
click.secho(fill(data["extract"]))
2126

src/hypermodern/wikipedia.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from click import ClickException
2+
from requests import get, RequestException
3+
4+
5+
def get_random_page(language="en"):
6+
API_URL = f"https://{language}.wikipedia.org/api/rest_v1/page/random/summary"
7+
8+
try:
9+
with get(API_URL) as response:
10+
response.raise_for_status()
11+
return response.json()
12+
except RequestException as exception:
13+
raise ClickException(str(exception))
14+

tests/__init__.py

Whitespace-only changes.

tests/conftest.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from click.testing import CliRunner
2+
from pytest import fixture
3+
4+
5+
@fixture
6+
def runner():
7+
return CliRunner()
8+
9+
10+
@fixture
11+
def mock_requests_get(mocker):
12+
mock = mocker.patch("hypermodern.wikipedia.get")
13+
mock.return_value.__enter__.return_value.json.return_value = {
14+
"title": "title",
15+
"extract": "extract"
16+
}
17+
18+
return mock
19+
20+
21+
@fixture
22+
def mock_get_random_page(mocker):
23+
return mocker.patch("hypermodern.wikipedia.get_random_page")
24+
25+
26+
def pytest_configure(config):
27+
config.addinivalue_line("markers", "e2e: mark as end-to-end test")
28+

tests/test_app.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from pytest import mark
2+
from requests import RequestException
3+
4+
from hypermodern import app
5+
from hypermodern.wikipedia import get_random_page
6+
7+
8+
@mark.e2e
9+
def test_main_pass(runner):
10+
result = runner.invoke(app.main)
11+
assert result.exit_code == 0
12+
13+
14+
def test_main_pass_mocked(runner, mock_requests_get):
15+
result = runner.invoke(app.main)
16+
assert result.exit_code == 0
17+
18+
19+
def test_main_requests_get_is_called(runner, mock_requests_get):
20+
runner.invoke(app.main)
21+
assert mock_requests_get.called
22+
23+
24+
def test_main_requests_wikipedia_api(runner, mock_requests_get):
25+
runner.invoke(app.main)
26+
assert "en.wikipedia.org/api" in str(mock_requests_get.call_args.args)
27+
28+
29+
def test_main_check_content(runner, mock_requests_get):
30+
result = runner.invoke(app.main)
31+
assert "title" in result.output and "extract" in result.output
32+
33+
34+
def test_main_request_failed(runner, mock_requests_get):
35+
mock_requests_get.side_effect = Exception()
36+
result = runner.invoke(app.main)
37+
assert result.exit_code != 0
38+
39+
40+
def test_main_prints_on_failed_request(runner, mock_requests_get):
41+
mock_requests_get.side_effect = RequestException()
42+
result = runner.invoke(app.main)
43+
print(result.output)
44+
assert "Error" in result.output
45+
46+
47+
def test_main_with_specific_language(runner, mock_get_random_page):
48+
language = "pt"
49+
runner.invoke(app.main, [f"--language={language}"])
50+
assert mock_get_random_page.called_with(language=language)
51+

tests/test_wikipedia.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from hypermodern.wikipedia import get_random_page
2+
3+
4+
def test_get_random_page_with_specific_language(mock_requests_get):
5+
get_random_page(language="de")
6+
assert "de.wikipedia.org" in str(mock_requests_get.call_args.args)
7+

0 commit comments

Comments
 (0)