mirror of
https://github.com/pybind/pybind11.git
synced 2026-04-20 06:49:25 +00:00
Port tests to pytest
Use simple asserts and pytest's powerful introspection to make testing simpler. This merges the old .py/.ref file pairs into simple .py files where the expected values are right next to the code being tested. This commit does not touch the C++ part of the code and replicates the Python tests exactly like the old .ref-file-based approach.
This commit is contained in:
227
tests/test_virtual_functions.py
Normal file
227
tests/test_virtual_functions.py
Normal file
@@ -0,0 +1,227 @@
|
||||
import pytest
|
||||
from pybind11_tests import ConstructorStats
|
||||
|
||||
|
||||
def test_override(capture, msg):
|
||||
from pybind11_tests import (ExampleVirt, runExampleVirt, runExampleVirtVirtual,
|
||||
runExampleVirtBool)
|
||||
|
||||
class ExtendedExampleVirt(ExampleVirt):
|
||||
def __init__(self, state):
|
||||
super(ExtendedExampleVirt, self).__init__(state + 1)
|
||||
self.data = "Hello world"
|
||||
|
||||
def run(self, value):
|
||||
print('ExtendedExampleVirt::run(%i), calling parent..' % value)
|
||||
return super(ExtendedExampleVirt, self).run(value + 1)
|
||||
|
||||
def run_bool(self):
|
||||
print('ExtendedExampleVirt::run_bool()')
|
||||
return False
|
||||
|
||||
def pure_virtual(self):
|
||||
print('ExtendedExampleVirt::pure_virtual(): %s' % self.data)
|
||||
|
||||
ex12 = ExampleVirt(10)
|
||||
with capture:
|
||||
assert runExampleVirt(ex12, 20) == 30
|
||||
assert capture == "Original implementation of ExampleVirt::run(state=10, value=20)"
|
||||
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
runExampleVirtVirtual(ex12)
|
||||
assert msg(excinfo.value) == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
|
||||
|
||||
ex12p = ExtendedExampleVirt(10)
|
||||
with capture:
|
||||
assert runExampleVirt(ex12p, 20) == 32
|
||||
assert capture == """
|
||||
ExtendedExampleVirt::run(20), calling parent..
|
||||
Original implementation of ExampleVirt::run(state=11, value=21)
|
||||
"""
|
||||
with capture:
|
||||
assert runExampleVirtBool(ex12p) is False
|
||||
assert capture == "ExtendedExampleVirt::run_bool()"
|
||||
with capture:
|
||||
runExampleVirtVirtual(ex12p)
|
||||
assert capture == "ExtendedExampleVirt::pure_virtual(): Hello world"
|
||||
|
||||
cstats = ConstructorStats.get(ExampleVirt)
|
||||
assert cstats.alive() == 2
|
||||
del ex12, ex12p
|
||||
assert cstats.alive() == 0
|
||||
assert cstats.values() == ['10', '11']
|
||||
assert cstats.copy_constructions == 0
|
||||
assert cstats.move_constructions >= 0
|
||||
|
||||
|
||||
def test_inheriting_repeat(capture):
|
||||
from pybind11_tests import A_Repeat, B_Repeat, C_Repeat, D_Repeat, A_Tpl, B_Tpl, C_Tpl, D_Tpl
|
||||
|
||||
class VI_AR(A_Repeat):
|
||||
def unlucky_number(self):
|
||||
return 99
|
||||
|
||||
class VI_AT(A_Tpl):
|
||||
def unlucky_number(self):
|
||||
return 999
|
||||
|
||||
obj = VI_AR()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "hihihi"
|
||||
assert obj.unlucky_number() == 99
|
||||
|
||||
obj = VI_AT()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "hihihi"
|
||||
assert obj.unlucky_number() == 999
|
||||
|
||||
for obj in [B_Repeat(), B_Tpl()]:
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 13
|
||||
assert obj.lucky_number() == 7.0
|
||||
|
||||
for obj in [C_Repeat(), C_Tpl()]:
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 888.0
|
||||
|
||||
class VI_CR(C_Repeat):
|
||||
def lucky_number(self):
|
||||
return C_Repeat.lucky_number(self) + 1.25
|
||||
|
||||
obj = VI_CR()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 889.25
|
||||
|
||||
class VI_CT(C_Tpl):
|
||||
pass
|
||||
|
||||
obj = VI_CT()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 888.0
|
||||
|
||||
class VI_CCR(VI_CR):
|
||||
def lucky_number(self):
|
||||
return VI_CR.lucky_number(self) * 10
|
||||
|
||||
obj = VI_CCR()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 8892.5
|
||||
|
||||
class VI_CCT(VI_CT):
|
||||
def lucky_number(self):
|
||||
return VI_CT.lucky_number(self) * 1000
|
||||
|
||||
obj = VI_CCT()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 888000.0
|
||||
|
||||
class VI_DR(D_Repeat):
|
||||
def unlucky_number(self):
|
||||
return 123
|
||||
|
||||
def lucky_number(self):
|
||||
return 42.0
|
||||
|
||||
for obj in [D_Repeat(), D_Tpl()]:
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 4444
|
||||
assert obj.lucky_number() == 888.0
|
||||
|
||||
obj = VI_DR()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "B says hi 3 times"
|
||||
assert obj.unlucky_number() == 123
|
||||
assert obj.lucky_number() == 42.0
|
||||
|
||||
class VI_DT(D_Tpl):
|
||||
def say_something(self, times):
|
||||
print("VI_DT says:" + (' quack' * times))
|
||||
|
||||
def unlucky_number(self):
|
||||
return 1234
|
||||
|
||||
def lucky_number(self):
|
||||
return -4.25
|
||||
|
||||
obj = VI_DT()
|
||||
with capture:
|
||||
obj.say_something(3)
|
||||
assert capture == "VI_DT says: quack quack quack"
|
||||
assert obj.unlucky_number() == 1234
|
||||
assert obj.lucky_number() == -4.25
|
||||
|
||||
|
||||
def test_move_support(capture, msg):
|
||||
from pybind11_tests import NCVirt, NonCopyable, Movable
|
||||
|
||||
class NCVirtExt(NCVirt):
|
||||
def get_noncopyable(self, a, b):
|
||||
# Constructs and returns a new instance:
|
||||
nc = NonCopyable(a*a, b*b)
|
||||
return nc
|
||||
|
||||
def get_movable(self, a, b):
|
||||
# Return a referenced copy
|
||||
self.movable = Movable(a, b)
|
||||
return self.movable
|
||||
|
||||
class NCVirtExt2(NCVirt):
|
||||
def get_noncopyable(self, a, b):
|
||||
# Keep a reference: this is going to throw an exception
|
||||
self.nc = NonCopyable(a, b)
|
||||
return self.nc
|
||||
|
||||
def get_movable(self, a, b):
|
||||
# Return a new instance without storing it
|
||||
return Movable(a, b)
|
||||
|
||||
ncv1 = NCVirtExt()
|
||||
with capture:
|
||||
ncv1.print_nc(2, 3)
|
||||
assert capture == "36"
|
||||
with capture:
|
||||
ncv1.print_movable(4, 5)
|
||||
assert capture == "9"
|
||||
ncv2 = NCVirtExt2()
|
||||
with capture:
|
||||
ncv2.print_movable(7, 7)
|
||||
assert capture == "14"
|
||||
# Don't check the exception message here because it differs under debug/non-debug mode
|
||||
with pytest.raises(RuntimeError):
|
||||
ncv2.print_nc(9, 9)
|
||||
|
||||
nc_stats = ConstructorStats.get(NonCopyable)
|
||||
mv_stats = ConstructorStats.get(Movable)
|
||||
assert nc_stats.alive() == 1
|
||||
assert mv_stats.alive() == 1
|
||||
del ncv1, ncv2
|
||||
assert nc_stats.alive() == 0
|
||||
assert mv_stats.alive() == 0
|
||||
assert nc_stats.values() == ['4', '9', '9', '9']
|
||||
assert mv_stats.values() == ['4', '5', '7', '7']
|
||||
assert nc_stats.copy_constructions == 0
|
||||
assert mv_stats.copy_constructions == 1
|
||||
assert nc_stats.move_constructions >= 0
|
||||
assert mv_stats.move_constructions >= 0
|
||||
Reference in New Issue
Block a user