By Developers, For Developers

Historical errata for Python Testing with pytest

PDF PgPaper PgTypeDescriptionFixed onComments
67ERROR

Missing code. Top code example is supposed to include this fixture:

@pytest.fixture()
def tasks_db(tasks_db_session):
‘an empty tasks db’
tasks.delete_all()

2017-06-07
12TYPO

Line 2: include closing single quote

-m ‘mark1 and not mark2
…should be…
-m ’mark1 and not mark2’

Line 3: include single quotes around -m argument parameter
-m mark1 or mark2
…should be…
-m ‘mark1 or mark2’

2017-06-07
2TYPO

carrots -> carets

2017-06-07
12TYPO

tests with bother markers
Should be:
tests with both markers

2017-06-07
10TYPO

Is: (a namedtuple called Task )
should be: (a named tuple called Task)

2017-06-19Thanks. But in this case, I really do mean namedtuple, as in collections.namedtuple.
10TYPO

Is: how to use assert affectively in your tests
Should be: how to use assert effectively in your tests

2017-06-07
38SUGGEST

The phrase (used a couple of times) “was ran” should be changed to either “ran” or “was run”.

2017-06-07
6TYPO

Invoking ‘pytest’ in the ‘ch1/’ directory as distributed has 11 tests found, as opposed to the 6 described in the text.

The correct directory to be in is ‘ch1/tasks/’. Then the output is as described.

2017-06-07Good catch. I've changed the code for the next beta release with the correct number of tests in ch1.
1SUGGEST

Chicken and egg: the reader hasn’t installed pytest yet, but the sample text looks like it could be run. The current typesetting does not give a strong visual clue differentiating text-to-be-read-as-example from text-to-be-entered-by-user.

As the book progresses, the context will be clearer to the reader. But this is the first time the reader is exposed to the typography. It might be worth making it clear that this is a read-not-do section. E.g. “We’ll install pytest shortly, but first lets look at some typical files and output.”

2017-06-19Thank you for the suggestion. I'll take this into consideration
117TYPO

There are a number of discrepancies between the latest sample code and the terminal session listings in the book.

For example, in Chapter 3, ‘Tracing Fixture Execution with —setup-show’ it shows ‘cd ch3/tasks_proj/tests/func’ but with the sample code this should be ‘cd ch3/a/tasks_proj/tests/func’. And in later pytest console listings discrepancies with ‘collected n items’ and assertion line number references.

In other words, at some point before ‘final’ edition the pytest sessions need to be re-generated with the final sample code so things match up.

I’m sure same is true of earlier chapters as well but I picked up reading with Chapter 3 in beta-2.

2017-06-20I can imagine that's frustrating while working through examples. I've fixed that one example for the next beta. And I've made a note to make sure to go through all examples before final release. \nI was planning on that anyway, but I appreciate the suggestion. \nThank you for bringing it up.
NASUGGEST

The pytest session listings should include a ‘cd [dir]’ whenever it is necessary to switch to a new directory to run the next script (and maybe this would be good in all cases just for consistency). Would make it a little easier to follow along in ones own terminal window without having to refer to the directory structure by other means.

2017-06-20Thank you for the suggestion. \nI'll take it into consideration, especially during the final review process, and see how it looks.
NASUGGEST

This is a really minor thing, and feel free to ignore it in favor of more important things, but the sample code is not always PEP-8. Mostly it just needs two blank lines between functions etc instead of the one supplied, or wants imports grouped at top of module, etc. For the book one line is probably best (to save space & paper) but when viewing the code in PyCharm (for example) there are all the squiggles due to ‘inspection’ issues.

2017-06-20I've made a note of this. I'll try to pep8-ify things and see if it detracts from the reading process. As I can see it detracts from the following-along process, I'll include a note of pep8 exceptions if we decide to not be pep8 compliant.
63TYPO

This fixture is pretty simple—it just returns the reqeust.param as its value to
the test using it.

2017-06-20Ha! I still had to stare at that for a moment to see the problem. Nice catch.
79SUGGEST

(on windows7)

for test named -
ch4/cache/test_slower.py

was getting 5 pytest-warnings
eg.
’WI9 None cache could not write path D:\\{edit long path}\\cache\\.cache\\v\\duration\\test_slower.py::test_slow_stuff[0]"

stuck for a while until modified the fixture ‘check_duration’ so key variable was modified so that colons were replaced with characters that work in a filename

