简体   繁体   中英

How to capture assert in python script

Is there any way in Python2.7, we can capture and log the assert statements in general python scripting despite of assert is True or False Suppose I assert following line in code:

assert len(lst) ==4

So is any way can log what statement is passed, at what line and it is true or false. I do not want to use a wrapper function, looking for something inbuilt in python .

Note: What I want to achieve is , suppose I have legacy code having 1000's of assert statements , without changing the code, I should be able to log which assert statement is executed and what is the output, Is its achievable in python 2.7.

try:
    assert len(lst) == 4    
    print "True"
except AssertionError as e:
    print "False"

Yes, you can define a custom excepthook to log some extra information:

import sys
import logging
def excepthook(*args):
  logging.getLogger().error('Uncaught exception:', exc_info=args)

sys.excepthook = excepthook

assert 1==2

EDIT: Whoops I forgot you wanted to log even if it's true :) oh well I'll leave this for a little bit in case it informs you or someone else...

This is what I could achieve closet, as does not seem it is possible in Python2.7 . I created a wrapper function.

import inspect

def assertit(condition,message):
    # The caller method
    (frame, filename, line_number,function_name, lines, index) = inspect.getouterframes(inspect.currentframe())[1]


    detailed_message=" => {message} [  {filename} : {line_number}]".format(message=message,line_number=line_number,
                                                                         filename=filename)

    if condition:
        print "True  %s"%detailed_message
        return
    raise AssertionError("False: %s"%detailed_message)
assertit(1==1,"Check if 1 equal 1")
assertit(1==2,"Check if 1 equal 2")

### HERE IS THE OUTPUT
True   => Check if 1 equal 1 [  test_cases.py : 20]
Traceback (most recent call last):
  File "test_cases.py", line 21, in <module>
    assertit(1==2,"Check if 1 equal 2")
  File "test_cases.py", line 19, in assertit
    raise AssertionError("False: %s"%detailed_message)
AssertionError: False:  => Check if 1 equal 2 [  test_cases.py : 21]

This is a proof of concept. So please downvote, or I will delete it... The idea is to replace the assert statement with print statement at the execution.

import ast
import inspect

from your_module import main

def my_assert(test_result, msg):
    assert test_result, msg
    # if test_result is True, just print the msg
    return "assert: {}, {}".format(test_result, msg)

class Transformer(ast.NodeTransformer):
    def visit_Assert(self, node):
        f = ast.Name(id='my_assert', ctx=ast.Load())
        c = ast.Call(func=f, args=[node.test, node.msg], keywords=[])
        p = ast.Print(values=[c], nl=True)

        # set line#, column offset same as the original assert statement
        f.lineno = c.lineno = p.lineno = node.lineno
        f.col_offset =c.col_offset = p.col_offset = node.col_offset

        return p


def replace_assert_with_print(func):
    source = inspect.getsource(func)
    ast_tree = ast.parse(source)
    Transformer().visit(ast_tree)
    return compile(ast_tree, filename="<ast>", mode="exec")

if __name__ == '__main__':
    exec(replace_assert_with_print(main))
    main(4)

And here is your_module.py

def main(x):
    assert x == 4, "hey {} is not 4".format(x)
    return x

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM