pax_global_header 0000666 0000000 0000000 00000000064 14501650272 0014514 g ustar 00root root 0000000 0000000 52 comment=d0ca7e22b8e4d0c2d8807a9cf9e1f8ca7ef20442
pytest-codeblocks-0.17.0/ 0000775 0000000 0000000 00000000000 14501650272 0015237 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/.codecov.yml 0000664 0000000 0000000 00000000014 14501650272 0017455 0 ustar 00root root 0000000 0000000 comment: no
pytest-codeblocks-0.17.0/.flake8 0000664 0000000 0000000 00000000167 14501650272 0016416 0 ustar 00root root 0000000 0000000 [flake8]
ignore = E203, E266, E501, W503, F401, C901
max-line-length = 80
max-complexity = 18
select = B,C,E,F,W,T4,B9
pytest-codeblocks-0.17.0/.github/ 0000775 0000000 0000000 00000000000 14501650272 0016577 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/.github/renovate.json 0000664 0000000 0000000 00000000041 14501650272 0021310 0 ustar 00root root 0000000 0000000 {
"extends": ["config:base"]
}
pytest-codeblocks-0.17.0/.github/workflows/ 0000775 0000000 0000000 00000000000 14501650272 0020634 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/.github/workflows/tests.yml 0000664 0000000 0000000 00000001716 14501650272 0022526 0 ustar 00root root 0000000 0000000 name: tests
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pre-commit/action@v3.0.0
build:
needs: [lint]
strategy:
matrix:
platform: [ubuntu-latest]
python-version: ["3.7", "3.11"]
include:
- platform: macos-latest
python-version: "3.11"
- platform: windows-latest
python-version: "3.11"
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- uses: actions/checkout@v4
- name: Test with tox
run: |
pip install tox
tox -- --cov pytest_codeblocks --cov-report xml --cov-report term
- uses: codecov/codecov-action@v4-beta
if: ${{ matrix.python-version == '3.11' && matrix.os == 'ubuntu-latest' }}
pytest-codeblocks-0.17.0/.gitignore 0000664 0000000 0000000 00000000123 14501650272 0017223 0 ustar 00root root 0000000 0000000 .cache/
build/
doc/_build/
doc/build/
*.egg-info/
dist/
*.png
.pytest_cache/
.tox/
pytest-codeblocks-0.17.0/.pre-commit-config.yaml 0000664 0000000 0000000 00000000521 14501650272 0021516 0 ustar 00root root 0000000 0000000 repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.290
hooks:
- id: ruff
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.3
hooks:
- id: prettier
pytest-codeblocks-0.17.0/LICENSE.txt 0000664 0000000 0000000 00000002101 14501650272 0017054 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2020-present Nico Schlömer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
pytest-codeblocks-0.17.0/MANIFEST.in 0000664 0000000 0000000 00000000046 14501650272 0016775 0 ustar 00root root 0000000 0000000 include tests/*.md
include tests/*.py
pytest-codeblocks-0.17.0/README.md 0000664 0000000 0000000 00000010277 14501650272 0016525 0 ustar 00root root 0000000 0000000
Test code blocks in your READMEs.
[](https://pypi.org/project/pytest_codeblocks/)
[](https://anaconda.org/conda-forge/pytest-codeblocks/)
[](https://pypi.org/project/pytest_codeblocks/)
[](https://github.com/nschloe/pytest-codeblocks)
[](https://www.pepy.tech/projects/pytest-codeblocks)
[](https://github.com/nschloe/pytest-codeblocks/actions?query=workflow%3Atests)
[](https://app.codecov.io/gh/nschloe/pytest-codeblocks)
[](https://github.com/psf/black)
This is pytest-codeblocks, a [pytest](https://pytest.org/) plugin for testing code
blocks from README files. It supports Python and shell code.
Install with
```sh
pip install pytest-codeblocks
```
and run pytest with
```sh
pytest --codeblocks
```
```sh
================================= test session starts =================================
platform linux -- Python 3.9.4, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: /path/to/directory
plugins: codeblocks-0.11.0
collected 56 items
example.md ....................... [ 50%]
README.md ....................... [100%]
================================= 56 passed in 0.08s ==================================
```
pytest-codeblocks will only pick up code blocks with `python` and `sh`/`bash`/`zsh`
syntax highlighting.
#### Marking code blocks
It is possible to use `pytest.mark` for marking code blocks. For example,
to skip a code block use `pytest.mark.skip` or `pytest.mark.skipif`:
````markdown
Lorem ipsum
```python
foo + bar # not working
```
dolor sit amet.
````
```markdown
```
You can skip code blocks on import errors with
```markdown
```
Skip the entire file by putting
```markdown
```
in the first line.
For expected errors, use `pytest.mark.xfail`:
````markdown
The following gives an error:
```python
1 / 0
```
````
#### Merging code blocks
Broken-up code blocks can be merged into one with the `pytest-codeblocks:cont` prefix
````markdown
Lorem ipsum
```python
a = 1
```
dolor sit amet
```python
# this would otherwise fail since `a` is not defined
a + 1
```
````
If you'd like to prepend code that you don't want to show, you can just comment it out;
pytest-codeblocks will pick it up anyway:
````markdown
Lorem ipsum
dolor sit amet
```python
# this would otherwise fail since `a` is not defined
a + 1
```
````
#### Expected output
You can also define the expected output of a code block:
````markdown
This
```sh
print(1 + 3)
```
gives
```
4
```
````
Use `expected-output-ignore-whitespace` if you'd like whitespace differences to
be ignored.
(Conditionally) Skipping the output verfication works by prepending the first
block with `skip`/`skipif` (see [above](#skipping-code-blocks)).
pytest-codeblocks-0.17.0/justfile 0000664 0000000 0000000 00000000752 14501650272 0017013 0 ustar 00root root 0000000 0000000 version := `python3 -c "from src.pytest_codeblocks.__about__ import __version__; print(__version__)"`
default:
@echo "\"just publish\"?"
publish:
@if [ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]; then exit 1; fi
gh release create "v{{version}}"
flit publish
clean:
@find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf
@rm -rf src/*.egg-info/ build/ dist/ .tox/
format:
ruff src/ tests/ --fix
black src/ tests/
blacken-docs README.md
lint:
pre-commit run --all
pytest-codeblocks-0.17.0/pyproject.toml 0000664 0000000 0000000 00000002473 14501650272 0020161 0 ustar 00root root 0000000 0000000 [build-system]
requires = ["setuptools>=61"]
build-backend = "setuptools.build_meta"
[project]
name = "pytest_codeblocks"
authors = [{name = "Nico Schlömer", email = "nico.schloemer@gmail.com"}]
description = "Test code blocks in your READMEs"
readme = "README.md"
license = {file = "LICENSE.txt"}
classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Pytest",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = ["version"]
requires-python = ">=3.7"
dependencies = [
"pytest >= 7.0.0"
]
[tool.setuptools.dynamic]
version = {attr = "pytest_codeblocks.__about__.__version__"}
[project.urls]
Homepage = "https://github.com/nschloe/pytest-codeblocks"
Code = "https://github.com/nschloe/pytest-codeblocks"
Issues = "https://github.com/nschloe/pytest-codeblocks/issues"
Funding = "https://github.com/sponsors/nschloe"
[project.entry-points.pytest11]
codeblocks = "pytest_codeblocks.plugin"
pytest-codeblocks-0.17.0/src/ 0000775 0000000 0000000 00000000000 14501650272 0016026 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/src/pytest_codeblocks/ 0000775 0000000 0000000 00000000000 14501650272 0021546 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/src/pytest_codeblocks/__about__.py 0000664 0000000 0000000 00000000027 14501650272 0024025 0 ustar 00root root 0000000 0000000 __version__ = "0.17.0"
pytest-codeblocks-0.17.0/src/pytest_codeblocks/__init__.py 0000664 0000000 0000000 00000000361 14501650272 0023657 0 ustar 00root root 0000000 0000000 from . import plugin
from .__about__ import __version__
from .main import CodeBlock, extract_from_buffer, extract_from_file
__all__ = [
"CodeBlock",
"extract_from_buffer",
"extract_from_file",
"plugin",
"__version__",
]
pytest-codeblocks-0.17.0/src/pytest_codeblocks/main.py 0000664 0000000 0000000 00000014646 14501650272 0023057 0 ustar 00root root 0000000 0000000 from __future__ import annotations
import contextlib
import re
import sys
import warnings
# namedtuple with default arguments
#
from dataclasses import dataclass, field
from io import StringIO
from pathlib import Path
@dataclass
class CodeBlock:
code: str
lineno: int
syntax: str | None = None
expected_output: str | None = None
expected_output_ignore_whitespace: bool = False
importorskip: str | None = None
marks: list[str] = field(default_factory=lambda: [])
def extract_from_file(
f: str | bytes | Path, encoding: str | None = "utf-8", *args, **kwargs
):
with open(f, encoding=encoding) as handle:
return extract_from_buffer(handle, *args, **kwargs)
def extract_from_buffer(f, max_num_lines: int = 10000) -> list[CodeBlock]:
out = []
marks = []
continued_block = None
expected_output_block = None
expected_output_ignore_whitespace = False
importorskip = None
k = 1
while True:
line = f.readline()
if k == 1 and line.strip() == "":
return []
k += 1
if not line:
# EOF
break
if line.strip() == "":
continue
m = re.match(
r"",
line.strip(),
)
if m is not None:
keyword = m.group(1).strip("- ")
# handle special tags
if keyword in {"expected-output", "expected-output-ignore-whitespace"}:
if len(out) == 0:
raise RuntimeError(
f"Found "
+ "but no previous code block."
)
if out[-1].expected_output is not None:
raise RuntimeError(
f"Found "
+ "but block already has expected_output."
)
expected_output_block = out[-1]
if keyword == "expected-output-ignore-whitespace":
# \s: regex matches all whitespace characters
expected_output_ignore_whitespace = True
elif keyword == "cont":
if len(out) == 0:
msg = (
"Found "
"but no previous code block."
)
raise RuntimeError(msg)
continued_block = out[-1]
elif keyword == "skip":
warnings.warn(
"pytest-codeblocks:skip is deprecated. Use pytest.mark.skip",
DeprecationWarning,
)
marks.append("pytest.mark.skip")
elif keyword.startswith("skipif"):
warnings.warn(
"pytest-codeblocks:skipif is deprecated. Use pytest.mark.skipif",
DeprecationWarning,
)
m = re.match(r"skipif\((.*)\)", keyword)
if m is None:
raise RuntimeError(
"pytest-codeblocks: Expected skipif(some-condition)"
)
marks.append(f"pytest.mark.skipif({m.group(1)}, reason='')")
elif keyword.startswith("importorskip"):
m = re.match(r"importorskip\((.*)\)", keyword)
if m is None:
raise RuntimeError(
"pytest-codeblocks: Expected importorskip(some-module)"
)
importorskip = m.group(1)
elif keyword in ["expect-exception", "expect-error"]:
warnings.warn(
f"pytest-codeblocks:{keyword} is deprecated. Use pytest.mark.xfail",
DeprecationWarning,
)
marks.append("pytest.mark.xfail")
else:
raise RuntimeError(f'Unknown pytest-codeblocks keyword "{keyword}"')
continue
m = re.match(
r"",
line.strip(),
)
if m is not None:
marks.append(m.group(1))
continue
lsline = line.lstrip()
if lsline.startswith("```"):
# normally 3, but can be more:
num_leading_backticks = len(lsline) - len(lsline.lstrip("`"))
syntax = line.strip()[num_leading_backticks:]
num_leading_spaces = len(line) - len(lsline)
lineno = k - 1
# read the block
code_block = []
while True:
line = f.readline()
lsline = line.lstrip()
k += 1
if not line:
raise RuntimeError("Hit end-of-file prematurely. Syntax error?")
if k > max_num_lines:
raise RuntimeError(
f"File too large (> {max_num_lines} lines). Set max_num_lines."
)
# check if end of block
if lsline[:num_leading_backticks] == "`" * num_leading_backticks:
break
# Cut (at most) num_leading_spaces leading spaces
nls = min(num_leading_spaces, len(line) - len(lsline))
line = line[nls:]
code_block.append(line)
code = "".join(code_block)
if continued_block:
continued_block.code += code
continued_block = None
elif expected_output_block:
expected_output_block.expected_output = code
expected_output_block.expected_output_ignore_whitespace = (
expected_output_ignore_whitespace
)
expected_output_block = None
else:
out.append(
CodeBlock(
code,
lineno,
syntax,
marks=marks,
importorskip=importorskip,
)
)
marks = []
importorskip = None
return out
# https://stackoverflow.com/a/3906390/353337
@contextlib.contextmanager
def stdout_io(stdout=None):
old = sys.stdout
if stdout is None:
stdout = StringIO()
sys.stdout = stdout
yield stdout
sys.stdout = old
pytest-codeblocks-0.17.0/src/pytest_codeblocks/plugin.py 0000664 0000000 0000000 00000010063 14501650272 0023416 0 ustar 00root root 0000000 0000000 #
# Take a look at the example
# https://docs.pytest.org/en/stable/example/nonpython.html
#
import subprocess
from pathlib import Path
import re
import pytest
from .main import extract_from_file, stdout_io
def pytest_addoption(parser):
group = parser.getgroup("general")
group.addoption(
"--codeblocks",
action="store_true",
help="enable testing of code blocks",
)
def pytest_collect_file(path, parent):
config = parent.config
path = Path(path)
if config.option.codeblocks and path.suffix == ".md":
return MarkdownFile.from_parent(parent, path=path)
class MarkdownFile(pytest.File):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def collect(self):
for block in extract_from_file(self.path):
if block.syntax not in ["python", "sh", "bash"]:
continue
# https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent
# The name makes sure that tests appear as
# ```
# README.md::line 56
# ```
out = TestBlock.from_parent(parent=self, name=f"line {block.lineno}")
out.obj = block
for mark in block.marks:
# A common thing is
#
# pytest.mark.skipif(sys.version_info < (3, 10), reason="...")
#
# which needs sys. Import it here.
import sys # noqa: F401
out.add_marker(eval(mark))
yield out
class TestBlock(pytest.Item):
def __init__(self, name, parent, obj=None):
super().__init__(name, parent=parent)
self.obj = obj
def runtest(self):
assert self.obj is not None
output = None
if self.obj.importorskip is not None:
try:
__import__(self.obj.importorskip)
except (ImportError, ModuleNotFoundError):
pytest.skip()
if self.obj.syntax == "python":
with stdout_io() as s:
try:
# https://stackoverflow.com/a/62851176/353337
exec(self.obj.code, {"__MODULE__": "__main__"})
except Exception as e:
raise RuntimeError(
f"{self.name}, line {self.obj.lineno}:\n```\n"
+ self.obj.code
+ "```\n\n"
+ f"{e}"
)
output = s.getvalue()
else:
assert self.obj.syntax in ["sh", "bash"]
executable = {
"sh": None,
"bash": "/bin/bash",
"zsh": "/bin/zsh",
}[self.obj.syntax]
# TODO for python 3.7+, stdout=subprocess.PIPE can be replaced
# by capture_output=True
ret = subprocess.run(
self.obj.code,
shell=True,
check=True,
stdout=subprocess.PIPE,
executable=executable,
)
output = ret.stdout.decode()
if output is not None and self.obj.expected_output is not None:
str0 = self.obj.expected_output
str1 = output
if self.obj.expected_output_ignore_whitespace:
str0 = re.sub(r"\s+", "", str0)
str1 = re.sub(r"\s+", "", str1)
if str0 != str1:
raise RuntimeError(
f"{self.name}, line {self.obj.lineno}:\n```\n"
+ f"Expected output\n```\n{self.obj.expected_output}```\n"
+ f"but got\n```\n{output}```"
)
def repr_failure(self, excinfo):
"""Called when self.runtest() raises an exception."""
# if isinstance(excinfo.value, CodeblockException):
return excinfo.value.args[0]
# if excinfo.errisinstance(RuntimeError):
# return excinfo.value.args[0].stdout
# return super().repr_failure(excinfo)
def reportinfo(self):
return (self.path, -1, "code block check")
pytest-codeblocks-0.17.0/tests/ 0000775 0000000 0000000 00000000000 14501650272 0016401 5 ustar 00root root 0000000 0000000 pytest-codeblocks-0.17.0/tests/example.md 0000664 0000000 0000000 00000001037 14501650272 0020357 0 ustar 00root root 0000000 0000000 ```python
1 + 1
```
Lorem ipsum
```python
1 + 2 + 3
2 + 5
```
dolor sit amet.
```python
import pytest_codeblocks
pytest_codeblocks.extract_from_buffer
```
Something that should be skipped because of the language:
```ruby
foobar
```
A shell script should be exectuted:
```sh
echo abc
```
Again with an explicit skip:
```python
bar
```
Something that contains triple fences
````python
# ```import math```
````
Indented code blocks:
```python
1 + 1 == 2
```
"Wrong" indentation:
```python
1 + 1 == 2
```
pytest-codeblocks-0.17.0/tests/test_comment_styles.py 0000664 0000000 0000000 00000001021 14501650272 0023051 0 ustar 00root root 0000000 0000000 import pytest
@pytest.mark.parametrize(
"comment",
[
"",
"",
"",
"",
],
)
def test_cont(testdir, comment):
string = """
Lorem ipsum
```python
a = 1
```
dolor sit amet
{comment}
```
a + 1
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
pytest-codeblocks-0.17.0/tests/test_cont.py 0000664 0000000 0000000 00000001535 14501650272 0020761 0 ustar 00root root 0000000 0000000 def test_cont(testdir):
string = """
Lorem ipsum
```python
a = 1
```
dolor sit amet
```
a + 1
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_hidden_cont(testdir):
string = """
Lorem ipsum
dolor sit amet
```
a + 1
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_nocont(testdir):
string = """
```python
1 + 2 + 3
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(errors=1)
pytest-codeblocks-0.17.0/tests/test_errors.py 0000664 0000000 0000000 00000000736 14501650272 0021334 0 ustar 00root root 0000000 0000000 import io
import pytest
import pytest_codeblocks
def test_unclosed(testdir):
string = """
```python
1 + 2 + 3
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(errors=1)
def test_maxlines():
unclosed = io.StringIO(
"""
```python
1 + 2 + 3
```
"""
)
with pytest.raises(RuntimeError):
pytest_codeblocks.extract_from_buffer(unclosed, max_num_lines=1)
pytest-codeblocks-0.17.0/tests/test_expect_error.py 0000664 0000000 0000000 00000002105 14501650272 0022511 0 ustar 00root root 0000000 0000000 def test_expect_error(testdir):
string = """
```python
raise RuntimeError()
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(xfailed=1)
def test_expect_error_runtimeerror(testdir):
string = """
```python
raise RuntimeError()
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(xfailed=1)
def test_expect_error_indexerror(testdir):
string = """
```python
raise RuntimeError()
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(failed=1)
def test_expect_error_fail(testdir):
string1 = """
Lorem ipsum
```python
1 + 1
```
"""
testdir.makefile(".md", string1)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(xpassed=1)
pytest-codeblocks-0.17.0/tests/test_expected_output.py 0000664 0000000 0000000 00000002601 14501650272 0023232 0 ustar 00root root 0000000 0000000 def test_expected_output(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
print(1 - 3)
print(1 * 3)
```
dolor sit amet
```
4
-2
3
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_expected_output_fail(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
dolor sit amet
```
5
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(failed=1)
def test_expected_output_ignore_whitespace(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
print(1 - 3)
print(1 * 3)
```
dolor sit amet
```
4 -2
3
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_expected_output_ignore_whitespace_fail(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
print(1 - 3)
print(1 * 3)
```
dolor sit amet
```
4 -2
5
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(failed=1)
pytest-codeblocks-0.17.0/tests/test_general.py 0000664 0000000 0000000 00000003263 14501650272 0021433 0 ustar 00root root 0000000 0000000 import pathlib
import pytest_codeblocks
def test_basic(testdir):
string1 = """
Lorem ipsum
```python
1 + 2 + 3
```
dolor sit amet
"""
testdir.makefile(".md", string1)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_skip(testdir):
string1 = """
Lorem ipsum
```python
1 + 2 + 3
```
dolor sit amet
Some newlines:
```python
1 + 2 + 3
```
"""
testdir.makefile(".md", string1)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=2)
# example.md against reference strings test against
def test_reference():
ref = [
pytest_codeblocks.CodeBlock("1 + 1\n", 1, "python"),
pytest_codeblocks.CodeBlock("1 + 2 + 3\n2 + 5\n", 7, "python"),
pytest_codeblocks.CodeBlock(
"import pytest_codeblocks\n\npytest_codeblocks.extract_from_buffer\n",
14,
"python",
),
pytest_codeblocks.CodeBlock("foobar\n", 22, "ruby"),
pytest_codeblocks.CodeBlock("echo abc\n", 28, "sh"),
pytest_codeblocks.CodeBlock("bar\n", 36, "python", marks=["pytest.mark.skip"]),
pytest_codeblocks.CodeBlock("# ```import math```\n", 42, "python"),
pytest_codeblocks.CodeBlock("1 + 1 == 2\n", 48, "python"),
pytest_codeblocks.CodeBlock("1 + 1 == 2\n", 54, "python"),
]
this_dir = pathlib.Path(__file__).resolve().parent
lst = pytest_codeblocks.extract_from_file(this_dir / "example.md")
print(lst)
for r, obj in zip(ref, lst):
print("\n\nr ", r)
print("\nobj", obj)
assert r == obj
pytest-codeblocks-0.17.0/tests/test_shell.py 0000664 0000000 0000000 00000003672 14501650272 0021131 0 ustar 00root root 0000000 0000000 import sys
import pytest
if sys.platform.startswith("win"):
pytest.skip("skipping shell tests", allow_module_level=True)
def test_shell(testdir):
string = """
Lorem ipsum
```sh
ls
```
dolor sit amet
```sh
cd
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=2)
def test_shell_fail(testdir):
string = """
```sh
cdc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(failed=1)
def test_shell_expect_fail(testdir):
string = """
```sh
cdc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(xfailed=1)
def test_shell_expect_fail_passed(testdir):
string = """
```sh
cd
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(xpassed=1)
def test_shell_expect_output(testdir):
string = """
```sh
echo abc
```
```sh
abc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_shell_expect_output_fail(testdir):
string = """
```sh
echo abc
```
```sh
ac
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(failed=1)
def test_bash(testdir):
string = """
```bash
foo=1
if [[ $foo == 1 ]]; then
echo abc
fi
```
```sh
abc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
pytest-codeblocks-0.17.0/tests/test_skipif.py 0000664 0000000 0000000 00000004662 14501650272 0021307 0 ustar 00root root 0000000 0000000 def test_skip(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)
def test_skip_expected_output(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
```
25abc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)
def test_skipif(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)
def test_skipif2(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_skipif_expected_output(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
```
25abc
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)
def test_skipif_expected_output2(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
```
4
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
def test_importorskip(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)
def test_importorskip2(testdir):
string = """
Lorem ipsum
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
pytest-codeblocks-0.17.0/tests/test_unicode.py 0000664 0000000 0000000 00000000673 14501650272 0021446 0 ustar 00root root 0000000 0000000 def test_unicode(testdir):
# Unicode identifyers are in fact legal Python code
string = """
```python
# Α α, Β β, Γ γ, Δ δ, Ε ε, Ζ ζ, Η η, Θ θ, Ι ι, Κ κ, Λ λ, Μ μ, Ν ν, Ξ ξ, Ο ο, Π π,
# Ρ ρ, Σ σ/ς, Τ τ, Υ υ, Φ φ, Χ χ, Ψ ψ, Ω ω
α = 1
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)
pytest-codeblocks-0.17.0/tox.ini 0000664 0000000 0000000 00000000202 14501650272 0016544 0 ustar 00root root 0000000 0000000 [tox]
envlist = py3
isolated_build = True
[testenv]
deps =
pytest
pytest-cov
commands =
pytest {posargs} -p pytester