after line
key = ‘duration/’ + request.node.nodeid
added
key = key.replace(‘:’, ‘=’)

Don’t know if this is the right thing to do, but it got the example working.

2017-06-20Chris, \nThanks for the question and the workaround. \nI'm primarily testing the examples on a Mac, and I don't get those errors. \nPlease let me know of any further issues you have with working through the examples on Windows. \n \nI'm actually going to check with some of the folks from pytest core to get a suggestion for this one. But I like your workaround for now.
13TYPO

In section -s and –capture=method:

“The -s or —capture=now option turns off…”

This should be —capture=no, not “now”.

2017-06-27Wow. --capture=now sure would have a different meaning, huh? Nice catch.
32TYPO

In “Filling out the smoke test”,

“# the [:–1] syntax retruns a list with all but the last element”

“retruns” should be “returns”

2017-06-27
24SUGGEST

windows pitfall - options needs double quotes

The sample for option -k on page 24 is the first one, which works with quotes. Problem is, windows requires double quotes instead single quotes your mac sample work with. So I stumble a while, why -k does not work for me.

Maybe this would be a good place for another “what is different on windows ” info box like on page 18 to explain, that we windows users has to use double quotes where the mac sample work with single quotes

that happens in a dos shell:

(pytest) D:\\…\\ch1>pytest -k ‘asdict or defaults’ —collect-only
= test session starts =
platform win32 — Python 3.6.1, pytest-3.1.1, py-1.4.33, pluggy-0.4.0
rootdir: D:\\git\\bopytest-code\\code\\ch1, inifile:

no tests ran in 0.00 seconds =
ERROR: file not found: or

(pytest) D:\\…\\ch1>pytest -k “asdict or defaults” —collect-only
= test session starts =
platform win32 — Python 3.6.1, pytest-3.1.1, py-1.4.33, pluggy-0.4.0
rootdir: D:\\git\\bopytest-code\\code\\ch1, inifile:
collected 11 items
<Module ‘tasks/test_four.py’>
<Function ‘test_asdict’>
<Module ‘tasks/test_three.py’>
<Function ‘test_defaults’>

= 9 tests deselected 9 deselected in 0.05 seconds ===

2017-07-04Thanks for mentioning this. I've changed the -k option section to use double quotes. I've also made a note to go through the whole book looking for single quotes.
37TYPO

an pytest.ini -> a pytest.ini

2017-07-04
41-64TYPO

excercise -> exercise (in various places)

2017-07-04
43TYPO

we can us it -> we can use it

2017-07-04
43SUGGEST

Recently you can also do pytest.param(‘value’, id=‘foobar’) which is nice because IDs and values are not as separated as they are when passing a list to ids=. Might be nice to mention that when mentioning how ids is used.

2017-07-06Thank you for the suggestion. I'll take it into consideration, and try to work that in.
47SUGGEST

Nitpick: For fixtures without parameters, sometimes “pytest.fixture" is used (without parens), and sometimes "pytest.fixture()” is. Both work, but it feels a bit inconsistent.

2017-07-06This is a reasonable observation. I'll consider when making changes during final edits.
51SUGGEST

For docstrings, the book uses ‘foo’ instead of “”“foo”“” for docstrings. While that works, it’s something I’ve never seen in any Python project, and it violates pep257.

2017-07-06I will consider these changes during final edits, and see how it looks.
53SUGGEST

Perhaps another good reason to use fixtures: The teardown is executed even when the test fails.

2017-07-06Good point. I'll consider adding that during final edits.
59ERROR

I didn’t actually check whether pytest.mark.usefixtures('fixture1, fixture2') works too, but the pytest documentation says pytest.mark.usefixtures(‘fixture1’, ‘fixture2’) (i.e., multiple comma-separated strings, not one string with commas)

2017-07-06Nice catch.
62-64TYPO

equivelant -> eqivalent (or maybe even just “equal”?)

2017-07-04
64ERROR

“With parameterized fixtures, there is another way—we can set the ids parameter to a function we write that provides the identifiers.”

This makes it sound like this isn’t possible when parametrizing tests - but it is.

2017-07-06Thanks. I'll consider changing that verbiage for the final edits.
65SUGGEST

The isinstance(db_path, string_types) check here is something very unidiomatic for Python - and here, it definitely serves no purpose at all (unless it’s just to demonstrate pytest.raises), because anything which isn’t a string would be caught by the else: below already, and raise ValueError.

