You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It appears that is impossible to use the execute=False capability of testbook and tb.patch() together due to patched code getting run twice.
Consider this example with a simple two cell notebook; the first cell defines a simple function, the second calls it and prints out some results:
importiofromtestbookimporttestbooknotebook_str="""{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "f92b5b71", "metadata": {}, "outputs": [], "source": [ "def test():\\n", " return int()" ] }, { "cell_type": "code", "execution_count": null, "id": "ece15770", "metadata": {}, "outputs": [], "source": [ "print(test())\\n", "print(test)" ] } ], "metadata": { "jupytext": { "hide_notebook_metadata": true }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" } }, "nbformat": 4, "nbformat_minor": 5}"""# Execute is False as we want to patch the target method before executionwithtestbook(io.StringIO(notebook_str), execute=False) astb:
# Patch `int()` but could be any imported functionwithtb.patch("__main__.int", return_value="Hello World!") asmock_test:
tb.execute()
# Print cell outputs nicely so we can see what was printed# Mocked "Hello World!" is output as expectedforidx, cellinenumerate(tb.cells):
outputs_texts= [o["text"].strip() foroincell.outputs]
outputs_texts="\n".join(outputs_texts)
outputs_texts=outputs_texts.split("\n")
ifoutputs_texts:
foro_idx, outputinenumerate(outputs_texts):
print(f"{idx}.{o_idx}: {output}")
else:
print(f"{idx}: No output")
# I would expect this to work as executed in one cellmock_test.assert_called_once() # AssertionError: Expected 'int' to have been called once. Called 0 times.
Output:
0.0:
1.0: Hello World!
1.1: <function test at 0x10b04e430>
2.0:
AssertionError: Expected 'int' to have been called once. Called 0 times.
The underlying issue seems to be that .patch() works by injecting a new cell at the end, executing it immediately, but leaving it in place (rather than popping it off). This means that the patch-cell gets called twice: once at injection, once at .execute() which results in a new Mock instance being created and assigned to the same variable name.
Ideally there should be a way to specify to pop off the patch-cell (by passing through the appropriate kwarg to .inject()) or even for this to be the default behaviour.
The text was updated successfully, but these errors were encountered:
It appears that is impossible to use the
execute=False
capability oftestbook
andtb.patch()
together due to patched code getting run twice.Consider this example with a simple two cell notebook; the first cell defines a simple function, the second calls it and prints out some results:
Output:
The underlying issue seems to be that
.patch()
works by injecting a new cell at the end, executing it immediately, but leaving it in place (rather thanpop
ping it off). This means that the patch-cell gets called twice: once at injection, once at.execute()
which results in a newMock
instance being created and assigned to the same variable name.Ideally there should be a way to specify to
pop
off the patch-cell (by passing through the appropriate kwarg to.inject()
) or even for this to be the default behaviour.The text was updated successfully, but these errors were encountered: