Pytest - Fixture对功能级别的反思

时间:2015-11-05 15:42:26

标签: python pytest fixtures introspection

我有一个需要测试功能变量的灯具。使用内省并在函数名称空间/上下文中声明变量应该有效,如果函数级别的内省工作,就像模块级别一样,但每次运行代码时我最终都会使用None而不是字符串" Fancy Table& #34;

在灯具中,我将范围设置为'功能'然后通过getattr和request.function进行内省:

#conftest.py
@pytest.fixture(scope='function')
def table(request):
    from data_setup import create_table
    table_name = getattr(request.function, "table_name", None)
    create_table(request, table_name)

我在测试函数中声明了变量table_name:

#test_file.py
class TestTable():

    @pytest.mark.tags("table")
    def test_create_table(self, test_db):
        table_name = "Fancy Table"
        current_page = TablePage(self.test_driver, test_db)
        current_page.go_to_kitchen("Eva", "Evas Kitchen")
        current_page.create_first_table(expected_table_name)
        Validation.assert_equal(expected_table_name, current_page.get_name(), "Table had the wrong name!")

在模块级别上执行此操作已经起作用,但是在我尝试在功能级别上执行此操作时,夹具再次吐出无。我在功能级别上使用夹具内省是错误的吗?如果不是这样的话怎么用?

3 个答案:

答案 0 :(得分:2)

函数变量是本地的,在函数返回后被销毁,它们不以任何方式绑定到函数对象......这就是Python的工作原理,与py.test无关。

如果将table_name局部变量明确地绑定到测试函数,那么您的示例将起作用,有效地使其比其通常的生命周期更长:

@pytest.mark.tags("table")
def test_create_table(self, test_db):
    test_create_table.table_name = "Fancy Table"

另一方面,明确地将table_name传递给TablePage会不会更简单?它会更简单,更直接,更明确。 :)

答案 1 :(得分:0)

将本地变量显式绑定到测试函数导致我的IDE抱怨未解析的引用。我们需要知道还有什么可以使这项工作?