2017-07-06Thanks. I'm going to do a final code review and retest before final book release. I'll add this to list of things to change/test.
70ERROR

The .write() calls should be replaced by .write_text(), as .write() is error-prone and will probably soon be deprecated. There’s a relevant mailinglist thread in the June 2017 archives for the pytest-dev mailinglist, which I unfortunately can’t link here…

2017-07-06Another good catch. Added to list for final code review.
71TYPO

In “To see how similar tmpdir and tmpdir_factory are are,”: “are” is duplicated

2017-07-04
85SUGGEST

Using re.sub in test_cheese.py seems unnecessarily complex - why not simply:

lambda x: x.replace(‘~’, str(fake_home_dir))

instead?

Also, what a “lambda” is might need some explanation for beginners to Python.

2017-07-06thanks for the suggestion. I've added it to a list of items to consider during final code review.
100TYPO

In “let’s call it “plugin-nice.”", the plugin-nice should probably be pytest-nice, like also reflected in the folder tree below.

2017-07-04
103ERROR

fnmatch_lines doesn’t take regular expressions (otherwise your test_nice example wouldn’t work). It takes globs or maybe “fnmatch-like patterns” or so.

2017-07-06thanks for the info. I'll consider the change.
111ERROR

“The —strict option turns pytest warnings into errors” - this is what the pytest help says (there’s an issue open discussing what to do about that), but not what actually happens. Currently the only thing —strict actually does is disallowing unregistered markers, and it’s likely to stay that way.

2017-07-06Even though it's not in there yet, I think I'll change the book text to reflect the change. Thanks for bringing it up.
113ERROR

venv is actually in the default norecursedirs nowadays, for exactly the reason you mention ;)

2017-07-06Cool. I'll add this to a list of mods during final review.
129SUGGEST

With “def list”, you shadow the python built-in list() function, which is a bit frowned upon. Not sure if it’s worth changing though.

2017-07-06good call. I'll consider changing this during the final code review and retest.
135TYPO

\\-\\tb=short and \\\\-strict have backslashes whichd on’t belong there

2017-07-06
148SUGGEST

Might be a good idea to mention unittest2pytest somewhere (under pytest-dev) which helps with the mechanical work of rewriting unittest tests to pytest.

2017-07-06I've never used it. I'll play with it a bit and consider mentioning it in the book.
152TYPO

The terminal output under “Therefore, the steps are usually just:” isn’t formatted correctly.

2017-07-04
167ERROR

“open” is a macOS-only thing. It might be best to just remove that line, as it should be clear the reader has to open that file I think.

2017-07-06Thanks for the suggestion. I'll consider the change for final edits.
4ERROR

nitpick: Mac OS X is called macOS nowadays

2017-07-04I think I got them all. Thanks for mentioning this.
175TYPO

nitpick: You should adjust the copyright holder and year for a MIT license - you’re not Hynek Schlawack ;)

2017-07-04
124SUGGEST

Since the current directory is tasks_proj_v2, the source code under test is all within src. Adding the option —cov=src generates a coverage report.
become
Since the current directory is tasks_proj_v2 and the source code under test is all within src. Adding the option —cov=src generates a coverage report for that specific directory under test only.

2017-07-06Thanks for the suggestion. I'll consider the change during final mods.
124TYPO

use the html reports. —> use the HTML reports.

a html report is generated. —> a HTML report is generated.

2017-07-06Thanks for the suggestion. I'll consider the change and discuss with editor.
25TYPO

PDF says 25 of 193

It be used as a shortcut to running an individual test if its
name is unique, or running a set of tests that have a common prefix or suffix
in their names.

2017-07-24It be very helpful to have people review my prose. :) \nThank you. \n-> "It can be used...."
xiTYPO

The growth of Python in many critical fields also comes with
it the desire to properly, effectively, and efficiently put software tests in place
to make sure the programs run correctly and produce the correct results.

should read as

The growth of Python in many critical fields also comes with
the desire to properly, effectively, and efficiently put software tests in place
to make sure the programs run correctly and produce the correct results.

2017-08-21
180TYPO

The word “the” is repeated in this sentence:
“However, for information about how to start contributing through PyPI, take a look at the Python Packaging User Guide and the the PyPI section of the Python documentation.”
It should read as:
“However, for information about how to start contributing through PyPI, take a look at the Python Packaging User Guide and the PyPI section of the Python documentation.”

