Commit a0c1ccf0 authored by Dean Moldovan's avatar Dean Moldovan
Browse files

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.
parent 192eb884
def test_vector_int():
from pybind11_tests import VectorInt
v_int = VectorInt([0, 0])
assert len(v_int) == 2
assert bool(v_int) is True
v_int2 = VectorInt([0, 0])
assert v_int == v_int2
v_int2[1] = 1
assert v_int != v_int2
v_int2.append(2)
v_int2.append(3)
v_int2.insert(0, 1)
v_int2.insert(0, 2)
v_int2.insert(0, 3)
assert str(v_int2) == "VectorInt[3, 2, 1, 0, 1, 2, 3]"
v_int.append(99)
v_int2[2:-2] = v_int
assert v_int2 == VectorInt([3, 2, 0, 0, 99, 2, 3])
del v_int2[1:3]
assert v_int2 == VectorInt([3, 0, 99, 2, 3])
del v_int2[0]
assert v_int2 == VectorInt([0, 99, 2, 3])
def test_vector_custom():
from pybind11_tests import El, VectorEl, VectorVectorEl
v_a = VectorEl()
v_a.append(El(1))
v_a.append(El(2))
assert str(v_a) == "VectorEl[El{1}, El{2}]"
vv_a = VectorVectorEl()
vv_a.append(v_a)
vv_b = vv_a[0]
assert str(vv_b) == "VectorEl[El{1}, El{2}]"
def test_vector_bool():
from pybind11_tests import VectorBool
vv_c = VectorBool()
for i in range(10):
vv_c.append(i % 2 == 0)
for i in range(10):
assert vv_c[i] == (i % 2 == 0)
assert str(vv_c) == "VectorBool[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]"
/*
example/example-virtual-functions.cpp -- overriding virtual functions from Python
tests/test_virtual_functions.cpp -- overriding virtual functions from Python
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
......@@ -7,8 +7,8 @@
BSD-style license that can be found in the LICENSE file.
*/
#include "example.h"
#include "constructor-stats.h"
#include "pybind11_tests.h"
#include "constructor_stats.h"
#include <pybind11/functional.h>
/* This is an example class that we'll want to be able to extend from Python */
......
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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment