se2p / pynguin

The PYthoN General UnIt Test geNerator is a test-generation tool for Python
https://www.pynguin.eu
MIT License
1.22k stars 74 forks source link

Request option to ignore the if __name__ == '__main__' section of a module #63

Closed sjswerdloff closed 4 weeks ago

sjswerdloff commented 3 months ago

I have modules that contain a "main" section so that they can be used as executable scripts in addition to providing library capabilities.

when I try to generate tests: pynguin --project-path ./ --output-path /tmp/pynguin-results --module-name echoscp -v

at the bottom of the verbose listing is:

NetworkXError: The node ProgramGraphNode(2)
LOAD_NAME 'sleep'
LOAD_CONST 100
CALL_FUNCTION 1
POP_TOP
JUMP_ABSOLUTE ProgramGraphNode is not in the digraph.

Modifying the module to remove the main section:

diff echoscp.py nomainechoscp.py 
56,60d55
< if __name__ == '__main__':
<     myecho_scp = EchoSCP()
<     myecho_scp.run()
<     while True: sleep(100) # sleep forever
<     

and running pynguin --project-path ./ --output-path /tmp/pynguin-results --module-name nomainechoscp -v I get a successful result.

I realise that how sleep() is handled might be the root cause of the "failure", but frankly, I really just want to not create tests for the main section. That's not a "unit". I also realise that if I had created a main() and called it from with if name == 'main' I would have the same problem and it would not be avoided even with fulfillment of this enhancement request. Solving that problem seems to be closer to #62

BergLucas commented 3 months ago

Hi,

I've checked this issue and I've been able to reproduce the bug with the following code:

if __name__ == "__main__":
    while True:
        pass

I think that the bug is caused by a Python bytecode optimization that causes the "while True" node to have a link that loops back on itself. This prevents the current algorithm from linking the "while true" node to the dummy exit node and therefore when the graph is reversed to calculate the dominance tree, the assumption that there is only a single entry node is no longer respected. The error is due to the fact that only the other entry node is used and that the "while True" node is ignored when the dominance tree is created.

Here is what the augmented graph looks like before being reversed to calculate the dominance tree: Augmented graph

I said that I think it's an optimization of the bytecode that's causing the problem because the following code doesn't cause any errors even though it does exactly the same thing:

if __name__ == "__main__":
    x = True
    while x:
        pass

Have a nice day!