2017-08-21
178TYPO

The word “paste” is spelled wrong in this sentence:
“You can also use an ASCII-formatted README.txt or README, but I’m okay with
copy/past/edit in this instance.”

2017-08-21
153ERROR

This sentence is incorrect:
“As of Python 3.6, the venv virtual environment module is included as part of the standard library.”
The venv module has been part of the standard library since Python 3.3. This is stated on the first line in the Python docs for the venv module: docs.python.org/3/library/venv.html

2017-08-21
170SUGGEST

The pep8 command-line tool was renamed to pycodestyle in the 31 May 2016 release of the tool (pypi.python.org/pypi/pycodestyle). Consider changing references to this tool in this section of the book to reflect the new name.
Also consider changing from pytest-pep8 to pytest-pycodestyle (pypi.python.org/pypi/pytest-pycodestyle). It is a fork from pytest-pep8, but with the newer versions of pycodestyle used instead of the stagnant PyPI pep8 package.
Using the old name for these tools means readers will be using the old, unmaintained versions.

2017-08-21I've added mention to pycodestyle. Thanks for that. \n
55SUGGEST

“”“Test tasks.add() affet on tasks.count().”“”

should read

“”“Test the effect tasks.add() has on tasks.count().”“”

2017-08-21
87TYPO

But it does have a side affect that we can test.

should read

But it does have a side effect that we can test.

2017-08-21
113TYPO

“This list(owner) function depends on a couple of other functions: tasks_db(), which is a context manager, and tasks.list(owner), which is the API function. We’re going to use mock to put fake functions in place for tasks_db() and tasks.list(). Then we can call the list method through the command-line interface and make sure it calls the tasks.list() function correctly and deals with the return value correctly.”

In most cases, list() should be list_tasks()

2017-08-21
113TYPO

“This list(owner) function depends on a couple of other functions: tasks_db(), which is a context manager, and tasks.list(owner), which is the API function. We’re going to use mock to put fake functions in place for tasks_db() and tasks.list(). Then we can call the list method through the command-line interface and make sure it calls the tasks.list() function correctly and deals with the return value correctly.”

In most cases, list() should be list_tasks()

2017-08-21
2TYPO

Typo: “it’s” should be “its” in the following sentence:

‘The failing test, “test_failing,” gets it’s own section to show us why it
failed’

2017-09-06
43TYPO

“to pass lots of data trough” immediately above the test_add_variety.py code should be “to pass lots of data through” (“through” instead of “trough”)

2017-09-06
67TYPO

“generate the identifier for on Task object at a time” should be “generate the identifier for one Task object at a time” (“one” instead of “on”)

2017-09-06
25TYPO

“It can contain directives that change the behaviour of pytest, such as settign up a list of options that will always be used.”

should read

“It can contain directives that change the behaviour of pytest, such as setting up a list of options that will always be used.”

(setting vs. settign …not to mention the British English spelling of ‘behaviour’ instead of the American English spelling.)

2017-09-06
43TYPO

change
“The second argument is list of values, which in our case is a list of Task objects.”
to
“The second argument is a list of values, which in our case is a list of Task objects.”

2017-09-06
46TYPO

“”“Demonstrate paramterize and test classes.”“”
should read
“”“Demonstrate parameterize and test classes.”“”

2017-09-06
46TYPO

“”“We can use the same data or multiple tests.”“”
should be
“”“We can use the same data for multiple tests.”“”

2018-11-02
47TYPO

The sentence
“You can also identify parameters by including an id right alongside the parameter value when passing in a list within the @pytest.mark.paramtrize() decorator.”
has parametrize misspelled.

2017-09-06
52TYPO

“We’re still writing tests to be run against the Tasks project in this chapter, which was first installed in the Chapter 2.”
should read:
“We’re still writing tests to be run against the Tasks project in this chapter, which was first installed in Chapter 2.”

2017-09-06
59TYPO

“With this knowledge of scope, let’s now change the scope of some the Task project fixtures.”
should read:
“With this knowledge of scope, let’s now change the scope of some of the Task project fixtures.”

2017-09-06
111TYPO

In the last sentence of the first paragraph, ‘…discuss how pytest changes it’s behavior’ should be ‘…discuss how pytest changes its behavior’ (‘its’ instead of ‘it’s’)

