I am writing a function that checks the output of a notebook file and checks against an assert expression to match the output. But I get a None value when I print the output from the function.
from testbook import testbook
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
score = 0.0
assert tb.cell_output_text(7) == 'Test passed.'
return score 1
assert tb.cell_output_text(13) == 'Test passed.'
return score 1
assert tb.cell_output_text(17) == 'Test passed.'
return score 1
assert tb.cell_output_text(21) == 'Test passed.'
return score 1
res = test_stdout()
print(res)
I want to return the output as 4.0 after running the assert.
CodePudding user response:
Ouroborus is right, assert
raises exceptions and stops the execution if the condition is not met, and return
returns the value and stops execution, so anything after that won't run. So your code will either return the first value if the first condition is met, or raise exceptions...
I highly doubt this is what you wanted.
Instead you should use if
statement and put return
inside blocks:
from testbook import testbook
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
score = 0.0
if tb.cell_output_text(7) == 'Test passed.':
return score 1
if tb.cell_output_text(13) == 'Test passed.':
return score 1
if tb.cell_output_text(17) == 'Test passed.':
return score 1
if tb.cell_output_text(21) == 'Test passed.':
return score 1
res = test_stdout()
print(res)
And the above won't run, it will raise missing required positional argument at position 1
or something like that, I didn't run your code but I know exactly what it will do.
You should do it like this:
res = test_stdout(tb)
But then again, if you just copy paste it into a console, it will raise NameError: tb is not defined
or something to that effort, you should define it first.
But I don't know what tb
is so I can't magically define it for you.
I really don't know what you are trying to do, but I am absolutely sure your code doesn't give you what you wanted. Here is a possible implementation of what I guess is your intention:
from testbook import testbook
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
score = 0
for i in (7, 13, 17, 21):
if tb.cell_output_text(i) == 'Test passed.':
score = 1
return score
Irrelevant secret message
42e71e9b014d2e80 42f0b0aa5ff7ee50 42f15518f3cd5910 42f1a4cc1ef4b650 42d493e9ddb5b140 42d4948c66382140 42d4956f47a4df80 42d48d51ef98c800 42f24b3168c10c40 42ef238c972f6bc0 42d4940a6d161e40 42f1d08a4b75b820 42f0335300c85100 42f274b887f0c690 42f00a456fe2e440 42d49347aed781c0 42f29b1cd0ec2440 42f035ebf3fbea10 42f1a6f2fc6aba80 42f0da295b396990 42f17e47515eb700 42f29d64997b6470 42dc3d4f9762dc80 42f035620dc1f390 42d49368784f01c0 42f29b1cd0ec2440 42f035ebf3fbea10 42f1a6f30f88e690 42f29b1cbdb4f500 42f2748f74151890 42f00c956ad23bc0 424c26c865af0000
CodePudding user response:
If your goal is to count the number of successful assertions, it's either 4 or you can't get it because an exception was raised. If you use regular checks instead of assertions, you can change that, because the function won't raise an error on the first falsy check it encounters:
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
score = 0
score = tb.cell_output_text(7) == 'Test passed.'
score = tb.cell_output_text(13) == 'Test passed.'
score = tb.cell_output_text(17) == 'Test passed.'
score = tb.cell_output_text(21) == 'Test passed.'
return score
If you want to short-circuit and return immediately on an error, a return after each test is more appropriate. You can use a loop at that point, to (arguably) simplify the code:
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
cells = [7, 13, 17, 21]
score = 0
for cell in cells:
if tb.cell_output_text(cell) != 'Test passed.':
break
score = 1
return score
Using this structure, you could rewrite the first example using sum
:
@testbook('ssnn_solved.ipynb', execute=True)
def test_stdout(tb):
cells = [7, 13, 17, 21]
return sum(tb.cell_output_text(cell) == 'Test passed.' for cell in cells)