Home > Enterprise >  None value from a function after assert checking
None value from a function after assert checking

Time:05-22

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)
  • Related