2017-09-06
117SUGGEST

The second sentence in the final bullet of the test discovery list confused me at first: “Look for methods in those classes that start with test_ . but don’t have an init method.”

The phrasing suggests that the test* methods themselves can’t haveinit_ methods, but it’s the classes that can’t have init methods. I’d suggest rephrasing it to make this more clear. For example, the entire bullet point could be rewritten like this:

Look for classes that start with Test but do not have init_ methods. Look for methods in those classes that start with test_.

2017-09-06
61ERROR

Change
“usefixtures takes a string that is composed of a comma-separated list of fixtures to use.”
to
“usefixtures takes a comma separated list of strings representing fixture names.”

2018-11-02
63TYPO

The sentence:
“Here, lue is now the fixture name, instead of fixture_with_a_name_much_longer_than_lue.”
should be changed to:
“Here, lue is now the fixture name, instead of ultimate_answer_to_life_the_universe_and_everything.”

2018-11-02
63TYPO

The test run output is incorrect. The line:
“test_rename_fixture.py::test_everything_2 (fixtures used: lue).”
should be changed to:
“test_rename_fixture.py::test_everything (fixtures used: lue).”

2018-11-02
74SUGGEST

Consider changing the variable name in this line:
“file = tmpdir_factory.mktemp(‘data’).join(‘author_file.json’)”
You could use ‘file_’ or anything other than ‘file’ since that is a built-in function in Python2.
I know the test code was written for Python3, but some people might still run it with Python2 and this syntax sticks out as a bad practice.

2018-11-02
24-25TYPO

There are two related issues, one of which is an outright error. Note that I am using the sample files downloaded today from the tar file.

