2017-12-01 10 views
1

私はPythonで実装された簡単なテストベンチを持っています。exec()で実行されるコードで定義された関数のスコープ

テストランナーは一連の機能をテストに公開します。 これはテストを書くためのドメイン固有の言語と考えることができます。 ほとんどのテストケースは、これらの関数の呼び出しの単純なシーケンスを形成します。制御フロー文を含むこともありますが、それより複雑なものはありません。

ここで、いくつかのテストケースが複雑すぎるため、関数を使用してリファクタリングすると恩恵を受けます。 これは私が問題にぶつかるところです。 関数内から、テストケース内で定義されたローカルシンボルにアクセスできません。ランナーが公開する機能にアクセスすることもできません(ログと確認)。

''' Testing variable scopes in exec()''' 

PRG_1 = ''' 
a = 42 
log('Testing a = ' + str(a)) 
verify(a, 42) 
''' 

PRG_2 = ''' 
a = 42 
def f(): 
    c = a # Error 'a' not defined 
    log(c) # Error 'log' not defined 

f() 
''' 

class TestRunner(): 
    def __init__(self, prg): 
     self.prg = prg 

    def log(self, msg): 
     print(msg) 

    def verify(self, a, b): 
     print('PASSED' if a == b else 'FAILED') 

    def run(self): 
     # Bring methods into local scope to avoid having 'self.' in DSL 
     log = self.log 
     verify = self.verify 

     # Execute test 
     exec(self.prg) 

r = TestRunner(PRG_1) 
r.run() 

r = TestRunner(PRG_2) 
r.run() 

どのように私はこれを動作させることができますか? 多分これを達成するための別の(そして良い方法)があります。私はC++開発者としては見えません。

$ python3 test.py 
Testing a = 42 
PASSED 
Traceback (most recent call last): 
    File "test.py", line 42, in <module> 
    r.run() 
    File "test.py", line 35, in run 
    exec(self.prg) 
    File "<string>", line 7, in <module> 
    File "<string>", line 4, in f 
NameError: name 'a' is not defined 
+0

ローカルとグローバルを 'exec'に渡すことができます。[documentation](https://docs.python.org/3/library/functions.html#exec) – FujiApple

+0

を参照してください。' exec(self.prg、 globals = globals()、locals = locals()) 'を取得しましたが、' TypeError:exec()はキーワード引数を取りません。その後、代わりに位置引数を使用してみましたが、助けにはなりませんでした。 –

答えて

2

そうした場合:

def run(self): 
    exec(self.prg, {'log': self.log, 'verify': self.verify}) 

が生成されます一般的に

42 

良いアイデアとにかく、このような動的なコードの実行を避けるために!

+0

ありがとうございます。これは私の問題を解決するかもしれません。スコープに 'log'と' verify'を追加しました。これはテストケースのローカル変数である 'a'ではありません。今私の小さな例が働いています。私はラッパー関数を使用しませんでしたが、何らかの理由で 'a'がとにかく見つかりました。 –

+0

私は動的コード実行の潜在的なセキュリティ問題を理解していますが、このケースではテストケースを書くすべての人が信頼されており、悪意のあるコードを実行したければ実際のテストベンチを変更する可能性があります。動的実行を避ける他の理由はありますか? –

+0

セキュリティが私が念頭に置いていた理由でした。それ以外にも、コードの可読性、IDEの統合、構文の強調表示などが考えられます。 – FujiApple

関連する問題