在给出的示例中,当我写test_create_table时,print "Found %d objects: %s" % (len(objects), [x.value() for x in objects]) #-----------------------------CUTOFF FOR BAD ATTRIBUTE TYPE---------------------------- all_attributes = PyKCS11.CKA.keys() # only use the integer values and not the strings like 'CKM_RSA_PKCS' all_attributes = [e for e in all_attributes if isinstance(e, int)] attributes = [ ["CKA_ENCRYPT", PyKCS11.CKA_ENCRYPT], ["CKA_CLASS", PyKCS11.CKA_CLASS], ["CKA_DECRYPT", PyKCS11.CKA_DECRYPT], ["CKA_SIGN", PyKCS11.CKA_SIGN], ["CKA_VERIFY", PyKCS11.CKA_VERIFY], ["CKA_ID", PyKCS11.CKA_ID], ["CKA_MODULUS", PyKCS11.CKA_MODULUS], ["CKA_MODULUS", PyKCS11.CKA_MODULUS], ["CKA_MODULUS_BITS", PyKCS11.CKA_MODULUS_BITS], ["CKA_PUBLIC_EXPONENT", PyKCS11.CKA_PUBLIC_EXPONENT], ["CKA_PRIVATE_EXPONENT", PyKCS11.CKA_PRIVATE_EXPONENT], ] for o in objects: print print (red + "==================== Object: %d ====================" + normal) % o.value() attributes = session.getAttributeValue(o, all_attributes) attrDict = dict(zip(all_attributes, attributes)) if attrDict[PyKCS11.CKA_CLASS] == PyKCS11.CKO_PRIVATE \ and attrDict[PyKCS11.CKA_KEY_TYPE] == PyKCS11.CKK_RSA: m = attrDict[PyKCS11.CKA_MODULUS] e = attrDict[PyKCS11.CKA_PUBLIC_EXPONENT] if m and e: mx = eval('0x%s' % ''.join(chr(c) for c in m).encode('hex')) ex = eval('0x%s' % ''.join(chr(c) for c in e).encode('hex')) if sign: try: toSign = "12345678901234567890" # 20 bytes, SHA1 digest print "* Signing with object 0x%08X following data: %s" % (o.value(), toSign) signature = session.sign(o, toSign) s = ''.join(chr(c) for c in signature).encode('hex') sx = eval('0x%s' % s) print "Signature:" print hexdump(''.join(map(chr, signature)), 16) if m and e: print "Verifying using following public key:" print "Modulus:" print hexdump(''.join(map(chr, m)), 16) print "Exponent:" print hexdump(''.join(map(chr, e)), 16) decrypted = pow(sx, ex, mx) # RSA print "Decrypted:" d = hexx(decrypted).decode('hex') print hexdump(d, 16) if toSign == d[-20:]: print "*** signature VERIFIED!\n" else: print "*** signature NOT VERIFIED; decrypted value:" print hex(decrypted), "\n" else: print "Unable to verify signature: MODULUS/PUBLIC_EXP not found" except: print "Sign failed, exception:", str(sys.exc_info()[1]) if decrypt: if m and e: try: toEncrypt = "12345678901234567890" # note: PKCS1 BT2 padding should be random data, # but this is just a test and we use 0xFF... padded = "\x00\x02%s\x00%s" % ("\xFF" * (128 - (len(toEncrypt)) - 3), toEncrypt) print "* Decrypting with 0x%08X following data: %s" % (o.value(), toEncrypt) print "padded:\n", dump(padded, 16) encrypted = pow(eval('0x%sL' % padded.encode('hex')), ex, mx) # RSA encrypted1 = hexx(encrypted).decode('hex') print "encrypted:\n", dump(encrypted1, 16) decrypted = session.decrypt(o, encrypted1) decrypted1 = ''.join(chr(i) for i in decrypted) print "decrypted:\n", dump(decrypted1, 16) if decrypted1 == toEncrypt: print "decryption SUCCESSFULL!\n" else: print "decryption FAILED!\n" except: print "Decrypt failed, exception:", str(sys.exc_info()[1]) else: print "ERROR: Private key don't have MODULUS/PUBLIC_EXP" print "Dumping attributes:" for q, a in zip(all_attributes, attributes): if a == None: # undefined (CKR_ATTRIBUTE_TYPE_INVALID) attribute continue if q == PyKCS11.CKA_CLASS: print format_long % (PyKCS11.CKA[q], PyKCS11.CKO[a], a) elif q == PyKCS11.CKA_CERTIFICATE_TYPE: print format_long % (PyKCS11.CKA[q], PyKCS11.CKC[a], a) elif q == PyKCS11.CKA_KEY_TYPE: print format_long % (PyKCS11.CKA[q], PyKCS11.CKK[a], a) elif session.isBin(q): print format_binary % (PyKCS11.CKA[q], len(a)) if a: print dump(''.join(map(chr, a)), 16), elif q == PyKCS11.CKA_SERIAL_NUMBER: print format_binary % (PyKCS11.CKA[q], len(a)) if a: print hexdump(a, 16), else: print format_normal % (PyKCS11.CKA[q], a) 部分是我的IDE抱怨的部分有一个未解析的引用。因此,鉴于我收到了Unresolved引用错误,如何成功显式绑定局部变量?

答案 2 :(得分:0)

出于某种原因,Bruno提供的解决方案对我不起作用。这就是我所做的

import inspect

@pytest.fixture(scope='function')
def custom_fixture(request):
    sig = inspect.signature(request.function)

    my_fixture_obj = None

    if 'fixture_data' in sig.parameters:
        fixture_data = sig.parameters['fixture_data'].default

        my_fixture_obj = MyFixtureObject(fixture_data['data'])

    yield my_fixture_obj

    # cleanup my_fixture_obj


def test_sample1(custom_fixture, fixture_data = {'data': ['s1', 's2', 's3']}):
    ...

def test_sample2(custom_fixture, fixture_data = {'data': ['a1', 'a2', 'a3']}):
    ...