1. The book reads “The test file, tests/test_task.py, contains the tests”. In my sample files, the file is located in ch2/tasks_proj/tests/unit/test_task.py. Or tests/unit/test_task.py if you prefer (though see issue #2). You left out (as a minimum) the unit/ subdirectory.

2. This section (pages 24-25 in the beginning of chapter 2) is incredibly confusing since you never provide context for which subdirectory this source code is from, AND you switch with no warning from one directory to a completely different directory on page 25. You never say what directory the directory structure found on page 24 is in, and an assumption of it being in code/ch2/ is of course wrong (it is actually in code/tasks_proj).

But then, with no warning, you talk about the tests/test_task.py (which is a typo, see issue #1), which is not in code/tasks_proj but rather in code/ch2/tasks_proj/tests/unit. Combine this lack (and sudden change) of context with the fact that there is no tests/test_task.py, and the result is, shall we say, a bit frustrating.

Note: This is on pages labeled 24 & 25 in the PDF, not the 24th page in the PDF.

2018-11-01
31TYPO

“”"
To add a smoke test suite to the Tasks project, we can add mark.pytest.smoke to some of the tests. Let’s add it to a couple of tests in test_api_exceptions.py (note that the markers smoke and get aren’t built into pytest; I just made them up): """ mark.pytest.smoke should be @pytest.mark.smoke

2018-11-02
15TYPO

In the first paragraph after the example, filenames “test\\_two.py” and “test\\_one.py” shouldn’t have backslashes in them.

2018-11-01
88TYPO

“This little function uses the regular expression module function re.sub to replace ~ with our new temporary directory.” - code (book and src) uses replace though: lambda x: x.replace(‘~’, str(fake_home_dir))

2018-11-02
47TYPO

“To add a smoke test suite to the Tasks project, we can add @mark.pytest.smoke to some of the tests”

The above should say @pytest.mark.smoke.

2018-11-02
80TYPO

At: “You can pass in —clear-cache to clear the cache before the session.”

The right argument is “—cache-clear”.

2018-11-02
134TYPO

The first sentence says: “Let’s pause and install version 3 of Tasks:” but then the following code snippet has “$ pip install -e ch7/tasks_proj_v2” — “version 3” should presumably be “version 2”.

2018-11-02
135TYPO

In the text (in various places on this page), the function “tasks_db()” is mentioned. However, the code defines “_tasks_db()”: the text is missing the leading underscore in the function name.

2018-11-02
136TYPO

The inline code in the second-last line on the page has ‘tasks_db’ instead of ‘_tasks_db’: the leading underscore is missing.

2018-11-02
51TYPO

Next, let’s rework some our tests for tasks_proj to properly use fixtures.

It should be: […] some OF our tests […]

2018-11-02
13SUGGEST

“use the —maxfail option to specify how many failures are okay with you.”

If I specify —maxfail=1 it stops at the first failure (just like -x). That doesn’t mean that I am “okay with 1 failure”. I am okay with 0 failures and I want to exit after 1 failure.

2018-10-31
13TYPO

The section heading for maxfail only has one dash, should be two: this “–maxfail=num” should be: “—maxfail=num”

2018-10-31
77TYPO

At the beginning of the ‘using cache’ section the phrase:
We want to make sure ‘order’ dependencies
Should be ‘other’

2018-11-02
114SUGGEST

In the book on pg. 114, the code snippets for pytest.ini, tox.ini and setup.cfg contain a line like this:
> … more options …

These lines are also included in the code, meaning in the files (pytest.ini, tox.ini and setup.cfg). If you do “pytest —help” in the ch6/format/ folder, you’ll get an error.

If you put a comment “;” in front of “… more options…”, the command “pytest —help”, when run in this particular folder, will run again.

2018-11-02
26ERROR

Final code snippet on this page has two “pip install” commands. The first says

pip install ./tasks_proj/

The second says

pip install —no-cache-dir ./tasks_proj

I believe any one of the commands in isolation is sufficient. If both are run consecutively, then the last command will simply echo “Requirement already satisfied” for all the packages that need to be installed. I suspect the final command was the one the author wanted, but am unsure.

2018-11-01
4429TYPO

The test file, tests/test_task.py, contains the tests we worked on in Running pytest, in files
test_three.py and test_four.py.

The correct path should be tests/unit/test_task.py

2018-11-02
25TYPO

“Installing a Package Locally
The test file, tests/test_task.py, contains …”

The partial path should be ‘tests/unit/test_task.py’ as per the header comment to the fisrt code snippet on P26

2018-11-01
40SUGGEST

The tinydb package has replaced “eid” with “doc_id”. This causes a Deprecation Warning when running the tests the involve tinydb, starting midway through Chapter 2. This is easily fixed by replacing “eid” with “doc_id” in …/code/tasks_proj/src/tasks/tasksdb_tinydb.py.

2018-11-02
32 34ERROR

In ch2 the name of the marker after -m option should be in double quotes not single quotes.
Especially when combining markers e.g. ‘smoke and get’ generated a “file not found” error, when run on a Windows PC
In ch1 the examples all use double quotes (or none)

2018-11-02
14SUGGEST

In the case of using the Windows platform, I ran into several issues while trying out the given session.

Must be created the folder for the database TinyDB for filename tasks_db in the folder of your user. For example c:\\Users\\User_1\\tasks_db\\
Use quotes instead of apostrophes. Otherwise, we get this error.

$ tasks add ‘do something else’ Usage: tasks add [OPTIONS] SUMMARY

Error: Got unexpected extra arguments (something else’)

46SUGGEST

For parametrize class example, the second function “def test_valid_id” is not indented correctly

11TYPO

s/is a percentage inticator/is a percentage indicator/

25SUGGEST

This line lacks context: The test file, tests/unit/test_task.py,

Suggest: s|The test file, tests/unit/test_task.py,|The test file, ch2/tasks_proj/tests/unit/test_task.py|

14TYPO

In the following fragment a line is printed two times:
“$ pytest —ff —tb=no”

START FRAGMENT
—ff, —failed-first
The —ff/—failed-first option will do the same as —last-failed, and then run the rest
of the tests that passed last time:
$ cd /path/to/code/ch1
$ pytest —ff —tb=no
$ pytest —ff —tb=no
= test session starts =
END FRAGMENT

17TYPO

Dangling E

—tb=style

… prints just the assert line and the E evaluated line with no context; …

21TYPO

Found a small typo: ‘parametrizing’ should be ‘parameterizing’.

25TYPO

“There should be at most only one of these in your project” is a little redundant either: “There
should be at most one of these in your project” or “There should be only one of these in your project”

26SUGGEST

“The test_task.py file has this import statement:
from tasks import Task
The best way to allow the tests to be able to import tasks or from tasks import something
is to install tasks locally us”

Might I suggest, for simplicity sake, to remove this section and the following paragraphs about pip installing the lib to a later portion of the book? You could have people import …tasks in the test files. If people are writing tests for web apps they’ll never pip install the application and will always directly import the file(s) under test using a relative path. So rather than jumping into a topic specific for writing tests for libraries you could focus on the tests rather than this added/unnecessary complexity.

140SUGGEST

“However, adding a custom command-line option and reading it from pytestconfig is common enough that I want to cover it here.”

The texts some basic examples but I’d like to know when you’d want to add a command line option? I haven’t found the need to add any in all the years I’ve used python/nose/pytest; especially given the existing pytest command line options(?) Giving real-world examples would be very helpful here; I’d love to know what you’ve found useful to add via the command line (as opposed to using a mark for example)

118SUGGEST

“This works well for code you want to run at certain times, but tests don’t really depend on any system state or data from the fixture”

We use autouse=True tests in function or class scope as xUnit-style setup methods; AFAIK it’s a pretty common use case that would be useful to mention.

?SUGGEST

Using online version:
Ch 2: Writing Test Functions; Testing a package:

Description given for installing package locally is insufficient.
Having reached the end of this section, running
> pytest test_task.py
gives:

ERROR collecting unit/test_task.py _
ImportError while importing test module ‘/Users/dsatterthwaite/Learning/completePython/testing/pytest_learn/task_proj/tests/unit/test_task.py’.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test_task.py:2: in
from tasks import Task
E ImportError: cannot import name ‘Task’

I have copied in the code from the book source code (i.e., am not missing setup.py), and run the pip install command as described.

In task_proj/src/tasks/task.py I have

from collections import namedtuple
from six import string_types

  1. Task element types : [summary: str, owner: str, done: bool, id: int]
    Task = namedtuple(‘Task’, [‘summary’, ‘owner’, ‘done’, ‘id’])
    Task.new.defaults = (None, None, False, None)
16-18ERROR

Unless I missed a step to modify test_four, mine doesn’t fail from a fresh clone, only test_two has failures. So on pages 16 - 18 referring to test_four as failing doesn’t occur for me.

(pytest_learning) (shaffek-mac)ch1$ pytest -l tasks
test session starts
platform darwin — Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: /Volumes/src/projects/pytest_learning/code/ch1
collected 4 items

tasks/test_four.py .. [ 50%]
tasks/test_three.py .. [100%]

(pytest_learning) (shaffek-mac)ch1$ pytest -l
test session starts
platform darwin — Python 3.7.3, pytest-4.5.0, py-1.8.0, pluggy-0.11.0
rootdir: /Volumes/src/projects/pytest_learning/code/ch1
collected 6 items

test_one.py . [ 16%]
test_two.py F [ 33%]
tasks/test_four.py .. [ 66%]
tasks/test_three.py .. [100%]

= FAILURES ==
_ test_failing

def test_failing():
> assert (1, 2, 3) (3, 2, 1) E assert (1, 2, 3) (3, 2, 1)
E At index 0 diff: 1 != 3
E Use -v to get the full diff

test_two.py:2: AssertionError
1 failed, 5 passed in 0.09 seconds =
(pytest_learning) (shaffek-mac)ch1$

100TYPO

In file ch4/authors/conftest.py, the author_file_json function has a typo:
“”“Demonstrate tmpdir_factory.”“”

import json
import pytest

@pytest.fixture(scope=‘module’)
def author_file_json(tmpdir_factory):
“”“Write some authors to a data file.”“”
python_author_data = {
‘Ned’: {’City’: ‘Boston’},
‘Brian’: {’City’: ‘Portland’},
‘Luciano’: {’City’: ‘Sau Paulo’}
}

file_ = tmpdir_factory.mktemp(‘data’).join(‘author_file.json’)
print(‘file:{}’.format(str(file_)))

with file_.open(‘w’) as f:
json.dump(python_author_data, f)
return file_

It’s written as “test” and not “test_”.
Thanks for the great book.

101ERROR

Using python3 with pytest 5.1.0, I get the following error:

cd ~/pytest_book/code/ch5/c/tasks_proj/tests
pytest

INTERNALERROR> AttributeError: module ‘pytest’ has no attribute ‘config’

i had to make the following change to “code/ch5/c/tasks_proj/tests/conftest.py” to fix this:

$ diff -c conftest.py.old conftest.py

* conftest.py.old\t2019-08-23 15:17:59.910172379 +0100
—- conftest.py\t2019-08-23 15:18:22.322516958 +0100
*

* 73,86
help=“nice: turn failures into opportunities”)

! def pytest_report_header():
“”“Thank tester for running tests.”“”
! if pytest.config.getoption(‘nice’):
return “Thanks for running the tests.”

! def pytest_report_teststatus(report):
“”“Turn failures into opportunities.”“”
if report.when == ‘call’:
! if report.failed and pytest.config.getoption(‘nice’):
return (report.outcome, ‘O’, ‘OPPORTUNITY for improvement’)
—- 73,86 ——
help=“nice: turn failures into opportunities”)

! def pytest_report_header(config):
“”“Thank tester for running tests.”“”
! if config.getoption(‘nice’):
return “Thanks for running the tests.”

! def pytest_report_teststatus(report,config):
“”“Turn failures into opportunities.”“”
if report.when == ‘call’:
! if report.failed and config.getoption(‘nice’):
return (report.outcome, ‘O’, ‘OPPORTUNITY for improvement’)

84TYPO

In the bottom paragraph, “The captured stdout and stderr are retrieved from capsys.redouterr() …”. The redouterr() should be readouterr(). There is an “a” missing.

74TYPO

You have file_ and file without the _ in some places in the function. I think you want to replace file with file_ when this is seen. I saw a note in previous errata that probably caused the mismatch. Great book. Keep up the great work.

83TYPO

Looks like the pytest Github repo has restructured since publication, moving the _pytest directory under a top level ‘src’ directory.

This breaks the link to cacheprovider.py in the footnote.

40SUGGEST

``README.rst is not included in the downloaded repository. Either remove it from the directory listing or add it to the repository.

242ERROR

The code for ch5/tasks_proj/tests/conftest.py should be:
def pytest_report_header(config):
if config.getoption(‘nice’):

And include config parameter in the following function as well:

def pytest_report_teststatus(report, config):
if report.when == ‘call’:
if report.failed and config.getoption(‘nice’):
….

Both hooks need the config parameter to have access to the getoption attribute that’s within the _pytest.config.Config class that provides said getoption attribute to both hooks.

74TYPO

Hi I am also from Sao Paulo, Brazil and spelling is Sao not Sau :)

I think you are referring to Luciano Ramalho if so it is Sao Paulo :)

python_author_data = {
‘Ned’: {’City’: ‘Boston’}, ‘Brian’: {’City’: ‘Portland’}, ‘Luciano’: {’City’: ‘Sao Paulo’}
}

Also picked the file variable not defined… because it was actually declared as file_ but someone already reported. cheers.

Book is very good thanks !

46TYPO

In the middle of the page,
$ pytest -v ‘tests/func/test_add_variety.py::TestAdd::test_equivalent[Task(wake,brian,False)]’

should be

$ pytest -v ‘tests/func/test_add_variety.py::TestAdd::test_equivalent[Task(wake,brian,False)0]’

35ERROR

To get the “unique_id” tests to run, I had to make the following package change:
diff —git a/src/tasks/tasksdb_tinydb.py b/src/tasks/tasksdb_tinydb.py
index 08e2c0e..0ae3bfb 100644
—- a/src/tasks/tasksdb_tinydb.py
+ b/src/tasks/tasksdb_tinydb.py
@@ –54,7 +54,7 @@ class TasksDB_TinyDB(): # noqa : E801
def unique_id(self): # type () -> int
“”“Return an integer that does not exist in the db.”“”
i = 1
- while self._db.contains(doc_ids=[i]):
+ while self._db.contains(doc_id=i):
i += 1
return i
My system insists “doc_ids” is not an acceptable named parameter, even though the documentation says it should be.

Here’s what it’s using:

$ pip install tinydb
Requirement already satisfied: tinydb in /Users/jsh/Desktop/Python/pytest/book/pytest/lib/python3.7/site-packages (4.1.1)

1ERROR

AttributeError: ‘Table’ object has no attribute ‘purge’
Where:
Chapter “CHANGING SCOPE FOR TASKS PROJECT FIXTURES”
$ cd /path/to/code/ch3/b/tasks_proj
$ pytest

Fix:
Changelog TinyDB v4.0.0 (2020-05-02):
Table.purge() has been renamed to Table.truncate()

Files:
code/tasks_proj/src/tasks/tasksdb_tinydb.py
code/ch7/tasks_proj_v2/src/tasks/tasksdb_tinydb.py
code/tasks_proj/build/lib/tasks/tasksdb_tinydb.py

Categories: