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.
diff --git a/.appveyor.yml b/.appveyor.yml
index 12a51b8..688a92e 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -5,7 +5,6 @@
 - x86
 - x64
 environment:
-  CTEST_OUTPUT_ON_FAILURE: 1
   matrix:
   - CONDA: 27
   - CONDA: 35
@@ -16,12 +15,12 @@
       if ($env:PLATFORM -eq "x64") { $env:PYTHON = "$env:PYTHON-x64" }
       $env:PATH = "C:\Python$env:PYTHON\;C:\Python$env:PYTHON\Scripts\;$env:PATH"
       pip install --disable-pip-version-check --user --upgrade pip wheel
-      pip install numpy scipy
+      pip install pytest numpy scipy
     } elseif ($env:CONDA) {
       if ($env:CONDA -eq "27") { $env:CONDA = "" }
       if ($env:PLATFORM -eq "x64") { $env:CONDA = "$env:CONDA-x64" }
       $env:PATH = "C:\Miniconda$env:CONDA\;C:\Miniconda$env:CONDA\Scripts\;$env:PATH"
-      conda install -y -q numpy scipy
+      conda install -y -q pytest numpy scipy
     }
 - ps: |
     Start-FileDownload 'http://bitbucket.org/eigen/eigen/get/3.2.9.zip'
@@ -30,4 +29,4 @@
 build_script:
 - cmake -A "%CMAKE_ARCH%" -DPYBIND11_WERROR=ON
 - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
-- cmake --build . --config Release --target check -- /v:m /logger:%MSBuildLogger%
+- cmake --build . --config Release --target pytest -- /v:m /logger:%MSBuildLogger%
diff --git a/.gitignore b/.gitignore
index d1676c9..ab66758 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,10 +3,9 @@
 Makefile
 cmake_install.cmake
 .DS_Store
-/example/example*.so
-/example/example.cpython*.so
-/example/example.pyd
-/example/example*.dll
+*.so
+*.pyd
+*.dll
 *.sln
 *.sdf
 *.opensdf
@@ -32,3 +31,4 @@
 /dist
 /build
 /cmake/
+.cache/
diff --git a/.travis.yml b/.travis.yml
index abdb4bb..e74a250 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -98,12 +98,12 @@
 
   wget -q -O eigen.tar.gz https://bitbucket.org/eigen/eigen/get/3.2.9.tar.gz
   tar xzf eigen.tar.gz
-  export CMAKE_EXTRA_ARGS="${CMAKE_EXTRA_ARGS} -DCMAKE_INCLUDE_PATH=eigen-eigen-dc6cfdf9bcec"
+  export CMAKE_EXTRA_ARGS="${CMAKE_EXTRA_ARGS} -DCMAKE_INCLUDE_PATH=$PWD/eigen-eigen-dc6cfdf9bcec"
 script:
 - $SCRIPT_RUN_PREFIX cmake ${CMAKE_EXTRA_ARGS}
     -DPYBIND11_PYTHON_VERSION=$PYTHON
     -DPYBIND11_CPP_STANDARD=-std=c++$CPP
     -DPYBIND11_WERROR=ON
-- $SCRIPT_RUN_PREFIX make CTEST_OUTPUT_ON_FAILURE=TRUE check -j 2
+- $SCRIPT_RUN_PREFIX make pytest -j 2
 after_script:
 - if [ -n "$DOCKER" ]; then docker stop "$containerid"; docker rm "$containerid"; fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 450f651..cd2c4cb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,4 @@
-# CMakeLists.txt -- Build system for the pybind11 examples
+# CMakeLists.txt -- Build system for the pybind11 modules
 #
 # Copyright (c) 2015 Wenzel Jakob <wenzel@inf.ethz.ch>
 #
@@ -20,7 +20,7 @@
 option(PYBIND11_WERROR  "Report all warnings as errors"  OFF)
 
 # Add a CMake parameter for choosing a desired Python version
-set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling the example application")
+set(PYBIND11_PYTHON_VERSION "" CACHE STRING "Python version to use for compiling modules")
 
 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/tools")
 set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7)
@@ -146,17 +146,15 @@
 
   if(PYBIND11_WERROR)
     if(MSVC)
-        target_compile_options(${target_name} PRIVATE /WX)
+      target_compile_options(${target_name} PRIVATE /WX)
     else()
-        target_compile_options(${target_name} PRIVATE -Werror)
+      target_compile_options(${target_name} PRIVATE -Werror)
     endif()
   endif()
 endfunction()
 
 if (PYBIND11_TEST)
-  enable_testing()
-  add_subdirectory(example)
-  add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> DEPENDS example)
+  add_subdirectory(tests)
 endif()
 
 if (PYBIND11_INSTALL)
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
deleted file mode 100644
index 2cc8f83..0000000
--- a/example/CMakeLists.txt
+++ /dev/null
@@ -1,68 +0,0 @@
-# Set a default build configuration if none is specified. 'MinSizeRel' produces the smallest binaries
-if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
-  message(STATUS "Setting build type to 'MinSizeRel' as none was specified.")
-  set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
-  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
-    "MinSizeRel" "RelWithDebInfo")
-endif()
-
-set(PYBIND11_EXAMPLES
-  example-methods-and-attributes.cpp
-  example-python-types.cpp
-  example-operator-overloading.cpp
-  example-constants-and-functions.cpp
-  example-callbacks.cpp
-  example-sequences-and-iterators.cpp
-  example-buffers.cpp
-  example-smart-ptr.cpp
-  example-modules.cpp
-  example-numpy-vectorize.cpp
-  example-arg-keywords-and-defaults.cpp
-  example-virtual-functions.cpp
-  example-keep-alive.cpp
-  example-opaque-types.cpp
-  example-pickling.cpp
-  example-inheritance.cpp
-  example-stl-binder-vector.cpp
-  example-eval.cpp
-  example-custom-exceptions.cpp
-  example-numpy-dtypes.cpp
-  issues.cpp
-)
-
-# Check if Eigen is available
-find_package(Eigen3 QUIET)
-
-if(EIGEN3_FOUND)
-  list(APPEND PYBIND11_EXAMPLES eigen.cpp)
-  message(STATUS "Building Eigen v${EIGEN3_VERSION} testcase")
-else()
-  message(STATUS "NOT Building Eigen testcase")
-endif()
-
-# Create the binding library
-pybind11_add_module(example example.cpp ${PYBIND11_EXAMPLES})
-pybind11_enable_warnings(example)
-
-if(EIGEN3_FOUND)
-  target_include_directories(example PRIVATE ${EIGEN3_INCLUDE_DIR})
-  target_compile_definitions(example PRIVATE -DPYBIND11_TEST_EIGEN)
-endif()
-
-# Always write the output file directly into the 'example' directory (even on MSVC)
-set(CompilerFlags
-  LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_RELEASE LIBRARY_OUTPUT_DIRECTORY_DEBUG
-  LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO
-  RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_RELEASE RUNTIME_OUTPUT_DIRECTORY_DEBUG
-  RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO)
-
-foreach(CompilerFlag ${CompilerFlags})
-  set_target_properties(example PROPERTIES ${CompilerFlag} ${PROJECT_SOURCE_DIR}/example)
-endforeach()
-
-set(RUN_TEST ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/run_test.py)
-
-foreach(VALUE ${PYBIND11_EXAMPLES})
-  string(REGEX REPLACE "^(.+).cpp$" "\\1" EXAMPLE_NAME "${VALUE}")
-  add_test(NAME ${EXAMPLE_NAME} COMMAND ${RUN_TEST} ${EXAMPLE_NAME})
-endforeach()
diff --git a/example/eigen.py b/example/eigen.py
deleted file mode 100644
index 18c8a45..0000000
--- a/example/eigen.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import fixed_r, fixed_c
-from example import fixed_passthrough_r, fixed_passthrough_c
-from example import dense_r, dense_c
-from example import dense_passthrough_r, dense_passthrough_c
-from example import sparse_r, sparse_c
-from example import sparse_passthrough_r, sparse_passthrough_c
-from example import double_row, double_col
-from example import double_mat_cm, double_mat_rm
-from example import cholesky1, cholesky2, cholesky3, cholesky4, cholesky5, cholesky6
-from example import diagonal, diagonal_1, diagonal_n
-from example import block
-from example import incr_diag, symmetric_upper, symmetric_lower
-try:
-    import numpy as np
-    import scipy
-except ImportError:
-    # NumPy missing: skip test
-    exit(99)
-
-ref = np.array(
-    [[0, 3, 0, 0, 0, 11],
-     [22, 0, 0, 0, 17, 11],
-     [7, 5, 0, 1, 0, 11],
-     [0, 0, 0, 0, 0, 11],
-     [0, 0, 14, 0, 8, 11]])
-
-
-def check(mat):
-    return 'OK' if np.sum(abs(mat - ref)) == 0 else 'NOT OK'
-
-print("should_give_NOT_OK = %s" % check(ref[:, ::-1]))
-
-print("fixed_r = %s" % check(fixed_r()))
-print("fixed_c = %s" % check(fixed_c()))
-print("pt_r(fixed_r) = %s" % check(fixed_passthrough_r(fixed_r())))
-print("pt_c(fixed_c) = %s" % check(fixed_passthrough_c(fixed_c())))
-print("pt_r(fixed_c) = %s" % check(fixed_passthrough_r(fixed_c())))
-print("pt_c(fixed_r) = %s" % check(fixed_passthrough_c(fixed_r())))
-
-print("dense_r = %s" % check(dense_r()))
-print("dense_c = %s" % check(dense_c()))
-print("pt_r(dense_r) = %s" % check(dense_passthrough_r(dense_r())))
-print("pt_c(dense_c) = %s" % check(dense_passthrough_c(dense_c())))
-print("pt_r(dense_c) = %s" % check(dense_passthrough_r(dense_c())))
-print("pt_c(dense_r) = %s" % check(dense_passthrough_c(dense_r())))
-
-print("sparse_r = %s" % check(sparse_r()))
-print("sparse_c = %s" % check(sparse_c()))
-print("pt_r(sparse_r) = %s" % check(sparse_passthrough_r(sparse_r())))
-print("pt_c(sparse_c) = %s" % check(sparse_passthrough_c(sparse_c())))
-print("pt_r(sparse_c) = %s" % check(sparse_passthrough_r(sparse_c())))
-print("pt_c(sparse_r) = %s" % check(sparse_passthrough_c(sparse_r())))
-
-def check_got_vs_ref(got_x, ref_x):
-    return 'OK' if np.array_equal(got_x, ref_x) else 'NOT OK'
-
-counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
-first_row = counting_mat[0, :]
-first_col = counting_mat[:, 0]
-
-print("double_row(first_row) = %s" % check_got_vs_ref(double_row(first_row), 2.0 * first_row))
-print("double_col(first_row) = %s" % check_got_vs_ref(double_col(first_row), 2.0 * first_row))
-print("double_row(first_col) = %s" % check_got_vs_ref(double_row(first_col), 2.0 * first_col))
-print("double_col(first_col) = %s" % check_got_vs_ref(double_col(first_col), 2.0 * first_col))
-
-counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
-slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
-
-for slice_idx, ref_mat in enumerate(slices):
-    print("double_mat_cm(%d) = %s" % (slice_idx, check_got_vs_ref(double_mat_cm(ref_mat), 2.0 * ref_mat)))
-    print("double_mat_rm(%d) = %s" % (slice_idx, check_got_vs_ref(double_mat_rm(ref_mat), 2.0 * ref_mat)))
-
-i = 1
-for chol in [cholesky1, cholesky2, cholesky3, cholesky4, cholesky5, cholesky6]:
-    mymat = chol(np.array([[1,2,4], [2,13,23], [4,23,77]]))
-    print("cholesky" + str(i) + " " + ("OK" if (mymat == np.array([[1,0,0], [2,3,0], [4,5,6]])).all() else "NOT OKAY"))
-    i += 1
-
-print("diagonal() %s" % ("OK" if (diagonal(ref) == ref.diagonal()).all() else "FAILED"))
-print("diagonal_1() %s" % ("OK" if (diagonal_1(ref) == ref.diagonal(1)).all() else "FAILED"))
-for i in range(-5, 7):
-    print("diagonal_n(%d) %s" % (i, "OK" if (diagonal_n(ref, i) == ref.diagonal(i)).all() else "FAILED"))
-
-print("block(2,1,3,3) %s" % ("OK" if (block(ref, 2, 1, 3, 3) == ref[2:5, 1:4]).all() else "FAILED"))
-print("block(1,4,4,2) %s" % ("OK" if (block(ref, 1, 4, 4, 2) == ref[1:, 4:]).all() else "FAILED"))
-print("block(1,4,3,2) %s" % ("OK" if (block(ref, 1, 4, 3, 2) == ref[1:4, 4:]).all() else "FAILED"))
-
-print("incr_diag %s" % ("OK" if (incr_diag(7) == np.diag([1,2,3,4,5,6,7])).all() else "FAILED"))
-
-asymm = np.array([
-    [1,  2, 3, 4],
-    [5,  6, 7, 8],
-    [9, 10,11,12],
-    [13,14,15,16]])
-symm_lower = np.array(asymm)
-symm_upper = np.array(asymm)
-for i in range(4):
-    for j in range(i+1, 4):
-        symm_lower[i,j] = symm_lower[j,i]
-        symm_upper[j,i] = symm_upper[i,j]
-
-print("symmetric_lower %s" % ("OK" if (symmetric_lower(asymm) == symm_lower).all() else "FAILED"))
-print("symmetric_upper %s" % ("OK" if (symmetric_upper(asymm) == symm_upper).all() else "FAILED"))
-
-print(double_col.__doc__)
-print(double_row.__doc__)
-print(double_mat_rm.__doc__)
-print(sparse_passthrough_r.__doc__)
-print(sparse_passthrough_c.__doc__)
diff --git a/example/eigen.ref b/example/eigen.ref
deleted file mode 100644
index 626c604..0000000
--- a/example/eigen.ref
+++ /dev/null
@@ -1,60 +0,0 @@
-should_give_NOT_OK = NOT OK
-fixed_r = OK
-fixed_c = OK
-pt_r(fixed_r) = OK
-pt_c(fixed_c) = OK
-pt_r(fixed_c) = OK
-pt_c(fixed_r) = OK
-dense_r = OK
-dense_c = OK
-pt_r(dense_r) = OK
-pt_c(dense_c) = OK
-pt_r(dense_c) = OK
-pt_c(dense_r) = OK
-sparse_r = OK
-sparse_c = OK
-pt_r(sparse_r) = OK
-pt_c(sparse_c) = OK
-pt_r(sparse_c) = OK
-pt_c(sparse_r) = OK
-double_row(first_row) = OK
-double_col(first_row) = OK
-double_row(first_col) = OK
-double_col(first_col) = OK
-double_mat_cm(0) = OK
-double_mat_rm(0) = OK
-double_mat_cm(1) = OK
-double_mat_rm(1) = OK
-double_mat_cm(2) = OK
-double_mat_rm(2) = OK
-cholesky1 OK
-cholesky2 OK
-cholesky3 OK
-cholesky4 OK
-cholesky5 OK
-cholesky6 OK
-diagonal() OK
-diagonal_1() OK
-diagonal_n(-5) OK
-diagonal_n(-4) OK
-diagonal_n(-3) OK
-diagonal_n(-2) OK
-diagonal_n(-1) OK
-diagonal_n(0) OK
-diagonal_n(1) OK
-diagonal_n(2) OK
-diagonal_n(3) OK
-diagonal_n(4) OK
-diagonal_n(5) OK
-diagonal_n(6) OK
-block(2,1,3,3) OK
-block(1,4,4,2) OK
-block(1,4,3,2) OK
-incr_diag OK
-symmetric_lower OK
-symmetric_upper OK
-double_col(arg0: numpy.ndarray[float32[m, 1]]) -> numpy.ndarray[float32[m, 1]]
-double_row(arg0: numpy.ndarray[float32[1, n]]) -> numpy.ndarray[float32[1, n]]
-double_mat_rm(arg0: numpy.ndarray[float32[m, n]]) -> numpy.ndarray[float32[m, n]]
-sparse_passthrough_r(arg0: scipy.sparse.csr_matrix[float32]) -> scipy.sparse.csr_matrix[float32]
-sparse_passthrough_c(arg0: scipy.sparse.csc_matrix[float32]) -> scipy.sparse.csc_matrix[float32]
diff --git a/example/example-arg-keywords-and-defaults.py b/example/example-arg-keywords-and-defaults.py
deleted file mode 100755
index 2536782..0000000
--- a/example/example-arg-keywords-and-defaults.py
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-import pydoc
-
-sys.path.append('.')
-
-from example import kw_func0, kw_func1, kw_func2, kw_func3, kw_func4, call_kw_func
-from example import args_function, args_kwargs_function, kw_func_udl, kw_func_udl_z
-from example import KWClass
-
-print(pydoc.render_doc(kw_func0, "Help on %s"))
-print(pydoc.render_doc(kw_func1, "Help on %s"))
-print(pydoc.render_doc(kw_func2, "Help on %s"))
-print(pydoc.render_doc(kw_func3, "Help on %s"))
-print(pydoc.render_doc(kw_func4, "Help on %s"))
-print(pydoc.render_doc(kw_func_udl, "Help on %s"))
-print(pydoc.render_doc(kw_func_udl_z, "Help on %s"))
-print(pydoc.render_doc(args_function, "Help on %s"))
-print(pydoc.render_doc(args_kwargs_function, "Help on %s"))
-
-print(KWClass.foo0.__doc__)
-print(KWClass.foo1.__doc__)
-
-kw_func1(5, 10)
-kw_func1(5, y=10)
-kw_func1(y=10, x=5)
-
-kw_func2()
-
-kw_func2(5)
-kw_func2(x=5)
-
-kw_func2(y=10)
-
-kw_func2(5, 10)
-kw_func2(x=5, y=10)
-
-try:
-    kw_func2(x=5, y=10, z=12)
-except Exception as e:
-    print("Caught expected exception: " + str(e))
-
-kw_func4()
-kw_func4(myList=[1, 2, 3])
-
-call_kw_func(kw_func2)
-
-args_function('arg1_value', 'arg2_value', 3)
-args_kwargs_function('arg1_value', 'arg2_value', arg3='arg3_value', arg4=4)
-
-kw_func_udl(x=5, y=10)
-kw_func_udl_z(x=5)
diff --git a/example/example-arg-keywords-and-defaults.ref b/example/example-arg-keywords-and-defaults.ref
deleted file mode 100644
index d3ca997..0000000
--- a/example/example-arg-keywords-and-defaults.ref
+++ /dev/null
@@ -1,75 +0,0 @@
-Help on built-in function kw_func0 in module example
-
-kkww__ffuunncc00(...)
-    kw_func0(arg0: int, arg1: int) -> None
-
-Help on built-in function kw_func1 in module example
-
-kkww__ffuunncc11(...)
-    kw_func1(x: int, y: int) -> None
-
-Help on built-in function kw_func2 in module example
-
-kkww__ffuunncc22(...)
-    kw_func2(x: int=100L, y: int=200L) -> None
-
-Help on built-in function kw_func3 in module example
-
-kkww__ffuunncc33(...)
-    kw_func3(data: unicode=u'Hello world!') -> None
-
-Help on built-in function kw_func4 in module example
-
-kkww__ffuunncc44(...)
-    kw_func4(myList: List[int]=[13L, 17L]) -> None
-
-Help on built-in function kw_func_udl in module example
-
-kkww__ffuunncc__uuddll(...)
-    kw_func_udl(x: int, y: int=300L) -> None
-
-Help on built-in function kw_func_udl_z in module example
-
-kkww__ffuunncc__uuddll__zz(...)
-    kw_func_udl_z(x: int, y: int=0L) -> None
-
-Help on built-in function args_function in module example
-
-aarrggss__ffuunnccttiioonn(...)
-    args_function(*args) -> None
-
-Help on built-in function args_kwargs_function in module example
-
-aarrggss__kkwwaarrggss__ffuunnccttiioonn(...)
-    args_kwargs_function(*args, **kwargs) -> None
-
-
-foo0(self: KWClass, arg0: int, arg1: float) -> None
-foo1(self: KWClass, x: int, y: float) -> None
-
-
-kw_func(x=5, y=10)
-kw_func(x=5, y=10)
-kw_func(x=5, y=10)
-kw_func(x=100, y=200)
-kw_func(x=5, y=200)
-kw_func(x=5, y=200)
-kw_func(x=100, y=10)
-kw_func(x=5, y=10)
-kw_func(x=5, y=10)
-Caught expected exception: Incompatible function arguments. The following argument types are supported:
-    1. (x: int=100L, y: int=200L) -> None
-    Invoked with:
-kw_func4: 13 17
-kw_func4: 1 2 3
-kw_func(x=1234, y=5678)
-got argument: arg1_value
-got argument: arg2_value
-got argument: 3
-got argument: arg1_value
-got argument: arg2_value
-got keyword argument: arg3 -> arg3_value
-got keyword argument: arg4 -> 4
-
-kw_func(x=5, y=10)
-kw_func(x=5, y=0)
diff --git a/example/example-buffers.py b/example/example-buffers.py
deleted file mode 100755
index 185e6d3..0000000
--- a/example/example-buffers.py
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import Matrix
-
-try:
-    import numpy as np
-except ImportError:
-    # NumPy missing: skip test
-    exit(99)
-
-m = Matrix(5, 5)
-
-print(m[2, 3])
-m[2, 3] = 4
-print(m[2, 3])
-
-m2 = np.array(m, copy=False)
-print(m2)
-print(m2[2, 3])
-m2[2, 3] = 5
-print(m[2, 3])
-
-m3 = np.array([[1,2,3],[4,5,6]]).astype(np.float32)
-print(m3)
-m4 = Matrix(m3)
-for i in range(m4.rows()):
-    for j in range(m4.cols()):
-        print(m4[i, j], end = ' ')
-    print()
-
-from example import ConstructorStats
-cstats = ConstructorStats.get(Matrix)
-print("Instances not destroyed:", cstats.alive())
-m = m4 = None
-print("Instances not destroyed:", cstats.alive())
-m2 = None # m2 holds an m reference
-print("Instances not destroyed:", cstats.alive())
-print("Constructor values:", cstats.values())
-print("Copy constructions:", cstats.copy_constructions)
-#print("Move constructions:", cstats.move_constructions >= 0) # Don't invoke any
-print("Copy assignments:", cstats.copy_assignments)
-print("Move assignments:", cstats.move_assignments)
diff --git a/example/example-buffers.ref b/example/example-buffers.ref
deleted file mode 100644
index 1e02ffd..0000000
--- a/example/example-buffers.ref
+++ /dev/null
@@ -1,24 +0,0 @@
-### Matrix @ 0x1df1920 created 5x5 matrix
-0.0
-4.0
-[[ 0.  0.  0.  0.  0.]
- [ 0.  0.  0.  0.  0.]
- [ 0.  0.  0.  4.  0.]
- [ 0.  0.  0.  0.  0.]
- [ 0.  0.  0.  0.  0.]]
-4.0
-5.0
-[[ 1.  2.  3.]
- [ 4.  5.  6.]]
-### Matrix @ 0x1fa8cf0 created 2x3 matrix
-1.0 2.0 3.0 
-4.0 5.0 6.0 
-Instances not destroyed: 2
-### Matrix @ 0x1fa8cf0 destroyed 2x3 matrix
-Instances not destroyed: 1
-### Matrix @ 0x1df1920 destroyed 5x5 matrix
-Instances not destroyed: 0
-Constructor values: ['5x5 matrix', '2x3 matrix']
-Copy constructions: 0
-Copy assignments: 0
-Move assignments: 0
diff --git a/example/example-callbacks.py b/example/example-callbacks.py
deleted file mode 100755
index 68a485a..0000000
--- a/example/example-callbacks.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-from functools import partial
-import sys
-sys.path.append('.')
-
-from example import Pet
-from example import Dog
-from example import Rabbit
-from example import dog_bark
-from example import pet_print
-
-polly = Pet('Polly', 'parrot')
-molly = Dog('Molly')
-roger = Rabbit('Rabbit')
-print(roger.name() + " is a " + roger.species())
-pet_print(roger)
-print(polly.name() + " is a " + polly.species())
-pet_print(polly)
-print(molly.name() + " is a " + molly.species())
-pet_print(molly)
-dog_bark(molly)
-try:
-    dog_bark(polly)
-except Exception as e:
-    print('The following error is expected: ' + str(e))
-
-from example import test_callback1
-from example import test_callback2
-from example import test_callback3
-from example import test_callback4
-from example import test_callback5
-from example import test_cleanup
-
-def func1():
-    print('Callback function 1 called!')
-
-def func2(a, b, c, d):
-    print('Callback function 2 called : ' + str(a) + ", " + str(b) + ", " + str(c) + ", "+ str(d))
-    return d
-
-def func3(a):
-    print('Callback function 3 called : ' + str(a))
-
-print(test_callback1(func1))
-print(test_callback2(func2))
-print(test_callback1(partial(func2, "Hello", "from", "partial", "object")))
-print(test_callback1(partial(func3, "Partial object with one argument")))
-
-test_callback3(lambda i: i + 1)
-f = test_callback4()
-print("func(43) = %i" % f(43))
-f = test_callback5()
-print("func(number=43) = %i" % f(number=43))
-
-test_cleanup()
-
-from example import payload_cstats
-cstats = payload_cstats()
-print("Payload instances not destroyed:", cstats.alive())
-print("Copy constructions:", cstats.copy_constructions)
-print("Move constructions:", cstats.move_constructions >= 1)
-
-from example import dummy_function
-from example import dummy_function2
-from example import test_dummy_function
-from example import roundtrip
-
-test_dummy_function(dummy_function)
-test_dummy_function(roundtrip(dummy_function))
-if roundtrip(None) is not None:
-    print("Problem!")
-test_dummy_function(lambda x: x + 2)
-
-try:
-    test_dummy_function(dummy_function2)
-    print("Problem!")
-except Exception as e:
-    if 'Incompatible function arguments' in str(e):
-        print("All OK!")
-    else:
-        print("Problem!")
-
-try:
-    test_dummy_function(lambda x, y: x + y)
-    print("Problem!")
-except Exception as e:
-    if 'missing 1 required positional argument' in str(e) or \
-       'takes exactly 2 arguments' in str(e):
-        print("All OK!")
-    else:
-        print("Problem!")
-
-print(test_callback3.__doc__)
-print(test_callback4.__doc__)
diff --git a/example/example-callbacks.ref b/example/example-callbacks.ref
deleted file mode 100644
index c6f8f53..0000000
--- a/example/example-callbacks.ref
+++ /dev/null
@@ -1,46 +0,0 @@
-Rabbit is a parrot
-Rabbit is a parrot
-Polly is a parrot
-Polly is a parrot
-Molly is a dog
-Molly is a dog
-Woof!
-The following error is expected: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: example.Dog) -> None
-    Invoked with: <example.Pet object at 0x7ffaf4b00db0>
-Callback function 1 called!
-False
-Callback function 2 called : Hello, x, True, 5
-5
-Callback function 2 called : Hello, from, partial, object
-False
-Callback function 3 called : Partial object with one argument
-False
-func(43) = 44
-func(43) = 44
-func(number=43) = 44
-### Payload @ 0x7ffdcee09c80 created via default constructor
-### Payload @ 0x7ffdcee09c88 created via copy constructor
-### Payload @ 0xb54500 created via move constructor
-### Payload @ 0x7ffdcee09c88 destroyed
-### Payload @ 0x7ffdcee09c80 destroyed
-### Payload @ 0xb54500 destroyed
-Payload instances not destroyed: 0
-Copy constructions: 1
-Move constructions: True
-argument matches dummy_function
-eval(1) = 2
-roundtrip (got None)..
-roundtrip..
-argument matches dummy_function
-eval(1) = 2
-could not convert to a function pointer.
-eval(1) = 3
-could not convert to a function pointer.
-All OK!
-could not convert to a function pointer.
-All OK!
-test_callback3(arg0: Callable[[int], int]) -> None
-
-test_callback4() -> Callable[[int], int]
-
diff --git a/example/example-constants-and-functions.py b/example/example-constants-and-functions.py
deleted file mode 100755
index 852902f..0000000
--- a/example/example-constants-and-functions.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import test_function
-from example import some_constant
-from example import EMyEnumeration
-from example import ECMyEnum, test_ecenum
-from example import EFirstEntry
-from example import ExampleWithEnum
-from example import return_bytes
-from example import print_bytes
-
-print(EMyEnumeration)
-print(EMyEnumeration.EFirstEntry)
-print(EMyEnumeration.ESecondEntry)
-print(EFirstEntry)
-
-print(test_function())
-print(test_function(7))
-print(test_function(EMyEnumeration.EFirstEntry))
-print(test_function(EMyEnumeration.ESecondEntry))
-test_ecenum(ECMyEnum.Three)
-z = ECMyEnum.Two
-test_ecenum(z)
-try:
-    z == 2
-    print("Bad: expected a TypeError exception")
-except TypeError:
-    try:
-        z != 3
-        print("Bad: expected a TypeError exception")
-    except TypeError:
-        print("Good: caught expected TypeError exceptions for scoped enum ==/!= int comparisons")
-
-y = EMyEnumeration.ESecondEntry
-try:
-    y == 2
-    y != 2
-    print("Good: no TypeError exception for unscoped enum ==/!= int comparisions")
-except TypeError:
-    print("Bad: caught TypeError exception for unscoped enum ==/!= int comparisons")
-
-print("enum->integer = %i" % int(EMyEnumeration.ESecondEntry))
-print("integer->enum = %s" % str(EMyEnumeration(2)))
-
-print("A constant = " + str(some_constant))
-
-print(ExampleWithEnum.EMode)
-print(ExampleWithEnum.EMode.EFirstMode)
-print(ExampleWithEnum.EFirstMode)
-ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode)
-
-print("Equality test 1: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode)))
-
-print("Inequality test 1: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode)))
-
-print("Equality test 2: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
-    ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode)))
-
-print("Inequality test 2: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
-    ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode)))
-
-print("Equality test 3: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
-    int(ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode))))
-
-print("Inequality test 3: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
-    int(ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode))))
-
-print("Equality test 4: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) ==
-    int(ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode))))
-
-print("Inequality test 4: " + str(
-    ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode) !=
-    int(ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode))))
-
-x = {
-        ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode): 1,
-        ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode): 2
-}
-
-x[ExampleWithEnum.test_function(ExampleWithEnum.EFirstMode)] = 3
-x[ExampleWithEnum.test_function(ExampleWithEnum.ESecondMode)] = 4
-print("Hashing test = " + str(x))
-
-print_bytes(return_bytes())
diff --git a/example/example-constants-and-functions.ref b/example/example-constants-and-functions.ref
deleted file mode 100644
index 4805631..0000000
--- a/example/example-constants-and-functions.ref
+++ /dev/null
@@ -1,56 +0,0 @@
-<class 'example.EMyEnumeration'>
-EMyEnumeration.EFirstEntry
-EMyEnumeration.ESecondEntry
-EMyEnumeration.EFirstEntry
-test_function()
-False
-test_function(7)
-3.5
-test_function(enum=1)
-None
-test_function(enum=2)
-None
-test_ecenum(ECMyEnum::Three)
-test_ecenum(ECMyEnum::Two)
-Good: caught expected TypeError exceptions for scoped enum ==/!= int comparisons
-Good: no TypeError exception for unscoped enum ==/!= int comparisions
-enum->integer = 2
-integer->enum = EMyEnumeration.ESecondEntry
-A constant = 14
-<class 'example.EMode'>
-EMode.EFirstMode
-EMode.EFirstMode
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=1)
-Equality test 1: True
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=1)
-Inequality test 1: False
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-Equality test 2: False
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-Inequality test 2: True
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=1)
-Equality test 3: True
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=1)
-Inequality test 3: False
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-Equality test 4: False
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-Inequality test 4: True
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-ExampleWithEnum::test_function(enum=1)
-ExampleWithEnum::test_function(enum=2)
-Hashing test = {EMode.EFirstMode: 3, EMode.ESecondMode: 4}
-bytes[0]=1
-bytes[1]=0
-bytes[2]=2
-bytes[3]=0
diff --git a/example/example-custom-exceptions.py b/example/example-custom-exceptions.py
deleted file mode 100644
index d4ee5f8..0000000
--- a/example/example-custom-exceptions.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-import example
-
-print("Can we catch a MyException?")
-try:
-    example.throws1()
-except example.MyException as e:
-    print(e.__class__.__name__, ":", e)
-print("")
-
-print("Can we translate to standard Python exceptions?")
-try:
-    example.throws2()
-except Exception as e:
-    print(e.__class__.__name__, ":", e)
-print("")
-
-print("Can we handle unknown exceptions?")
-try:
-    example.throws3()
-except Exception as e:
-    print(e.__class__.__name__, ":", e)
-print("")
-
-print("Can we delegate to another handler by rethrowing?")
-try:
-    example.throws4()
-except example.MyException as e:
-    print(e.__class__.__name__, ":", e)
-print("")
-
-print("Can we fall-through to the default handler?")
-try:
-    example.throws_logic_error()
-except Exception as e:
-    print(e.__class__.__name__, ":", e)
-print("")
-
diff --git a/example/example-custom-exceptions.ref b/example/example-custom-exceptions.ref
deleted file mode 100644
index a048923..0000000
--- a/example/example-custom-exceptions.ref
+++ /dev/null
@@ -1,15 +0,0 @@
-Can we catch a MyException?
-MyException : this error should go to a custom type
-
-Can we translate to standard Python exceptions?
-RuntimeError : this error should go to a standard Python exception
-
-Can we handle unknown exceptions?
-RuntimeError : Caught an unknown exception!
-
-Can we delegate to another handler by rethrowing?
-MyException : this error is rethrown
-
-Can we fall-through to the default handler?
-RuntimeError : this error should fall through to the standard handler
-
diff --git a/example/example-eval.py b/example/example-eval.py
deleted file mode 100644
index eec10c3..0000000
--- a/example/example-eval.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from example import example_eval
-
-example_eval()
-
-
diff --git a/example/example-eval.ref b/example/example-eval.ref
deleted file mode 100644
index db350bd..0000000
--- a/example/example-eval.ref
+++ /dev/null
@@ -1,13 +0,0 @@
-eval_statements test
-eval_statements passed
-eval test
-eval passed
-eval_single_statement test
-eval_single_statement passed
-eval_file test
-eval_file passed
-eval failure test
-eval failure test passed
-eval_file failure test
-eval_file failure test passed
-Hello World!
diff --git a/example/example-eval_call.py b/example/example-eval_call.py
deleted file mode 100644
index db96fd3..0000000
--- a/example/example-eval_call.py
+++ /dev/null
@@ -1 +0,0 @@
-call_test2(y)
\ No newline at end of file
diff --git a/example/example-inheritance.py b/example/example-inheritance.py
deleted file mode 100644
index b4bcb65..0000000
--- a/example/example-inheritance.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import print_function
-import sys
-
-sys.path.append('.')
-
-from example import return_class_1
-from example import return_class_2
-from example import return_none
-
-print(type(return_class_1()).__name__)
-print(type(return_class_2()).__name__)
-print(type(return_none()).__name__)
diff --git a/example/example-inheritance.ref b/example/example-inheritance.ref
deleted file mode 100644
index 9600336..0000000
--- a/example/example-inheritance.ref
+++ /dev/null
@@ -1,3 +0,0 @@
-DerivedClass1
-DerivedClass2
-NoneType
diff --git a/example/example-keep-alive.py b/example/example-keep-alive.py
deleted file mode 100644
index 187ad53..0000000
--- a/example/example-keep-alive.py
+++ /dev/null
@@ -1,67 +0,0 @@
-from __future__ import print_function
-import sys
-import gc
-sys.path.append('.')
-
-from example import Parent, Child
-
-if True:
-    p = Parent()
-    p.addChild(Child())
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-
-if True:
-    p = Parent()
-    p.returnChild()
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-
-if True:
-    p = Parent()
-    p.addChildKeepAlive(Child())
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-
-if True:
-    p = Parent()
-    p.returnChildKeepAlive()
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-
-if True:
-    p = Parent()
-    p.returnNullChildKeepAliveChild()
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-
-if True:
-    p = Parent()
-    p.returnNullChildKeepAliveParent()
-    gc.collect()
-    print(p)
-    p = None
-
-gc.collect()
-print("")
-print("Terminating..")
diff --git a/example/example-keep-alive.ref b/example/example-keep-alive.ref
deleted file mode 100644
index 775aff4..0000000
--- a/example/example-keep-alive.ref
+++ /dev/null
@@ -1,33 +0,0 @@
-Allocating parent.
-Allocating child.
-Releasing child.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-
-Allocating parent.
-Allocating child.
-Releasing child.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-
-Allocating parent.
-Allocating child.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-Releasing child.
-
-Allocating parent.
-Allocating child.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-Releasing child.
-
-Allocating parent.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-
-Allocating parent.
-<example.Parent object at 0x10eb726c0>
-Releasing parent.
-
-Terminating..
diff --git a/example/example-methods-and-attributes.py b/example/example-methods-and-attributes.py
deleted file mode 100755
index 8f2a524..0000000
--- a/example/example-methods-and-attributes.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import ExampleMandA
-
-instance1 = ExampleMandA()
-instance2 = ExampleMandA(32)
-instance1.add1(instance2)
-instance1.add2(instance2)
-instance1.add3(instance2)
-instance1.add4(instance2)
-instance1.add5(instance2)
-instance1.add6(32)
-instance1.add7(32)
-instance1.add8(32)
-instance1.add9(32)
-instance1.add10(32)
-
-print("Instance 1: " + str(instance1))
-print("Instance 2: " + str(instance2))
-
-print(instance1.self1())
-print(instance1.self2())
-print(instance1.self3())
-print(instance1.self4())
-print(instance1.self5())
-print(instance1.internal1())
-print(instance1.internal2())
-print(instance1.internal3())
-print(instance1.internal4())
-print(instance1.internal5())
-
-print("Instance 1, direct access = %i" % instance1.value)
-instance1.value = 100
-print("Instance 1: " + str(instance1))
-
-from example import ConstructorStats
-
-cstats = ConstructorStats.get(ExampleMandA)
-print("Instances not destroyed:", cstats.alive())
-instance1 = instance2 = None
-print("Instances not destroyed:", cstats.alive())
-print("Constructor values:", cstats.values())
-print("Default constructions:", cstats.default_constructions)
-print("Copy constructions:", cstats.copy_constructions)
-print("Move constructions:", cstats.move_constructions >= 1)
-print("Copy assignments:", cstats.copy_assignments)
-print("Move assignments:", cstats.move_assignments)
diff --git a/example/example-methods-and-attributes.ref b/example/example-methods-and-attributes.ref
deleted file mode 100644
index 338539e..0000000
--- a/example/example-methods-and-attributes.ref
+++ /dev/null
@@ -1,34 +0,0 @@
-### ExampleMandA @ 0x2801910 created via default constructor
-### ExampleMandA @ 0x27fa780 created 32
-### ExampleMandA @ 0x7fff80a98a74 created via copy constructor
-### ExampleMandA @ 0x7fff80a98a78 created via copy constructor
-### ExampleMandA @ 0x7fff80a98a78 destroyed
-### ExampleMandA @ 0x7fff80a98a74 destroyed
-Instance 1: ExampleMandA[value=320]
-Instance 2: ExampleMandA[value=32]
-### ExampleMandA @ 0x7fff80a98a84 created via copy constructor
-### ExampleMandA @ 0x2801fd0 created via move constructor
-### ExampleMandA @ 0x7fff80a98a84 destroyed
-ExampleMandA[value=320]
-### ExampleMandA @ 0x2801fd0 destroyed
-ExampleMandA[value=320]
-ExampleMandA[value=320]
-ExampleMandA[value=320]
-ExampleMandA[value=320]
-320
-320
-320
-320
-320
-Instance 1, direct access = 320
-Instance 1: ExampleMandA[value=100]
-Instances not destroyed: 2
-### ExampleMandA @ 0x2801910 destroyed
-### ExampleMandA @ 0x27fa780 destroyed
-Instances not destroyed: 0
-Constructor values: ['32']
-Default constructions: 1
-Copy constructions: 3
-Move constructions: True
-Copy assignments: 0
-Move assignments: 0
diff --git a/example/example-modules.py b/example/example-modules.py
deleted file mode 100755
index 91c075c..0000000
--- a/example/example-modules.py
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-import example
-
-print(example.__name__)
-print(example.submodule.__name__)
-
-from example.submodule import *
-from example import OD
-
-submodule_func()
-
-b = B()
-print(b.get_a1())
-print(b.a1)
-print(b.get_a2())
-print(b.a2)
-
-b.a1 = A(42)
-b.a2 = A(43)
-
-print(b.get_a1())
-print(b.a1)
-print(b.get_a2())
-print(b.a2)
-
-print(OD([(1, 'a'), (2, 'b')]))
-
-from example import ConstructorStats
-
-cstats = [ConstructorStats.get(A), ConstructorStats.get(B)]
-print("Instances not destroyed:", [x.alive() for x in cstats])
-b = None
-print("Instances not destroyed:", [x.alive() for x in cstats])
-print("Constructor values:", [x.values() for x in cstats])
-print("Default constructions:", [x.default_constructions for x in cstats])
-print("Copy constructions:", [x.copy_constructions for x in cstats])
-#print("Move constructions:", [x.move_constructions >= 0 for x in cstats]) # Don't invoke any
-print("Copy assignments:", [x.copy_assignments for x in cstats])
-print("Move assignments:", [x.move_assignments for x in cstats])
diff --git a/example/example-modules.ref b/example/example-modules.ref
deleted file mode 100644
index 1ca0783..0000000
--- a/example/example-modules.ref
+++ /dev/null
@@ -1,31 +0,0 @@
-example
-example.submodule
-submodule_func()
-### A @ 0x21a5bc0 created 1
-### A @ 0x21a5bc4 created 2
-### B @ 0x21a5bc0 created via default constructor
-A[1]
-A[1]
-A[2]
-A[2]
-### A @ 0x20f93b0 created 42
-### A @ 0x21a5bc0 assigned via copy assignment
-### A @ 0x20f93b0 destroyed
-### A @ 0x20f93d0 created 43
-### A @ 0x21a5bc4 assigned via copy assignment
-### A @ 0x20f93d0 destroyed
-A[42]
-A[42]
-A[43]
-A[43]
-OrderedDict([(1, 'a'), (2, 'b')])
-Instances not destroyed: [2, 1]
-### B @ 0x21a5bc0 destroyed
-### A @ 0x21a5bc4 destroyed
-### A @ 0x21a5bc0 destroyed
-Instances not destroyed: [0, 0]
-Constructor values: [['1', '2', '42', '43'], []]
-Default constructions: [0, 1]
-Copy constructions: [0, 0]
-Copy assignments: [2, 0]
-Move assignments: [0, 0]
diff --git a/example/example-numpy-dtypes.py b/example/example-numpy-dtypes.py
deleted file mode 100644
index 0618591..0000000
--- a/example/example-numpy-dtypes.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-
-import numpy as np
-from example import (
-    create_rec_simple, create_rec_packed, create_rec_nested, print_format_descriptors,
-    print_rec_simple, print_rec_packed, print_rec_nested, print_dtypes, get_format_unbound,
-    create_rec_partial, create_rec_partial_nested, create_string_array, print_string_array,
-    test_array_ctors, test_dtype_ctors, test_dtype_methods
-)
-
-
-def check_eq(arr, data, dtype):
-    np.testing.assert_equal(arr, np.array(data, dtype=dtype))
-
-try:
-    get_format_unbound()
-    raise Exception
-except RuntimeError as e:
-    assert 'unsupported buffer format' in str(e)
-
-print_format_descriptors()
-print_dtypes()
-
-simple_dtype = np.dtype({'names': ['x', 'y', 'z'],
-                         'formats': ['?', 'u4', 'f4'],
-                         'offsets': [0, 4, 8]})
-packed_dtype = np.dtype([('x', '?'), ('y', 'u4'), ('z', 'f4')])
-
-elements = [(False, 0, 0.0), (True, 1, 1.5), (False, 2, 3.0)]
-
-for func, dtype in [(create_rec_simple, simple_dtype), (create_rec_packed, packed_dtype)]:
-    arr = func(0)
-    assert arr.dtype == dtype
-    check_eq(arr, [], simple_dtype)
-    check_eq(arr, [], packed_dtype)
-
-    arr = func(3)
-    assert arr.dtype == dtype
-    check_eq(arr, elements, simple_dtype)
-    check_eq(arr, elements, packed_dtype)
-
-    if dtype == simple_dtype:
-        print_rec_simple(arr)
-    else:
-        print_rec_packed(arr)
-
-arr = create_rec_partial(3)
-print(arr.dtype)
-partial_dtype = arr.dtype
-assert '' not in arr.dtype.fields
-assert partial_dtype.itemsize > simple_dtype.itemsize
-check_eq(arr, elements, simple_dtype)
-check_eq(arr, elements, packed_dtype)
-
-arr = create_rec_partial_nested(3)
-print(arr.dtype)
-assert '' not in arr.dtype.fields
-assert '' not in arr.dtype.fields['a'][0].fields
-assert arr.dtype.itemsize > partial_dtype.itemsize
-np.testing.assert_equal(arr['a'], create_rec_partial(3))
-
-nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)])
-
-arr = create_rec_nested(0)
-assert arr.dtype == nested_dtype
-check_eq(arr, [], nested_dtype)
-
-arr = create_rec_nested(3)
-assert arr.dtype == nested_dtype
-check_eq(arr, [((False, 0, 0.0), (True, 1, 1.5)),
-               ((True, 1, 1.5), (False, 2, 3.0)),
-               ((False, 2, 3.0), (True, 3, 4.5))], nested_dtype)
-print_rec_nested(arr)
-
-assert create_rec_nested.__doc__.strip().endswith('numpy.ndarray[NestedStruct]')
-
-arr = create_string_array(True)
-print(arr.dtype)
-print_string_array(arr)
-dtype = arr.dtype
-assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc']
-assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc']
-arr = create_string_array(False)
-assert dtype == arr.dtype
-
-data = np.arange(1, 7, dtype='int32')
-for i in range(8):
-    np.testing.assert_array_equal(test_array_ctors(10 + i), data.reshape((3, 2)))
-    np.testing.assert_array_equal(test_array_ctors(20 + i), data.reshape((3, 2)))
-for i in range(5):
-    np.testing.assert_array_equal(test_array_ctors(30 + i), data)
-    np.testing.assert_array_equal(test_array_ctors(40 + i), data)
-
-d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
-               'offsets': [1, 10], 'itemsize': 20})
-d2 = np.dtype([('a', 'i4'), ('b', 'f4')])
-assert test_dtype_ctors() == [np.dtype('int32'), np.dtype('float64'),
-                              np.dtype('bool'), d1, d1, np.dtype('uint32'), d2]
-
-assert test_dtype_methods() == [np.dtype('int32'), simple_dtype, False, True,
-                                np.dtype('int32').itemsize, simple_dtype.itemsize]
diff --git a/example/example-numpy-dtypes.ref b/example/example-numpy-dtypes.ref
deleted file mode 100644
index 4f07ce4..0000000
--- a/example/example-numpy-dtypes.ref
+++ /dev/null
@@ -1,28 +0,0 @@
-T{=?:x:3x=I:y:=f:z:}
-T{=?:x:=I:y:=f:z:}
-T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}
-T{=?:x:3x=I:y:=f:z:12x}
-T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}
-T{=3s:a:=3s:b:}
-{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}
-[('x', '?'), ('y', '<u4'), ('z', '<f4')]
-[('a', {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}), ('b', [('x', '?'), ('y', '<u4'), ('z', '<f4')])]
-{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}
-{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}
-[('a', 'S3'), ('b', 'S3')]
-s:0,0,0
-s:1,1,1.5
-s:0,2,3
-p:0,0,0
-p:1,1,1.5
-p:0,2,3
-{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}
-{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}
-n:a=s:0,0,0;b=p:1,1,1.5
-n:a=s:1,1,1.5;b=p:0,2,3
-n:a=s:0,2,3;b=p:1,3,4.5
-[('a', 'S3'), ('b', 'S3')]
-a='',b=''
-a='a',b='a'
-a='ab',b='ab'
-a='abc',b='abc'
diff --git a/example/example-numpy-vectorize.py b/example/example-numpy-vectorize.py
deleted file mode 100755
index 322ce2a..0000000
--- a/example/example-numpy-vectorize.py
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-import example
-try:
-    import numpy as np
-except ImportError:
-    # NumPy missing: skip test
-    exit(99)
-
-from example import vectorized_func
-from example import vectorized_func2
-from example import vectorized_func3
-
-print(vectorized_func3(np.array(3+7j)))
-
-for f in [vectorized_func, vectorized_func2]:
-    print(f(1, 2, 3))
-    print(f(np.array(1), np.array(2), 3))
-    print(f(np.array([1, 3]), np.array([2, 4]), 3))
-    print(f(np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3))
-    print(np.array([[1, 3, 5], [7, 9, 11]])* np.array([[2, 4, 6], [8, 10, 12]])*3)
-    print(f(np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2))
-    print(np.array([[1, 2, 3], [4, 5, 6]])* np.array([2, 3, 4])* 2)
-    print(f(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2))
-    print(np.array([[1, 2, 3], [4, 5, 6]])* np.array([[2], [3]])* 2)
-
-from example import selective_func
-
-selective_func(np.array([1], dtype=np.int32))
-selective_func(np.array([1.0], dtype=np.float32))
-selective_func(np.array([1.0j], dtype=np.complex64))
-
-print(vectorized_func.__doc__)
diff --git a/example/example-numpy-vectorize.ref b/example/example-numpy-vectorize.ref
deleted file mode 100644
index d2d5d9b..0000000
--- a/example/example-numpy-vectorize.ref
+++ /dev/null
@@ -1,79 +0,0 @@
-(6+14j)
-my_func(x:int=1, y:float=2, z:float=3)
-6.0
-my_func(x:int=1, y:float=2, z:float=3)
-6.0
-my_func(x:int=1, y:float=2, z:float=3)
-my_func(x:int=3, y:float=4, z:float=3)
-[  6.  36.]
-my_func(x:int=1, y:float=2, z:float=3)
-my_func(x:int=3, y:float=4, z:float=3)
-my_func(x:int=5, y:float=6, z:float=3)
-my_func(x:int=7, y:float=8, z:float=3)
-my_func(x:int=9, y:float=10, z:float=3)
-my_func(x:int=11, y:float=12, z:float=3)
-[[   6.   36.   90.]
- [ 168.  270.  396.]]
-[[  6  36  90]
- [168 270 396]]
-my_func(x:int=1, y:float=2, z:float=2)
-my_func(x:int=2, y:float=3, z:float=2)
-my_func(x:int=3, y:float=4, z:float=2)
-my_func(x:int=4, y:float=2, z:float=2)
-my_func(x:int=5, y:float=3, z:float=2)
-my_func(x:int=6, y:float=4, z:float=2)
-[[  4.  12.  24.]
- [ 16.  30.  48.]]
-[[ 4 12 24]
- [16 30 48]]
-my_func(x:int=1, y:float=2, z:float=2)
-my_func(x:int=2, y:float=2, z:float=2)
-my_func(x:int=3, y:float=2, z:float=2)
-my_func(x:int=4, y:float=3, z:float=2)
-my_func(x:int=5, y:float=3, z:float=2)
-my_func(x:int=6, y:float=3, z:float=2)
-[[  4.   8.  12.]
- [ 24.  30.  36.]]
-[[ 4  8 12]
- [24 30 36]]
-my_func(x:int=1, y:float=2, z:float=3)
-6.0
-my_func(x:int=1, y:float=2, z:float=3)
-6.0
-my_func(x:int=1, y:float=2, z:float=3)
-my_func(x:int=3, y:float=4, z:float=3)
-[  6.  36.]
-my_func(x:int=1, y:float=2, z:float=3)
-my_func(x:int=3, y:float=4, z:float=3)
-my_func(x:int=5, y:float=6, z:float=3)
-my_func(x:int=7, y:float=8, z:float=3)
-my_func(x:int=9, y:float=10, z:float=3)
-my_func(x:int=11, y:float=12, z:float=3)
-[[   6.   36.   90.]
- [ 168.  270.  396.]]
-[[  6  36  90]
- [168 270 396]]
-my_func(x:int=1, y:float=2, z:float=2)
-my_func(x:int=2, y:float=3, z:float=2)
-my_func(x:int=3, y:float=4, z:float=2)
-my_func(x:int=4, y:float=2, z:float=2)
-my_func(x:int=5, y:float=3, z:float=2)
-my_func(x:int=6, y:float=4, z:float=2)
-[[  4.  12.  24.]
- [ 16.  30.  48.]]
-[[ 4 12 24]
- [16 30 48]]
-my_func(x:int=1, y:float=2, z:float=2)
-my_func(x:int=2, y:float=2, z:float=2)
-my_func(x:int=3, y:float=2, z:float=2)
-my_func(x:int=4, y:float=3, z:float=2)
-my_func(x:int=5, y:float=3, z:float=2)
-my_func(x:int=6, y:float=3, z:float=2)
-[[  4.   8.  12.]
- [ 24.  30.  36.]]
-[[ 4  8 12]
- [24 30 36]]
-Int branch taken. 
-Float branch taken. 
-Complex float branch taken. 
-vectorized_func(arg0: numpy.ndarray[int], arg1: numpy.ndarray[float], arg2: numpy.ndarray[float]) -> object
diff --git a/example/example-opaque-types.py b/example/example-opaque-types.py
deleted file mode 100644
index 1035634..0000000
--- a/example/example-opaque-types.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from __future__ import print_function
-import sys
-
-sys.path.append('.')
-
-from example import StringList, print_opaque_list
-from example import ClassWithSTLVecProperty
-from example import return_void_ptr, print_void_ptr
-from example import return_null_str, print_null_str
-from example import return_unique_ptr
-from example import ExampleMandA
-
-#####
-
-l = StringList()
-l.push_back("Element 1")
-l.push_back("Element 2")
-print_opaque_list(l)
-print("Back element is %s" % l.back())
-for i, k in enumerate(l):
-    print("%i/%i : %s" % (i + 1, len(l), k))
-l.pop_back()
-print_opaque_list(l)
-
-#####
-cvp = ClassWithSTLVecProperty()
-print_opaque_list(cvp.stringList)
-
-cvp.stringList = l
-cvp.stringList.push_back("Element 3")
-print_opaque_list(cvp.stringList)
-
-#####
-
-print_void_ptr(return_void_ptr())
-print_void_ptr(ExampleMandA())  # Should also work for other C++ types
-from example import ConstructorStats
-print("ExampleMandA still alive:", ConstructorStats.get(ExampleMandA).alive())
-
-try:
-    print_void_ptr([1, 2, 3])  # This should not work
-except Exception as e:
-    print("Caught expected exception: " + str(e))
-
-print(return_null_str())
-print_null_str(return_null_str())
-
-#####
-
-ptr = return_unique_ptr()
-print(ptr)
-print_opaque_list(ptr)
diff --git a/example/example-opaque-types.ref b/example/example-opaque-types.ref
deleted file mode 100644
index 12b87d3..0000000
--- a/example/example-opaque-types.ref
+++ /dev/null
@@ -1,19 +0,0 @@
-Opaque list: [Element 1, Element 2]
-Back element is Element 2
-1/2 : Element 1
-2/2 : Element 2
-Opaque list: [Element 1]
-Opaque list: []
-Opaque list: [Element 1, Element 3]
-Got void ptr : 0x1234
-### ExampleMandA @ 0x2ac5370 created via default constructor
-Got void ptr : 0x2ac5370
-### ExampleMandA @ 0x2ac5370 destroyed
-ExampleMandA still alive: 0
-Caught expected exception: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: capsule) -> None
-    Invoked with: [1, 2, 3]
-None
-Got null str : 0x0
-<example.StringList object at 0x7f7ecde6fc00>
-Opaque list: [some value]
diff --git a/example/example-operator-overloading.py b/example/example-operator-overloading.py
deleted file mode 100755
index 4253a75..0000000
--- a/example/example-operator-overloading.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import Vector2, Vector
-
-v1 = Vector2(1, 2)
-v2 = Vector(3, -1)
-
-print("v1    = " + str(v1))
-print("v2    = " + str(v2))
-print("v1+v2 = " + str(v1+v2))
-print("v1-v2 = " + str(v1-v2))
-print("v1-8  = " + str(v1-8))
-print("v1+8  = " + str(v1+8))
-print("v1*8  = " + str(v1*8))
-print("v1/8  = " + str(v1/8))
-print("8-v1  = " + str(8-v1))
-print("8+v1  = " + str(8+v1))
-print("8*v1  = " + str(8*v1))
-print("8/v1  = " + str(8/v1))
-
-v1 += v2
-v1 *= 2
-
-print("(v1+v2)*2 = " + str(v1))
-
-from example import ConstructorStats
-cstats = ConstructorStats.get(Vector2)
-print("Instances not destroyed:", cstats.alive())
-v1 = None
-print("Instances not destroyed:", cstats.alive())
-v2 = None
-print("Instances not destroyed:", cstats.alive())
-print("Constructor values:", cstats.values())
-print("Default constructions:", cstats.default_constructions)
-print("Copy constructions:", cstats.copy_constructions)
-print("Move constructions:", cstats.move_constructions >= 10)
-print("Copy assignments:", cstats.copy_assignments)
-print("Move assignments:", cstats.move_assignments)
diff --git a/example/example-operator-overloading.ref b/example/example-operator-overloading.ref
deleted file mode 100644
index 8236531..0000000
--- a/example/example-operator-overloading.ref
+++ /dev/null
@@ -1,66 +0,0 @@
-### Vector2 @ 0x11f7830 created [1.000000, 2.000000]
-### Vector2 @ 0x11427c0 created [3.000000, -1.000000]
-v1    = [1.000000, 2.000000]
-v2    = [3.000000, -1.000000]
-### Vector2 @ 0x7ffef6b144b8 created [4.000000, 1.000000]
-### Vector2 @ 0x11f7e90 created via move constructor
-### Vector2 @ 0x7ffef6b144b8 destroyed
-### Vector2 @ 0x11f7e90 destroyed
-v1+v2 = [4.000000, 1.000000]
-### Vector2 @ 0x7ffef6b144b8 created [-2.000000, 3.000000]
-### Vector2 @ 0x11f7e90 created via move constructor
-### Vector2 @ 0x7ffef6b144b8 destroyed
-### Vector2 @ 0x11f7e90 destroyed
-v1-v2 = [-2.000000, 3.000000]
-### Vector2 @ 0x7ffef6b144c8 created [-7.000000, -6.000000]
-### Vector2 @ 0x1115760 created via move constructor
-### Vector2 @ 0x7ffef6b144c8 destroyed
-### Vector2 @ 0x1115760 destroyed
-v1-8  = [-7.000000, -6.000000]
-### Vector2 @ 0x7ffef6b144c8 created [9.000000, 10.000000]
-### Vector2 @ 0x1115760 created via move constructor
-### Vector2 @ 0x7ffef6b144c8 destroyed
-### Vector2 @ 0x1115760 destroyed
-v1+8  = [9.000000, 10.000000]
-### Vector2 @ 0x7ffef6b144b8 created [8.000000, 16.000000]
-### Vector2 @ 0x1115760 created via move constructor
-### Vector2 @ 0x7ffef6b144b8 destroyed
-### Vector2 @ 0x1115760 destroyed
-v1*8  = [8.000000, 16.000000]
-### Vector2 @ 0x7ffef6b144a8 created [0.125000, 0.250000]
-### Vector2 @ 0x112f150 created via move constructor
-### Vector2 @ 0x7ffef6b144a8 destroyed
-### Vector2 @ 0x112f150 destroyed
-v1/8  = [0.125000, 0.250000]
-### Vector2 @ 0x7ffef6b144f8 created [7.000000, 6.000000]
-### Vector2 @ 0x112f1b0 created via move constructor
-### Vector2 @ 0x7ffef6b144f8 destroyed
-### Vector2 @ 0x112f1b0 destroyed
-8-v1  = [7.000000, 6.000000]
-### Vector2 @ 0x7ffef6b144f8 created [9.000000, 10.000000]
-### Vector2 @ 0x112f1b0 created via move constructor
-### Vector2 @ 0x7ffef6b144f8 destroyed
-### Vector2 @ 0x112f1b0 destroyed
-8+v1  = [9.000000, 10.000000]
-### Vector2 @ 0x7ffef6b144e8 created [8.000000, 16.000000]
-### Vector2 @ 0x112f230 created via move constructor
-### Vector2 @ 0x7ffef6b144e8 destroyed
-### Vector2 @ 0x112f230 destroyed
-8*v1  = [8.000000, 16.000000]
-### Vector2 @ 0x7ffef6b144d8 created [8.000000, 4.000000]
-### Vector2 @ 0x11fb360 created via move constructor
-### Vector2 @ 0x7ffef6b144d8 destroyed
-### Vector2 @ 0x11fb360 destroyed
-8/v1  = [8.000000, 4.000000]
-(v1+v2)*2 = [8.000000, 2.000000]
-Instances not destroyed: 2
-### Vector2 @ 0x11f7830 destroyed
-Instances not destroyed: 1
-### Vector2 @ 0x11427c0 destroyed
-Instances not destroyed: 0
-Constructor values: ['[1.000000, 2.000000]', '[3.000000, -1.000000]', '[4.000000, 1.000000]', '[-2.000000, 3.000000]', '[-7.000000, -6.000000]', '[9.000000, 10.000000]', '[8.000000, 16.000000]', '[0.125000, 0.250000]', '[7.000000, 6.000000]', '[9.000000, 10.000000]', '[8.000000, 16.000000]', '[8.000000, 4.000000]']
-Default constructions: 0
-Copy constructions: 0
-Move constructions: True
-Copy assignments: 0
-Move assignments: 0
diff --git a/example/example-pickling.py b/example/example-pickling.py
deleted file mode 100644
index 1810d3e..0000000
--- a/example/example-pickling.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from __future__ import print_function
-import sys
-
-sys.path.append('.')
-
-from example import Pickleable
-
-try:
-    import cPickle as pickle  # Use cPickle on Python 2.7
-except ImportError:
-    import pickle
-
-p = Pickleable("test_value")
-p.setExtra1(15)
-p.setExtra2(48)
-
-data = pickle.dumps(p, 2)  # Must use pickle protocol >= 2
-print("%s %i %i" % (p.value(), p.extra1(), p.extra2()))
-
-p2 = pickle.loads(data)
-print("%s %i %i" % (p2.value(), p2.extra1(), p2.extra2()))
diff --git a/example/example-pickling.ref b/example/example-pickling.ref
deleted file mode 100644
index d804973..0000000
--- a/example/example-pickling.ref
+++ /dev/null
@@ -1,2 +0,0 @@
-test_value 15 48
-test_value 15 48
diff --git a/example/example-python-types.py b/example/example-python-types.py
deleted file mode 100755
index 11b89bf..0000000
--- a/example/example-python-types.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys, pydoc
-sys.path.append('.')
-
-import example
-from example import ExamplePythonTypes
-
-ExamplePythonTypes.value = 15
-print(ExamplePythonTypes.value)
-print(ExamplePythonTypes.value2)
-
-try:
-    ExamplePythonTypes()
-except Exception as e:
-    print(e)
-
-try:
-    ExamplePythonTypes.value2 = 15
-except Exception as e:
-    print(e)
-
-instance = ExamplePythonTypes.new_instance()
-
-dict_result = instance.get_dict()
-dict_result['key2'] = 'value2'
-instance.print_dict(dict_result)
-
-dict_result = instance.get_dict_2()
-dict_result['key2'] = 'value2'
-instance.print_dict_2(dict_result)
-
-set_result = instance.get_set()
-set_result.add('key3')
-instance.print_set(set_result)
-
-set_result = instance.get_set2()
-set_result.add('key3')
-instance.print_set_2(set_result)
-
-list_result = instance.get_list()
-list_result.append('value2')
-instance.print_list(list_result)
-
-list_result = instance.get_list_2()
-list_result.append('value2')
-instance.print_list_2(list_result)
-
-array_result = instance.get_array()
-print(array_result)
-instance.print_array(array_result)
-
-try:
-    instance.throw_exception()
-except Exception as e:
-    print(e)
-
-print(instance.pair_passthrough((True, "test")))
-print(instance.tuple_passthrough((True, "test", 5)))
-
-print(pydoc.render_doc(ExamplePythonTypes, "Help on %s"))
-
-print("__name__(example) = %s" % example.__name__)
-print("__name__(example.ExamplePythonTypes) = %s" % ExamplePythonTypes.__name__)
-print("__module__(example.ExamplePythonTypes) = %s" % ExamplePythonTypes.__module__)
-print("__name__(example.ExamplePythonTypes.get_set) = %s" % ExamplePythonTypes.get_set.__name__)
-print("__module__(example.ExamplePythonTypes.get_set) = %s" % ExamplePythonTypes.get_set.__module__)
-
-print(instance.get_bytes_from_string().decode())
-print(instance.get_bytes_from_str().decode())
-print(instance.get_str_from_string().encode().decode())
-print(instance.get_str_from_bytes().encode().decode())
-
-class A(object):
-    __str__ = lambda _: 'this is a str'
-    __repr__ = lambda _: 'this is a repr'
-
-instance.test_print(A())
-
-from example import ConstructorStats
-
-cstats = ConstructorStats.get(ExamplePythonTypes)
-print("Instances not destroyed:", cstats.alive())
-instance = None
-print("Instances not destroyed:", cstats.alive())
diff --git a/example/example-python-types.ref b/example/example-python-types.ref
deleted file mode 100644
index d89acb6..0000000
--- a/example/example-python-types.ref
+++ /dev/null
@@ -1,146 +0,0 @@
-15
-5
-example.ExamplePythonTypes: No constructor defined!
-can't set attribute
-### ExamplePythonTypes @ 0x1045b80 created via new_instance
-key: key2, value=value2
-key: key, value=value
-key: key, value=value
-key: key2, value=value2
-key: key3
-key: key2
-key: key1
-key: key1
-key: key2
-key: key3
-Entry at positon 0: value
-list item 0: overwritten
-list item 1: value2
-list item 0: value
-list item 1: value2
-[u'array entry 1', u'array entry 2']
-array item 0: array entry 1
-array item 1: array entry 2
-This exception was intentionally thrown.
-(u'test', True)
-(5L, u'test', True)
-Help on class ExamplePythonTypes in module example
-
-class EExxaammpplleePPyytthhoonnTTyyppeess(__builtin__.object)
- |  Example 2 documentation
- |
- |  Methods defined here:
- |
- |  ____iinniitt____(...)
- |      x.__init__(...) initializes x; see help(type(x)) for signature
- |
- |  ggeett__aarrrraayy(...)
- |
- |      Signature : (example.ExamplePythonTypes) -> List[unicode[2]]
- |      Return a C++ array
- |
- |  ggeett__ddiicctt(...)
- |      Signature : (example.ExamplePythonTypes) -> dict
- |
- |      Return a Python dictionary
- |
- |  ggeett__ddiicctt__22(...)
- |
- |      Signature : (example.ExamplePythonTypes) -> Dict[unicode, unicode]
- |      Return a C++ dictionary
- |
- |  ggeett__lliisstt(...)
- |      Signature : (example.ExamplePythonTypes) -> list
- |
- |      Return a Python list
- |
- |  ggeett__lliisstt__22(...)
- |
- |      Signature : (example.ExamplePythonTypes) -> List[unicode]
- |      Return a C++ list
- |
- |  ggeett__sseett(...)
- |      Signature : (example.ExamplePythonTypes) -> set
- |
- |      Return a Python set
- |
- |  ggeett__sseett22(...)
- |      Signature : (example.ExamplePythonTypes) -> set
- |
- |      Return a C++ set
- |
- |  ppaaiirr__ppaasssstthhrroouugghh(...)
- |
- |      Signature : (example.ExamplePythonTypes, Tuple[bool, unicode]) -> Tuple[unicode, bool]
- |      Return a pair in reversed order
- |
- |  pprriinntt__aarrrraayy(...)
- |
- |      Signature : (example.ExamplePythonTypes, List[unicode[2]]) -> None
- |      Print entries of a C++ array
- |
- |  pprriinntt__ddiicctt(...)
- |
- |      Signature : (example.ExamplePythonTypes, dict) -> None
- |      Print entries of a Python dictionary
- |
- |  pprriinntt__ddiicctt__22(...)
- |
- |      Signature : (example.ExamplePythonTypes, Dict[unicode, unicode]) -> None
- |      Print entries of a C++ dictionary
- |
- |  pprriinntt__lliisstt(...)
- |
- |      Signature : (example.ExamplePythonTypes, list) -> None
- |      Print entries of a Python list
- |
- |  pprriinntt__lliisstt__22(...)
- |
- |      Signature : (example.ExamplePythonTypes, List[unicode]) -> None
- |      Print entries of a C++ list
- |
- |  pprriinntt__sseett(...)
- |
- |      Signature : (example.ExamplePythonTypes, set) -> None
- |      Print entries of a Python set
- |
- |  pprriinntt__sseett__22(...)
- |
- |      Signature : (example.ExamplePythonTypes, Set[unicode]) -> None
- |      Print entries of a C++ set
- |
- |  tthhrrooww__eexxcceeppttiioonn(...)
- |
- |      Signature : (example.ExamplePythonTypes) -> None
- |      Throw an exception
- |
- |  ttuuppllee__ppaasssstthhrroouugghh(...)
- |
- |      Signature : (example.ExamplePythonTypes, Tuple[bool, unicode, int]) -> Tuple[int, unicode, bool]
- |      Return a triple in reversed order
- |
- |  ----------------------------------------------------------------------
- |  Data and other attributes defined here:
- |
- |  ____nneeww____ = <built-in method __new__ of example.ExamplePythonTypes__Meta object>
- |      T.__new__(S, ...) -> a new object with type S, a subtype of T
- |
- |  nneeww__iinnssttaannccee = <built-in method new_instance of PyCapsule object>
- |      Signature : () -> example.ExamplePythonTypes
- |
- |      Return an instance
-
-__name__(example) = example
-__name__(example.ExamplePythonTypes) = ExamplePythonTypes
-__module__(example.ExamplePythonTypes) = example
-__name__(example.ExamplePythonTypes.get_set) = get_set
-__module__(example.ExamplePythonTypes.get_set) = example
-foo
-bar
-baz
-boo
-this is a str
-this is a repr
-Instances not destroyed: 1
-### ExamplePythonTypes @ 0x1045b80 destroyed
-Instances not destroyed: 0
diff --git a/example/example-sequences-and-iterators.py b/example/example-sequences-and-iterators.py
deleted file mode 100755
index 764a527..0000000
--- a/example/example-sequences-and-iterators.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import Sequence, StringMap
-
-s = Sequence(5)
-print("s = " + str(s))
-print("len(s) = " + str(len(s)))
-print("s[0], s[3] = %f %f" % (s[0], s[3]))
-print('12.34 in s: ' + str(12.34 in s))
-s[0], s[3] = 12.34, 56.78
-print('12.34 in s: ' + str(12.34 in s))
-print("s[0], s[3] = %f %f" % (s[0], s[3]))
-rev = reversed(s)
-rev2 = s[::-1]
-print("rev[0], rev[1], rev[2], rev[3], rev[4] = %f %f %f %f %f" % (rev[0], rev[1], rev[2], rev[3], rev[4]))
-
-for i in rev:
-    print(i, end=' ')
-print('')
-for i in rev2:
-    print(i, end=' ')
-print('')
-print(rev == rev2)
-rev[0::2] = Sequence([2.0, 2.0, 2.0])
-for i in rev:
-    print(i, end=' ')
-print('')
-
-m = StringMap({ 'hi': 'bye', 'black': 'white' })
-print(m['hi'])
-print(len(m))
-print(m['black'])
-try:
-    print(m['orange'])
-    print('Error: should have thrown exception')
-except KeyError:
-    pass
-m['orange'] = 'banana'
-print(m['orange'])
-
-for k in m:
-    print("key = %s, value = %s" % (k, m[k]))
-
-for k,v in m.items():
-    print("item: (%s, %s)" % (k,v))
-
-from example import ConstructorStats
-cstats = ConstructorStats.get(Sequence)
-print("Instances not destroyed:", cstats.alive())
-s = None
-print("Instances not destroyed:", cstats.alive())
-rev = None
-print("Instances not destroyed:", cstats.alive())
-rev2 = None
-print("Instances not destroyed:", cstats.alive())
-print("Constructor values:", cstats.values())
-print("Default constructions:", cstats.default_constructions)
-print("Copy constructions:", cstats.copy_constructions)
-print("Move constructions:", cstats.move_constructions >= 1)
-print("Copy assignments:", cstats.copy_assignments)
-print("Move assignments:", cstats.move_assignments)
diff --git a/example/example-sequences-and-iterators.ref b/example/example-sequences-and-iterators.ref
deleted file mode 100644
index d658fba..0000000
--- a/example/example-sequences-and-iterators.ref
+++ /dev/null
@@ -1,41 +0,0 @@
-### Sequence @ 0x1535b00 created of size 5
-s = <example.Sequence object at 0x7efc73cfa4e0>
-len(s) = 5
-s[0], s[3] = 0.000000 0.000000
-12.34 in s: False
-12.34 in s: True
-s[0], s[3] = 12.340000 56.779999
-### Sequence @ 0x7fff22a45068 created of size 5
-### Sequence @ 0x1538b90 created via move constructor
-### Sequence @ 0x7fff22a45068 destroyed
-### Sequence @ 0x1538bf0 created of size 5
-rev[0], rev[1], rev[2], rev[3], rev[4] = 0.000000 56.779999 0.000000 0.000000 12.340000
-0.0 56.779998779296875 0.0 0.0 12.34000015258789 
-0.0 56.779998779296875 0.0 0.0 12.34000015258789 
-True
-### Sequence @ 0x1b4d1f0 created of size 3 from std::vector
-### Sequence @ 0x1b4d1f0 destroyed
-2.0 56.779998779296875 2.0 0.0 2.0 
-bye
-2
-white
-banana
-key = orange, value = banana
-key = hi, value = bye
-key = black, value = white
-item: (orange, banana)
-item: (hi, bye)
-item: (black, white)
-Instances not destroyed: 3
-### Sequence @ 0x1535b00 destroyed
-Instances not destroyed: 2
-### Sequence @ 0x1538b90 destroyed
-Instances not destroyed: 1
-### Sequence @ 0x1538bf0 destroyed
-Instances not destroyed: 0
-Constructor values: ['of size', '5', 'of size', '5', 'of size', '5', 'of size', '3', 'from std::vector']
-Default constructions: 0
-Copy constructions: 0
-Move constructions: True
-Copy assignments: 0
-Move assignments: 0
diff --git a/example/example-smart-ptr.py b/example/example-smart-ptr.py
deleted file mode 100755
index fe23e11..0000000
--- a/example/example-smart-ptr.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import MyObject1
-from example import MyObject2
-from example import MyObject3
-
-from example import make_object_1
-from example import make_object_2
-from example import make_myobject1_1
-from example import make_myobject1_2
-from example import make_myobject2_1
-from example import make_myobject2_2
-from example import make_myobject3_1
-from example import make_myobject3_2
-
-from example import print_object_1
-from example import print_object_2
-from example import print_object_3
-from example import print_object_4
-
-from example import print_myobject1_1
-from example import print_myobject1_2
-from example import print_myobject1_3
-from example import print_myobject1_4
-
-from example import print_myobject2_1
-from example import print_myobject2_2
-from example import print_myobject2_3
-from example import print_myobject2_4
-
-from example import print_myobject3_1
-from example import print_myobject3_2
-from example import print_myobject3_3
-from example import print_myobject3_4
-
-for o in [make_object_1(), make_object_2(), MyObject1(3)]:
-    print("Reference count = %i" % o.getRefCount())
-    print_object_1(o)
-    print_object_2(o)
-    print_object_3(o)
-    print_object_4(o)
-
-for o in [make_myobject1_1(), make_myobject1_2(), MyObject1(6), 7]:
-    print(o)
-    if not isinstance(o, int):
-        print_object_1(o)
-        print_object_2(o)
-        print_object_3(o)
-        print_object_4(o)
-    print_myobject1_1(o)
-    print_myobject1_2(o)
-    print_myobject1_3(o)
-    print_myobject1_4(o)
-
-for o in [MyObject2(8), make_myobject2_1(), make_myobject2_2()]:
-    print(o)
-    print_myobject2_1(o)
-    print_myobject2_2(o)
-    print_myobject2_3(o)
-    print_myobject2_4(o)
-
-for o in [MyObject3(9), make_myobject3_1(), make_myobject3_2()]:
-    print(o)
-    print_myobject3_1(o)
-    print_myobject3_2(o)
-    print_myobject3_3(o)
-    print_myobject3_4(o)
-
-from example import ConstructorStats, cstats_ref, Object
-
-cstats = [ConstructorStats.get(Object), ConstructorStats.get(MyObject1),
-        ConstructorStats.get(MyObject2), ConstructorStats.get(MyObject3),
-        cstats_ref()]
-print("Instances not destroyed:", [x.alive() for x in cstats])
-o = None
-print("Instances not destroyed:", [x.alive() for x in cstats])
-print("Object value constructions:", [x.values() for x in cstats])
-print("Default constructions:", [x.default_constructions for x in cstats])
-print("Copy constructions:", [x.copy_constructions for x in cstats])
-#print("Move constructions:", [x.move_constructions >= 0 for x in cstats]) # Doesn't invoke any
-print("Copy assignments:", [x.copy_assignments for x in cstats])
-print("Move assignments:", [x.move_assignments for x in cstats])
diff --git a/example/example-smart-ptr.ref b/example/example-smart-ptr.ref
deleted file mode 100644
index 52ffa8b..0000000
--- a/example/example-smart-ptr.ref
+++ /dev/null
@@ -1,270 +0,0 @@
-### Object @ 0xdeffd0 created via default constructor
-### MyObject1 @ 0xdeffd0 created MyObject1[1]
-### ref<MyObject1> @ 0x7f6a2e03c4a8 created from pointer 0xdeffd0
-### Object @ 0xe43f50 created via default constructor
-### MyObject1 @ 0xe43f50 created MyObject1[2]
-### ref<Object> @ 0x7fff136845d0 created from pointer 0xe43f50
-### ref<MyObject1> @ 0x7f6a2c32aad8 created via copy constructor with pointer 0xe43f50
-### ref<Object> @ 0x7fff136845d0 destroyed
-### Object @ 0xee8cf0 created via default constructor
-### MyObject1 @ 0xee8cf0 created MyObject1[3]
-### ref<MyObject1> @ 0x7f6a2c32ab08 created from pointer 0xee8cf0
-Reference count = 1
-MyObject1[1]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xdeffd0
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xdeffd0
-MyObject1[1]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xdeffd0
-MyObject1[1]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xdeffd0
-MyObject1[1]
-### ref<Object> @ 0x7fff136845c8 destroyed
-Reference count = 1
-MyObject1[2]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xe43f50
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xe43f50
-MyObject1[2]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xe43f50
-MyObject1[2]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xe43f50
-MyObject1[2]
-### ref<Object> @ 0x7fff136845c8 destroyed
-Reference count = 1
-MyObject1[3]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8cf0
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xee8cf0
-MyObject1[3]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8cf0
-MyObject1[3]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8cf0
-MyObject1[3]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### MyObject1 @ 0xe43f50 destroyed
-### Object @ 0xe43f50 destroyed
-### ref<MyObject1> @ 0x7f6a2c32aad8 destroyed
-### MyObject1 @ 0xdeffd0 destroyed
-### Object @ 0xdeffd0 destroyed
-### ref<MyObject1> @ 0x7f6a2e03c4a8 destroyed
-### Object @ 0xee8310 created via default constructor
-### MyObject1 @ 0xee8310 created MyObject1[4]
-### ref<MyObject1> @ 0x7f6a2e03c4a8 created from pointer 0xee8310
-### Object @ 0xee8470 created via default constructor
-### MyObject1 @ 0xee8470 created MyObject1[5]
-### ref<MyObject1> @ 0x7fff136845d0 created from pointer 0xee8470
-### ref<MyObject1> @ 0x7f6a2c32aad8 created via copy constructor with pointer 0xee8470
-### ref<MyObject1> @ 0x7fff136845d0 destroyed
-### Object @ 0xee95a0 created via default constructor
-### MyObject1 @ 0xee95a0 created MyObject1[6]
-### ref<MyObject1> @ 0x7f6a2c32ab38 created from pointer 0xee95a0
-### MyObject1 @ 0xee8cf0 destroyed
-### Object @ 0xee8cf0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab08 destroyed
-<example.MyObject1 object at 0x7f6a2e03c480>
-MyObject1[4]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xee8310
-MyObject1[4]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-MyObject1[4]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-MyObject1[4]
-### ref<Object> @ 0x7fff136845c8 destroyed
-MyObject1[4]
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-### ref<MyObject1> @ 0x7fff136845a8 created via copy constructor with pointer 0xee8310
-MyObject1[4]
-### ref<MyObject1> @ 0x7fff136845a8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-MyObject1[4]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8310
-MyObject1[4]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-<example.MyObject1 object at 0x7f6a2c32aab0>
-MyObject1[5]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xee8470
-MyObject1[5]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-MyObject1[5]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-MyObject1[5]
-### ref<Object> @ 0x7fff136845c8 destroyed
-MyObject1[5]
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-### ref<MyObject1> @ 0x7fff136845a8 created via copy constructor with pointer 0xee8470
-MyObject1[5]
-### ref<MyObject1> @ 0x7fff136845a8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-MyObject1[5]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee8470
-MyObject1[5]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-<example.MyObject1 object at 0x7f6a2c32ab10>
-MyObject1[6]
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-### ref<Object> @ 0x7fff136845a8 created via copy constructor with pointer 0xee95a0
-MyObject1[6]
-### ref<Object> @ 0x7fff136845a8 destroyed
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-MyObject1[6]
-### ref<Object> @ 0x7fff136845c8 destroyed
-### ref<Object> @ 0x7fff136845c8 created via default constructor
-### ref<Object> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-MyObject1[6]
-### ref<Object> @ 0x7fff136845c8 destroyed
-MyObject1[6]
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-### ref<MyObject1> @ 0x7fff136845a8 created via copy constructor with pointer 0xee95a0
-MyObject1[6]
-### ref<MyObject1> @ 0x7fff136845a8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-MyObject1[6]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee95a0
-MyObject1[6]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-7
-### Object @ 0xee97f0 created via default constructor
-### MyObject1 @ 0xee97f0 created MyObject1[7]
-### ref<MyObject1> @ 0x7f6a2c32ab08 created from pointer 0xee97f0
-MyObject1[7]
-### MyObject1 @ 0xee97f0 destroyed
-### Object @ 0xee97f0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab08 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### Object @ 0xee99e0 created via default constructor
-### MyObject1 @ 0xee99e0 created MyObject1[7]
-### ref<MyObject1> @ 0x7f6a2c32ab08 created from pointer 0xee99e0
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee99e0
-### ref<MyObject1> @ 0x7fff136845a8 created via copy constructor with pointer 0xee99e0
-MyObject1[7]
-### ref<MyObject1> @ 0x7fff136845a8 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### MyObject1 @ 0xee99e0 destroyed
-### Object @ 0xee99e0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab08 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### Object @ 0xee97f0 created via default constructor
-### MyObject1 @ 0xee97f0 created MyObject1[7]
-### ref<MyObject1> @ 0x7f6a2c32ab08 created from pointer 0xee97f0
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee97f0
-MyObject1[7]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### MyObject1 @ 0xee97f0 destroyed
-### Object @ 0xee97f0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab08 destroyed
-### ref<MyObject1> @ 0x7fff136845c8 created via default constructor
-### Object @ 0xee99e0 created via default constructor
-### MyObject1 @ 0xee99e0 created MyObject1[7]
-### ref<MyObject1> @ 0x7f6a2c32ab08 created from pointer 0xee99e0
-### ref<MyObject1> @ 0x7fff136845c8 assigned via copy assignment pointer 0xee99e0
-MyObject1[7]
-### ref<MyObject1> @ 0x7fff136845c8 destroyed
-### MyObject1 @ 0xee99e0 destroyed
-### Object @ 0xee99e0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab08 destroyed
-### MyObject1 @ 0xee95a0 destroyed
-### Object @ 0xee95a0 destroyed
-### ref<MyObject1> @ 0x7f6a2c32ab38 destroyed
-### MyObject1 @ 0xee8470 destroyed
-### Object @ 0xee8470 destroyed
-### ref<MyObject1> @ 0x7f6a2c32aad8 destroyed
-### MyObject1 @ 0xee8310 destroyed
-### Object @ 0xee8310 destroyed
-### ref<MyObject1> @ 0x7f6a2e03c4a8 destroyed
-### MyObject2 @ 0xe43f50 created MyObject2[8]
-### MyObject2 @ 0xee95a0 created MyObject2[6]
-### MyObject2 @ 0xee95d0 created MyObject2[7]
-<example.MyObject2 object at 0x7f6a2dfc8768>
-MyObject2[8]
-MyObject2[8]
-MyObject2[8]
-MyObject2[8]
-<example.MyObject2 object at 0x7f6a2dfc86c0>
-MyObject2[6]
-MyObject2[6]
-MyObject2[6]
-MyObject2[6]
-<example.MyObject2 object at 0x7f6a2c32d030>
-MyObject2[7]
-MyObject2[7]
-MyObject2[7]
-MyObject2[7]
-### MyObject2 @ 0xee95a0 destroyed
-### MyObject2 @ 0xe43f50 destroyed
-### MyObject3 @ 0xee9ac0 created MyObject3[9]
-### MyObject3 @ 0xe43f90 created MyObject3[8]
-### MyObject3 @ 0xeea7d0 created MyObject3[9]
-### MyObject2 @ 0xee95d0 destroyed
-<example.MyObject3 object at 0x7f6a2dfc8768>
-MyObject3[9]
-MyObject3[9]
-MyObject3[9]
-MyObject3[9]
-<example.MyObject3 object at 0x7f6a2dfc86c0>
-MyObject3[8]
-MyObject3[8]
-MyObject3[8]
-MyObject3[8]
-<example.MyObject3 object at 0x7f6a2c32d068>
-MyObject3[9]
-MyObject3[9]
-MyObject3[9]
-MyObject3[9]
-### MyObject3 @ 0xe43f90 destroyed
-### MyObject3 @ 0xee9ac0 destroyed
-Instances not destroyed: [0, 0, 0, 1, 0]
-### MyObject3 @ 0xeea7d0 destroyed
-Instances not destroyed: [0, 0, 0, 0, 0]
-Object value constructions: [[], ['MyObject1[1]', 'MyObject1[2]', 'MyObject1[3]', 'MyObject1[4]', 'MyObject1[5]', 'MyObject1[6]', 'MyObject1[7]', 'MyObject1[7]', 'MyObject1[7]', 'MyObject1[7]'], ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]'], ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]'], ['from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer', 'from pointer']]
-Default constructions: [10, 0, 0, 0, 30]
-Copy constructions: [0, 0, 0, 0, 12]
-Copy assignments: [0, 0, 0, 0, 30]
-Move assignments: [0, 0, 0, 0, 0]
diff --git a/example/example-stl-binder-vector.py b/example/example-stl-binder-vector.py
deleted file mode 100644
index feae307..0000000
--- a/example/example-stl-binder-vector.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-
-from example import VectorInt, El, VectorEl, VectorVectorEl, VectorBool
-
-v_int = VectorInt([0, 0])
-print(len(v_int))
-
-print(bool(v_int))
-
-v_int2 = VectorInt([0, 0])
-print(v_int == v_int2)
-
-v_int2[1] = 1
-print(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)
-print(v_int2)
-
-v_int.append(99)
-v_int2[2:-2] = v_int
-print(v_int2)
-del v_int2[1:3]
-print(v_int2)
-del v_int2[0]
-print(v_int2)
-
-v_a = VectorEl()
-v_a.append(El(1))
-v_a.append(El(2))
-print(v_a)
-
-vv_a = VectorVectorEl()
-vv_a.append(v_a)
-vv_b = vv_a[0]
-print(vv_b)
-
-vv_c = VectorBool()
-for i in range(10):
-    vv_c.append(i % 2 == 0)
-for i in range(10):
-    if vv_c[i] != (i % 2 == 0):
-        print("Error!")
-print(vv_c)
diff --git a/example/example-stl-binder-vector.ref b/example/example-stl-binder-vector.ref
deleted file mode 100644
index cc271f3..0000000
--- a/example/example-stl-binder-vector.ref
+++ /dev/null
@@ -1,11 +0,0 @@
-2
-True
-True
-True
-VectorInt[3, 2, 1, 0, 1, 2, 3]
-VectorInt[3, 2, 0, 0, 99, 2, 3]
-VectorInt[3, 0, 99, 2, 3]
-VectorInt[0, 99, 2, 3]
-VectorEl[El{1}, El{2}]
-VectorEl[El{1}, El{2}]
-VectorBool[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
diff --git a/example/example-virtual-functions.py b/example/example-virtual-functions.py
deleted file mode 100644
index d67539b..0000000
--- a/example/example-virtual-functions.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example import ExampleVirt, runExampleVirt, runExampleVirtVirtual, runExampleVirtBool
-from example import A_Repeat, B_Repeat, C_Repeat, D_Repeat, A_Tpl, B_Tpl, C_Tpl, D_Tpl
-from example import NCVirt, NonCopyable, Movable
-
-
-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)
-print(runExampleVirt(ex12, 20))
-try:
-    runExampleVirtVirtual(ex12)
-except Exception as e:
-    print("Caught expected exception: " + str(e))
-
-ex12p = ExtendedExampleVirt(10)
-print(runExampleVirt(ex12p, 20))
-print(runExampleVirtBool(ex12p))
-runExampleVirtVirtual(ex12p)
-
-class VI_AR(A_Repeat):
-    def unlucky_number(self):
-        return 99
-class VI_AT(A_Tpl):
-    def unlucky_number(self):
-        return 999
-
-class VI_CR(C_Repeat):
-    def lucky_number(self):
-        return C_Repeat.lucky_number(self) + 1.25
-class VI_CT(C_Tpl):
-    pass
-class VI_CCR(VI_CR):
-    def lucky_number(self):
-        return VI_CR.lucky_number(self) * 10
-class VI_CCT(VI_CT):
-    def lucky_number(self):
-        return VI_CT.lucky_number(self) * 1000
-
-
-class VI_DR(D_Repeat):
-    def unlucky_number(self):
-        return 123
-    def lucky_number(self):
-        return 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
-
-classes = [
-    # A_Repeat, A_Tpl, # abstract (they have a pure virtual unlucky_number)
-    VI_AR, VI_AT,
-    B_Repeat, B_Tpl,
-    C_Repeat, C_Tpl,
-    VI_CR, VI_CT, VI_CCR, VI_CCT,
-    D_Repeat, D_Tpl, VI_DR, VI_DT
-]
-
-for cl in classes:
-    print("\n%s:" % cl.__name__)
-    obj = cl()
-    obj.say_something(3)
-    print("Unlucky = %d" % obj.unlucky_number())
-    if hasattr(obj, "lucky_number"):
-        print("Lucky = %.2f" % obj.lucky_number())
-
-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()
-print("2^2 * 3^2 =")
-ncv1.print_nc(2, 3)
-print("4 + 5 =")
-ncv1.print_movable(4, 5)
-ncv2 = NCVirtExt2()
-print("7 + 7 =")
-ncv2.print_movable(7, 7)
-try:
-    ncv2.print_nc(9, 9)
-    print("Something's wrong: exception not raised!")
-except RuntimeError as e:
-    # Don't print the exception message here because it differs under debug/non-debug mode
-    print("Caught expected exception")
-
-from example import ConstructorStats
-del ex12
-del ex12p
-del obj
-del ncv1
-del ncv2
-cstats = [ConstructorStats.get(ExampleVirt), ConstructorStats.get(NonCopyable), ConstructorStats.get(Movable)]
-print("Instances not destroyed:", [x.alive() for x in cstats])
-print("Constructor values:", [x.values() for x in cstats])
-print("Copy constructions:", [x.copy_constructions for x in cstats])
-print("Move constructions:", [cstats[i].move_constructions >= 1 for i in range(1, len(cstats))])
-
diff --git a/example/example-virtual-functions.ref b/example/example-virtual-functions.ref
deleted file mode 100644
index 5927e0d..0000000
--- a/example/example-virtual-functions.ref
+++ /dev/null
@@ -1,106 +0,0 @@
-### ExampleVirt @ 0x2073a90 created 10
-Original implementation of ExampleVirt::run(state=10, value=20)
-30
-Caught expected exception: Tried to call pure virtual function "ExampleVirt::pure_virtual"
-### ExampleVirt @ 0x2076a00 created 11
-ExtendedExampleVirt::run(20), calling parent..
-Original implementation of ExampleVirt::run(state=11, value=21)
-32
-ExtendedExampleVirt::run_bool()
-False
-ExtendedExampleVirt::pure_virtual(): Hello world
-
-VI_AR:
-hihihi
-Unlucky = 99
-
-VI_AT:
-hihihi
-Unlucky = 999
-
-B_Repeat:
-B says hi 3 times
-Unlucky = 13
-Lucky = 7.00
-
-B_Tpl:
-B says hi 3 times
-Unlucky = 13
-Lucky = 7.00
-
-C_Repeat:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888.00
-
-C_Tpl:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888.00
-
-VI_CR:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 889.25
-
-VI_CT:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888.00
-
-VI_CCR:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 8892.50
-
-VI_CCT:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888000.00
-
-D_Repeat:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888.00
-
-D_Tpl:
-B says hi 3 times
-Unlucky = 4444
-Lucky = 888.00
-
-VI_DR:
-B says hi 3 times
-Unlucky = 123
-Lucky = 42.00
-
-VI_DT:
-VI_DT says: quack quack quack
-Unlucky = 1234
-Lucky = -4.25
-2^2 * 3^2 =
-### NonCopyable @ 0x207df10 created 4 9
-### NonCopyable @ 0x7ffcfe866228 created via move constructor
-### NonCopyable @ 0x207df10 destroyed
-36
-### NonCopyable @ 0x7ffcfe866228 destroyed
-4 + 5 =
-### Movable @ 0x207e230 created 4 5
-### Movable @ 0x7ffcfe86624c created via copy constructor
-9
-### Movable @ 0x7ffcfe86624c destroyed
-7 + 7 =
-### Movable @ 0x20259e0 created 7 7
-### Movable @ 0x7ffcfe86624c created via move constructor
-### Movable @ 0x20259e0 destroyed
-14
-### Movable @ 0x7ffcfe86624c destroyed
-### NonCopyable @ 0x2025a00 created 9 9
-Caught expected exception
-### ExampleVirt @ 0x2073a90 destroyed
-### ExampleVirt @ 0x2076a00 destroyed
-### Movable @ 0x207e230 destroyed
-### NonCopyable @ 0x2025a00 destroyed
-Instances not destroyed: [0, 0, 0]
-Constructor values: [['10', '11'], ['4', '9', '9', '9'], ['4', '5', '7', '7']]
-Copy constructions: [0, 0, 1]
-Move constructions: [True, True]
diff --git a/example/issues.py b/example/issues.py
deleted file mode 100644
index facdafa..0000000
--- a/example/issues.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-import sys
-sys.path.append('.')
-
-from example.issues import print_cchar, print_char
-from example.issues import DispatchIssue, dispatch_issue_go
-from example.issues import Placeholder, return_vec_of_reference_wrapper
-from example.issues import iterator_passthrough
-from example.issues import ElementList, ElementA, print_element
-from example.issues import expect_float, expect_int
-from example.issues import A, call_f
-from example.issues import StrIssue
-from example.issues import NestA, NestB, NestC, print_NestA, print_NestB, print_NestC
-import gc
-
-print_cchar("const char *")
-print_char('c')
-
-
-class PyClass1(DispatchIssue):
-    def dispatch(self):
-        print("Yay..")
-
-
-class PyClass2(DispatchIssue):
-    def dispatch(self):
-        try:
-            super(PyClass2, self).dispatch()
-        except Exception as e:
-            print("Failed as expected: " + str(e))
-        p = PyClass1()
-        dispatch_issue_go(p)
-
-b = PyClass2()
-dispatch_issue_go(b)
-
-print(return_vec_of_reference_wrapper(Placeholder(4)))
-
-print(list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))))
-
-el = ElementList()
-for i in range(10):
-    el.add(ElementA(i))
-gc.collect()
-for i, v in enumerate(el.get()):
-    print("%i==%i, " % (i, v.value()), end='')
-print()
-
-try:
-    print_element(None)
-except Exception as e:
-    print("Failed as expected: " + str(e))
-
-try:
-    print(expect_int(5.2))
-except Exception as e:
-    print("Failed as expected: " + str(e))
-
-print(expect_float(12))
-
-class B(A):
-    def __init__(self):
-        super(B, self).__init__()
-
-    def f(self):
-        print("In python f()")
-
-print("C++ version")
-a = A()
-call_f(a)
-
-print("Python version")
-b = B()
-call_f(b)
-
-print(StrIssue(3))
-try:
-    print(StrIssue("no", "such", "constructor"))
-except TypeError as e:
-    print("Failed as expected: " + str(e))
-
-a = NestA()
-b = NestB()
-c = NestC()
-a += 10
-b.a += 100
-c.b.a += 1000
-b -= 1
-c.b -= 3
-c *= 7
-print_NestA(a)
-print_NestA(b.a)
-print_NestA(c.b.a)
-print_NestB(b)
-print_NestB(c.b)
-print_NestC(c)
-abase = a.as_base()
-print(abase.value)
-a.as_base().value += 44
-print(abase.value)
-print(c.b.a.as_base().value)
-c.b.a.as_base().value += 44
-print(c.b.a.as_base().value)
-del c
-gc.collect()
-del a # Should't delete while abase is still alive
-gc.collect()
-print(abase.value)
-del abase
-gc.collect()
diff --git a/example/issues.ref b/example/issues.ref
deleted file mode 100644
index 1d5d0fb..0000000
--- a/example/issues.ref
+++ /dev/null
@@ -1,55 +0,0 @@
-const char *
-c
-Failed as expected: Tried to call pure virtual function "Base::dispatch"
-Yay..
-[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]]
-[3, 5, 7, 9, 11, 13, 15]
-0==0, 1==1, 2==2, 3==3, 4==4, 5==5, 6==6, 7==7, 8==8, 9==9, 
-Failed as expected: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: example.issues.ElementA) -> None
-    Invoked with: None
-Failed as expected: Incompatible function arguments. The following argument types are supported:
-    1. (arg0: int) -> int
-    Invoked with: 5.2
-12.0
-C++ version
-A.f()
-Python version
-PyA.PyA()
-PyA.f()
-In python f()
-StrIssue.__str__ called
-StrIssue[3]
-Failed as expected: Incompatible constructor arguments. The following argument types are supported:
-    1. example.issues.StrIssue(arg0: int)
-    2. example.issues.StrIssue()
-    Invoked with: no, such, constructor
-### NestABase @ 0x15eb630 created via default constructor
-### NestA @ 0x15eb630 created via default constructor
-### NestABase @ 0x1704000 created via default constructor
-### NestA @ 0x1704000 created via default constructor
-### NestB @ 0x1704000 created via default constructor
-### NestABase @ 0x1633110 created via default constructor
-### NestA @ 0x1633110 created via default constructor
-### NestB @ 0x1633110 created via default constructor
-### NestC @ 0x1633110 created via default constructor
-13
-103
-1003
-3
-1
-35
--2
-42
--2
-42
-### NestC @ 0x1633110 destroyed
-### NestB @ 0x1633110 destroyed
-### NestA @ 0x1633110 destroyed
-### NestABase @ 0x1633110 destroyed
-42
-### NestA @ 0x15eb630 destroyed
-### NestABase @ 0x15eb630 destroyed
-### NestB @ 0x1704000 destroyed
-### NestA @ 0x1704000 destroyed
-### NestABase @ 0x1704000 destroyed
diff --git a/example/run_test.py b/example/run_test.py
deleted file mode 100755
index 2785c8e..0000000
--- a/example/run_test.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import sys
-import os
-import re
-import subprocess
-import difflib
-
-remove_unicode_marker = re.compile(r'u(\'[^\']*\')')
-remove_long_marker    = re.compile(r'([0-9])L')
-remove_hex            = re.compile(r'0x[0-9a-fA-F]+')
-shorten_floats        = re.compile(r'([1-9][0-9]*\.[0-9]{4})[0-9]*')
-
-def sanitize(lines):
-    lines = lines.split('\n')
-    for i in range(len(lines)):
-        line = lines[i]
-        if line.startswith(" |"):
-            line = ""
-        if line.startswith("### "):
-            # Constructor/destructor output.  Useful for example, but unreliable across compilers;
-            # testing of proper construction/destruction occurs with ConstructorStats mechanism instead
-            line = ""
-        line = remove_unicode_marker.sub(r'\1', line)
-        line = remove_long_marker.sub(r'\1', line)
-        line = remove_hex.sub(r'0', line)
-        line = shorten_floats.sub(r'\1', line)
-        line = line.replace('__builtin__', 'builtins')
-        line = line.replace('example.', '')
-        line = line.replace('unicode', 'str')
-        line = line.replace('ExampleWithEnum.EMode', 'EMode')
-        line = line.replace('example.EMode', 'EMode')
-        line = line.replace('method of builtins.PyCapsule instance', '')
-        line = line.strip()
-        lines[i] = line
-
-    return '\n'.join(sorted([l for l in lines if l != ""]))
-
-path = os.path.dirname(__file__)
-if path != '':
-    os.chdir(path)
-
-if len(sys.argv) < 2:
-    print("Syntax: %s <test name>" % sys.argv[0])
-    exit(0)
-
-name = sys.argv[1]
-try:
-    output_bytes = subprocess.check_output([sys.executable, "-u", name + ".py"],
-                                           stderr=subprocess.STDOUT)
-except subprocess.CalledProcessError as exc:
-    print('Test `{}` failed:\n{}\n'.format(name, '-' * 50))
-    print(exc.output.decode())
-    print('-' * 50)
-    sys.exit(1)
-
-output    = sanitize(output_bytes.decode('utf-8'))
-reference = sanitize(open(name + '.ref', 'r').read())
-
-if output == reference:
-    print('Test "%s" succeeded.' % name)
-    exit(0)
-else:
-    print('Test "%s" FAILED!' % name)
-    print('--- output')
-    print('+++ reference')
-    print(''.join(difflib.ndiff(output.splitlines(True),
-                                reference.splitlines(True))))
-    exit(-1)
diff --git a/setup.py b/setup.py
index 07465bb..425e6c5 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-# Setup script for PyPI; use CMakeFile.txt to build the example application
+# Setup script for PyPI; use CMakeFile.txt to build extension modules
 
 from setuptools import setup
 from pybind11 import __version__
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..f433929
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,62 @@
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  message(STATUS "Setting tests build type to MinSizeRel as none was specified")
+  set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build" FORCE)
+endif()
+
+set(PYBIND11_TEST_FILES
+  test_buffers.cpp
+  test_callbacks.cpp
+  test_constants_and_functions.cpp
+  test_eval.cpp
+  test_exceptions.cpp
+  test_inheritance.cpp
+  test_issues.cpp
+  test_keep_alive.cpp
+  test_kwargs_and_defaults.cpp
+  test_methods_and_attributes.cpp
+  test_modules.cpp
+  test_numpy_dtypes.cpp
+  test_numpy_vectorize.cpp
+  test_opaque_types.cpp
+  test_operator_overloading.cpp
+  test_pickling.cpp
+  test_python_types.cpp
+  test_sequences_and_iterators.cpp
+  test_smart_ptr.cpp
+  test_stl_binders.cpp
+  test_virtual_functions.cpp
+)
+
+# Check if Eigen is available
+find_package(Eigen3 QUIET)
+
+if(EIGEN3_FOUND)
+  list(APPEND PYBIND11_TEST_FILES test_eigen.cpp)
+  message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
+else()
+  message(STATUS "Building tests WITHOUT Eigen")
+endif()
+
+# Create the binding library
+pybind11_add_module(pybind11_tests pybind11_tests.cpp ${PYBIND11_TEST_FILES})
+pybind11_enable_warnings(pybind11_tests)
+
+if(EIGEN3_FOUND)
+  target_include_directories(pybind11_tests PRIVATE ${EIGEN3_INCLUDE_DIR})
+  target_compile_definitions(pybind11_tests PRIVATE -DPYBIND11_TEST_EIGEN)
+endif()
+
+set(testdir ${PROJECT_SOURCE_DIR}/tests)
+
+# Always write the output file directly into the 'tests' directory (even on MSVC)
+if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
+  set_target_properties(pybind11_tests PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${testdir})
+  foreach(config ${CMAKE_CONFIGURATION_TYPES})
+    string(TOUPPER ${config} config)
+    set_target_properties(pybind11_tests PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config} ${testdir})
+  endforeach()
+endif()
+
+# A single command to compile and run the tests
+add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest
+                  DEPENDS pybind11_tests WORKING_DIRECTORY ${testdir})
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..5641392
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,204 @@
+"""pytest configuration
+
+Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
+Adds docstring and exceptions message sanitizers: ignore Python 2 vs 3 differences.
+"""
+
+import pytest
+import textwrap
+import difflib
+import re
+import os
+import sys
+import contextlib
+
+_unicode_marker = re.compile(r'u(\'[^\']*\')')
+_long_marker    = re.compile(r'([0-9])L')
+_hexadecimal    = re.compile(r'0x[0-9a-fA-F]+')
+
+
+def _strip_and_dedent(s):
+    """For triple-quote strings"""
+    return textwrap.dedent(s.lstrip('\n').rstrip())
+
+
+def _split_and_sort(s):
+    """For output which does not require specific line order"""
+    return sorted(_strip_and_dedent(s).splitlines())
+
+
+def _make_explanation(a, b):
+    """Explanation for a failed assert -- the a and b arguments are List[str]"""
+    return ["--- actual / +++ expected"] + [line.strip('\n') for line in difflib.ndiff(a, b)]
+
+
+class Output(object):
+    """Basic output post-processing and comparison"""
+    def __init__(self, string):
+        self.string = string
+        self.explanation = []
+
+    def __str__(self):
+        return self.string
+
+    def __eq__(self, other):
+        # Ignore constructor/destructor output which is prefixed with "###"
+        a = [line for line in self.string.strip().splitlines() if not line.startswith("###")]
+        b = _strip_and_dedent(other).splitlines()
+        if a == b:
+            return True
+        else:
+            self.explanation = _make_explanation(a, b)
+            return False
+
+
+class Unordered(Output):
+    """Custom comparison for output without strict line ordering"""
+    def __eq__(self, other):
+        a = _split_and_sort(self.string)
+        b = _split_and_sort(other)
+        if a == b:
+            return True
+        else:
+            self.explanation = _make_explanation(a, b)
+            return False
+
+
+class Capture(object):
+    def __init__(self, capfd):
+        self.capfd = capfd
+        self.out = ""
+
+    def _flush_stdout(self):
+        sys.stdout.flush()
+        os.fsync(sys.stdout.fileno())  # make sure C++ output is also read
+        return self.capfd.readouterr()[0]
+
+    def __enter__(self):
+        self._flush_stdout()
+        return self
+
+    def __exit__(self, *_):
+        self.out = self._flush_stdout()
+
+    def __eq__(self, other):
+        a = Output(self.out)
+        b = other
+        if a == b:
+            return True
+        else:
+            self.explanation = a.explanation
+            return False
+
+    def __str__(self):
+        return self.out
+
+    def __contains__(self, item):
+        return item in self.out
+
+    @property
+    def unordered(self):
+        return Unordered(self.out)
+
+
+@pytest.fixture
+def capture(capfd):
+    """Extended `capfd` with context manager and custom equality operators"""
+    return Capture(capfd)
+
+
+class SanitizedString(object):
+    def __init__(self, sanitizer):
+        self.sanitizer = sanitizer
+        self.string = ""
+        self.explanation = []
+
+    def __call__(self, thing):
+        self.string = self.sanitizer(thing)
+        return self
+
+    def __eq__(self, other):
+        a = self.string
+        b = _strip_and_dedent(other)
+        if a == b:
+            return True
+        else:
+            self.explanation = _make_explanation(a.splitlines(), b.splitlines())
+            return False
+
+
+def _sanitize_general(s):
+    s = s.strip()
+    s = s.replace("pybind11_tests.", "m.")
+    s = s.replace("unicode", "str")
+    s = _long_marker.sub(r"\1", s)
+    s = _unicode_marker.sub(r"\1", s)
+    return s
+
+
+def _sanitize_docstring(thing):
+    s = thing.__doc__
+    s = _sanitize_general(s)
+    return s
+
+
+@pytest.fixture
+def doc():
+    """Sanitize docstrings and add custom failure explanation"""
+    return SanitizedString(_sanitize_docstring)
+
+
+def _sanitize_message(thing):
+    s = str(thing)
+    s = _sanitize_general(s)
+    s = _hexadecimal.sub("0", s)
+    return s
+
+
+@pytest.fixture
+def msg():
+    """Sanitize messages and add custom failure explanation"""
+    return SanitizedString(_sanitize_message)
+
+
+# noinspection PyUnusedLocal
+def pytest_assertrepr_compare(op, left, right):
+    """Hook to insert custom failure explanation"""
+    if hasattr(left, 'explanation'):
+        return left.explanation
+
+
+@contextlib.contextmanager
+def suppress(exception):
+    """Suppress the desired exception"""
+    try:
+        yield
+    except exception:
+        pass
+
+
+def pytest_namespace():
+    """Add import suppression and test requirements to `pytest` namespace"""
+    try:
+        import numpy as np
+    except ImportError:
+        np = None
+    try:
+        import scipy
+    except ImportError:
+        scipy = None
+    try:
+        from pybind11_tests import have_eigen
+    except ImportError:
+        have_eigen = False
+
+    skipif = pytest.mark.skipif
+    return {
+        'suppress': suppress,
+        'requires_numpy': skipif(not np, reason="numpy is not installed"),
+        'requires_scipy': skipif(not np, reason="scipy is not installed"),
+        'requires_eigen_and_numpy': skipif(not have_eigen or not np,
+                                           reason="eigen and/or numpy are not installed"),
+        'requires_eigen_and_scipy': skipif(not have_eigen or not scipy,
+                                           reason="eigen and/or scipy are not installed"),
+    }
diff --git a/example/constructor-stats.h b/tests/constructor_stats.h
similarity index 97%
rename from example/constructor-stats.h
rename to tests/constructor_stats.h
index 0f505c1..757ebf9 100644
--- a/example/constructor-stats.h
+++ b/tests/constructor_stats.h
@@ -1,6 +1,6 @@
 #pragma once
 /*
-    example/constructor-stats.h -- framework for printing and tracking object
+    tests/constructor_stats.h -- framework for printing and tracking object
     instance lifetimes in example/test code.
 
     Copyright (c) 2016 Jason Rhinelander <jason@imaginary.ca>
@@ -64,7 +64,7 @@
 
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include <unordered_map>
 #include <list>
 #include <typeindex>
@@ -117,9 +117,12 @@
         _values.push_back(oss.str());
         value(std::forward<Tmore>(args)...);
     }
+
+    // Move out stored values
     py::list values() {
         py::list l;
         for (const auto &v : _values) l.append(py::cast(v));
+        _values.clear();
         return l;
     }
 
diff --git a/example/object.h b/tests/object.h
similarity index 98%
rename from example/object.h
rename to tests/object.h
index 4e6fa6e..99a6916 100644
--- a/example/object.h
+++ b/tests/object.h
@@ -2,7 +2,7 @@
 #define __OBJECT_H
 
 #include <atomic>
-#include "constructor-stats.h"
+#include "constructor_stats.h"
 
 /// Reference counted object base class
 class Object {
diff --git a/example/example.cpp b/tests/pybind11_tests.cpp
similarity index 87%
rename from example/example.cpp
rename to tests/pybind11_tests.cpp
index bd6ac9b..507ede8 100644
--- a/example/example.cpp
+++ b/tests/pybind11_tests.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example.cpp -- pybind example plugin
+    tests/pybind11_tests.cpp -- pybind example plugin
 
     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"
 
 void init_ex_methods_and_attributes(py::module &);
 void init_ex_python_types(py::module &);
@@ -49,8 +49,8 @@
         ;
 }
 
-PYBIND11_PLUGIN(example) {
-    py::module m("example", "pybind example plugin");
+PYBIND11_PLUGIN(pybind11_tests) {
+    py::module m("pybind11_tests", "pybind example plugin");
 
     bind_ConstructorStats(m);
 
@@ -76,9 +76,12 @@
     init_ex_numpy_dtypes(m);
     init_issues(m);
 
-    #if defined(PYBIND11_TEST_EIGEN)
-        init_eigen(m);
-    #endif
+#if defined(PYBIND11_TEST_EIGEN)
+    init_eigen(m);
+    m.attr("have_eigen") = py::cast(true);
+#else
+    m.attr("have_eigen") = py::cast(false);
+#endif
 
     return m.ptr();
 }
diff --git a/example/example.h b/tests/pybind11_tests.h
similarity index 100%
rename from example/example.h
rename to tests/pybind11_tests.h
diff --git a/example/example-buffers.cpp b/tests/test_buffers.cpp
similarity index 96%
rename from example/example-buffers.cpp
rename to tests/test_buffers.cpp
index fa3178b..5a4dc67 100644
--- a/example/example-buffers.cpp
+++ b/tests/test_buffers.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-buffers.cpp -- supporting Pythons' buffer protocol
+    tests/test_buffers.cpp -- supporting Pythons' buffer protocol
 
     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"
 
 class Matrix {
 public:
diff --git a/tests/test_buffers.py b/tests/test_buffers.py
new file mode 100644
index 0000000..f0ea964
--- /dev/null
+++ b/tests/test_buffers.py
@@ -0,0 +1,57 @@
+import pytest
+from pybind11_tests import Matrix, ConstructorStats
+
+with pytest.suppress(ImportError):
+    import numpy as np
+
+
+@pytest.requires_numpy
+def test_to_python():
+    m = Matrix(5, 5)
+
+    assert m[2, 3] == 0
+    m[2, 3] = 4
+    assert m[2, 3] == 4
+
+    m2 = np.array(m, copy=False)
+    assert m2.shape == (5, 5)
+    assert abs(m2).sum() == 4
+    assert m2[2, 3] == 4
+    m2[2, 3] = 5
+    assert m2[2, 3] == 5
+
+    cstats = ConstructorStats.get(Matrix)
+    assert cstats.alive() == 1
+    del m
+    assert cstats.alive() == 1
+    del m2  # holds an m reference
+    assert cstats.alive() == 0
+    assert cstats.values() == ["5x5 matrix"]
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0  # Don't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+
+@pytest.requires_numpy
+def test_from_python():
+    with pytest.raises(RuntimeError) as excinfo:
+        Matrix(np.array([1, 2, 3]))  # trying to assign a 1D array
+    assert str(excinfo.value) == "Incompatible buffer format!"
+
+    m3 = np.array([[1, 2, 3], [4, 5, 6]]).astype(np.float32)
+    m4 = Matrix(m3)
+
+    for i in range(m4.rows()):
+        for j in range(m4.cols()):
+            assert m3[i, j] == m4[i, j]
+
+    cstats = ConstructorStats.get(Matrix)
+    assert cstats.alive() == 1
+    del m3, m4
+    assert cstats.alive() == 0
+    assert cstats.values() == ["2x3 matrix"]
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0  # Don't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
diff --git a/example/example-callbacks.cpp b/tests/test_callbacks.cpp
similarity index 95%
rename from example/example-callbacks.cpp
rename to tests/test_callbacks.cpp
index a5a3b83..80a0d0e 100644
--- a/example/example-callbacks.cpp
+++ b/tests/test_callbacks.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-callbacks.cpp -- callbacks
+    tests/test_callbacks.cpp -- callbacks
 
     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>
 
 
diff --git a/tests/test_callbacks.py b/tests/test_callbacks.py
new file mode 100644
index 0000000..3f70e87
--- /dev/null
+++ b/tests/test_callbacks.py
@@ -0,0 +1,130 @@
+import pytest
+
+
+def test_inheritance(capture, msg):
+    from pybind11_tests import Pet, Dog, Rabbit, dog_bark, pet_print
+
+    roger = Rabbit('Rabbit')
+    assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
+    with capture:
+        pet_print(roger)
+    assert capture == "Rabbit is a parrot"
+
+    polly = Pet('Polly', 'parrot')
+    assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
+    with capture:
+        pet_print(polly)
+    assert capture == "Polly is a parrot"
+
+    molly = Dog('Molly')
+    assert molly.name() + " is a " + molly.species() == "Molly is a dog"
+    with capture:
+        pet_print(molly)
+    assert capture == "Molly is a dog"
+
+    with capture:
+        dog_bark(molly)
+    assert capture == "Woof!"
+
+    with pytest.raises(TypeError) as excinfo:
+        dog_bark(polly)
+    assert msg(excinfo.value) == """
+        Incompatible function arguments. The following argument types are supported:
+            1. (arg0: m.Dog) -> None
+            Invoked with: <m.Pet object at 0>
+    """
+
+
+def test_callbacks(capture):
+    from functools import partial
+    from pybind11_tests import (test_callback1, test_callback2, test_callback3,
+                                test_callback4, test_callback5)
+
+    def func1():
+        print('Callback function 1 called!')
+
+    def func2(a, b, c, d):
+        print('Callback function 2 called : {}, {}, {}, {}'.format(a, b, c, d))
+        return d
+
+    def func3(a):
+        print('Callback function 3 called : {}'.format(a))
+
+    with capture:
+        assert test_callback1(func1) is False
+    assert capture == "Callback function 1 called!"
+    with capture:
+        assert test_callback2(func2) == 5
+    assert capture == "Callback function 2 called : Hello, x, True, 5"
+    with capture:
+        assert test_callback1(partial(func2, "Hello", "from", "partial", "object")) is False
+    assert capture == "Callback function 2 called : Hello, from, partial, object"
+    with capture:
+        assert test_callback1(partial(func3, "Partial object with one argument")) is False
+    assert capture == "Callback function 3 called : Partial object with one argument"
+    with capture:
+        test_callback3(lambda i: i + 1)
+    assert capture == "func(43) = 44"
+
+    f = test_callback4()
+    assert f(43) == 44
+    f = test_callback5()
+    assert f(number=43) == 44
+
+
+def test_lambda_closure_cleanup():
+    from pybind11_tests import test_cleanup, payload_cstats
+
+    test_cleanup()
+    cstats = payload_cstats()
+    assert cstats.alive() == 0
+    assert cstats.copy_constructions == 1
+    assert cstats.move_constructions >= 1
+
+
+def test_cpp_function_roundtrip(capture):
+    """Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
+    from pybind11_tests import dummy_function, dummy_function2, test_dummy_function, roundtrip
+
+    with capture:
+        test_dummy_function(dummy_function)
+    assert capture == """
+        argument matches dummy_function
+        eval(1) = 2
+    """
+    with capture:
+        test_dummy_function(roundtrip(dummy_function))
+    assert capture == """
+        roundtrip..
+        argument matches dummy_function
+        eval(1) = 2
+    """
+    with capture:
+        assert roundtrip(None) is None
+    assert capture == "roundtrip (got None).."
+    with capture:
+        test_dummy_function(lambda x: x + 2)
+    assert capture == """
+        could not convert to a function pointer.
+        eval(1) = 3
+    """
+
+    with capture:
+        with pytest.raises(TypeError) as excinfo:
+            test_dummy_function(dummy_function2)
+        assert "Incompatible function arguments" in str(excinfo.value)
+    assert capture == "could not convert to a function pointer."
+
+    with capture:
+        with pytest.raises(TypeError) as excinfo:
+            test_dummy_function(lambda x, y: x + y)
+        assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument",
+                                                     "takes exactly 2 arguments"))
+    assert capture == "could not convert to a function pointer."
+
+
+def test_function_signatures(doc):
+    from pybind11_tests import test_callback3, test_callback4
+
+    assert doc(test_callback3) == "test_callback3(arg0: Callable[[int], int]) -> None"
+    assert doc(test_callback4) == "test_callback4() -> Callable[[int], int]"
diff --git a/example/example-constants-and-functions.cpp b/tests/test_constants_and_functions.cpp
similarity index 93%
rename from example/example-constants-and-functions.cpp
rename to tests/test_constants_and_functions.cpp
index d7f8ad1..1977a0a 100644
--- a/example/example-constants-and-functions.cpp
+++ b/tests/test_constants_and_functions.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-constants-and-functions.cpp -- global constants and functions, enumerations, raw byte strings
+    tests/test_constants_and_functions.cpp -- global constants and functions, enumerations, raw byte strings
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 enum EMyEnumeration {
     EFirstEntry = 1,
diff --git a/tests/test_constants_and_functions.py b/tests/test_constants_and_functions.py
new file mode 100644
index 0000000..119965b
--- /dev/null
+++ b/tests/test_constants_and_functions.py
@@ -0,0 +1,130 @@
+import pytest
+
+
+def test_constants():
+    from pybind11_tests import some_constant
+
+    assert some_constant == 14
+
+
+def test_function_overloading(capture):
+    from pybind11_tests import EMyEnumeration, test_function
+
+    with capture:
+        assert test_function() is False
+        assert test_function(7) == 3.5
+        assert test_function(EMyEnumeration.EFirstEntry) is None
+        assert test_function(EMyEnumeration.ESecondEntry) is None
+    assert capture == """
+        test_function()
+        test_function(7)
+        test_function(enum=1)
+        test_function(enum=2)
+    """
+
+
+def test_unscoped_enum():
+    from pybind11_tests import EMyEnumeration, EFirstEntry
+
+    assert str(EMyEnumeration.EFirstEntry) == "EMyEnumeration.EFirstEntry"
+    assert str(EMyEnumeration.ESecondEntry) == "EMyEnumeration.ESecondEntry"
+    assert str(EFirstEntry) == "EMyEnumeration.EFirstEntry"
+
+    # no TypeError exception for unscoped enum ==/!= int comparisons
+    y = EMyEnumeration.ESecondEntry
+    assert y == 2
+    assert y != 3
+
+    assert int(EMyEnumeration.ESecondEntry) == 2
+    assert str(EMyEnumeration(2)) == "EMyEnumeration.ESecondEntry"
+
+
+def test_scoped_enum(capture):
+    from pybind11_tests import ECMyEnum, test_ecenum
+
+    with capture:
+        test_ecenum(ECMyEnum.Three)
+    assert capture == "test_ecenum(ECMyEnum::Three)"
+    z = ECMyEnum.Two
+    with capture:
+        test_ecenum(z)
+    assert capture == "test_ecenum(ECMyEnum::Two)"
+
+    # expected TypeError exceptions for scoped enum ==/!= int comparisons
+    with pytest.raises(TypeError):
+        assert z == 2
+    with pytest.raises(TypeError):
+        assert z != 3
+
+
+def test_implicit_conversion(capture):
+    from pybind11_tests import ExampleWithEnum
+
+    assert str(ExampleWithEnum.EMode.EFirstMode) == "EMode.EFirstMode"
+    assert str(ExampleWithEnum.EFirstMode) == "EMode.EFirstMode"
+
+    f = ExampleWithEnum.test_function
+    first = ExampleWithEnum.EFirstMode
+    second = ExampleWithEnum.ESecondMode
+
+    with capture:
+        f(first)
+    assert capture == "ExampleWithEnum::test_function(enum=1)"
+
+    with capture:
+        assert f(first) == f(first)
+        assert not f(first) != f(first)
+
+        assert f(first) != f(second)
+        assert not f(first) == f(second)
+
+        assert f(first) == int(f(first))
+        assert not f(first) != int(f(first))
+
+        assert f(first) != int(f(second))
+        assert not f(first) == int(f(second))
+    assert capture == """
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+    """
+
+    with capture:
+        # noinspection PyDictCreation
+        x = {f(first): 1, f(second): 2}
+        x[f(first)] = 3
+        x[f(second)] = 4
+    assert capture == """
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+        ExampleWithEnum::test_function(enum=1)
+        ExampleWithEnum::test_function(enum=2)
+    """
+    # Hashing test
+    assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
+
+
+def test_bytes(capture):
+    from pybind11_tests import return_bytes, print_bytes
+
+    with capture:
+        print_bytes(return_bytes())
+    assert capture == """
+        bytes[0]=1
+        bytes[1]=0
+        bytes[2]=2
+        bytes[3]=0
+    """
diff --git a/example/eigen.cpp b/tests/test_eigen.cpp
similarity index 97%
rename from example/eigen.cpp
rename to tests/test_eigen.cpp
index c88bee2..42bb969 100644
--- a/example/eigen.cpp
+++ b/tests/test_eigen.cpp
@@ -1,5 +1,5 @@
 /*
-    example/eigen.cpp -- automatic conversion of Eigen types
+    tests/eigen.cpp -- automatic conversion of Eigen types
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include <pybind11/eigen.h>
 #include <Eigen/Cholesky>
 
diff --git a/tests/test_eigen.py b/tests/test_eigen.py
new file mode 100644
index 0000000..43cc2fb
--- /dev/null
+++ b/tests/test_eigen.py
@@ -0,0 +1,136 @@
+import pytest
+
+with pytest.suppress(ImportError):
+    import numpy as np
+
+
+ref = np.array([[ 0,  3,  0,  0,  0, 11],
+                [22,  0,  0,  0, 17, 11],
+                [ 7,  5,  0,  1,  0, 11],
+                [ 0,  0,  0,  0,  0, 11],
+                [ 0,  0, 14,  0,  8, 11]])
+
+
+def assert_equal_ref(mat):
+    np.testing.assert_array_equal(mat, ref)
+
+
+def assert_sparse_equal_ref(sparse_mat):
+    assert_equal_ref(sparse_mat.todense())
+
+
+@pytest.requires_eigen_and_numpy
+def test_fixed():
+    from pybind11_tests import fixed_r, fixed_c, fixed_passthrough_r, fixed_passthrough_c
+
+    assert_equal_ref(fixed_c())
+    assert_equal_ref(fixed_r())
+    assert_equal_ref(fixed_passthrough_r(fixed_r()))
+    assert_equal_ref(fixed_passthrough_c(fixed_c()))
+    assert_equal_ref(fixed_passthrough_r(fixed_c()))
+    assert_equal_ref(fixed_passthrough_c(fixed_r()))
+
+
+@pytest.requires_eigen_and_numpy
+def test_dense():
+    from pybind11_tests import dense_r, dense_c, dense_passthrough_r, dense_passthrough_c
+
+    assert_equal_ref(dense_r())
+    assert_equal_ref(dense_c())
+    assert_equal_ref(dense_passthrough_r(dense_r()))
+    assert_equal_ref(dense_passthrough_c(dense_c()))
+    assert_equal_ref(dense_passthrough_r(dense_c()))
+    assert_equal_ref(dense_passthrough_c(dense_r()))
+
+
+@pytest.requires_eigen_and_numpy
+def test_nonunit_stride_from_python():
+    from pybind11_tests import double_row, double_col, double_mat_cm, double_mat_rm
+
+    counting_mat = np.arange(9.0, dtype=np.float32).reshape((3, 3))
+    first_row = counting_mat[0, :]
+    first_col = counting_mat[:, 0]
+    assert np.array_equal(double_row(first_row), 2.0 * first_row)
+    assert np.array_equal(double_col(first_row), 2.0 * first_row)
+    assert np.array_equal(double_row(first_col), 2.0 * first_col)
+    assert np.array_equal(double_col(first_col), 2.0 * first_col)
+
+    counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
+    slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
+    for slice_idx, ref_mat in enumerate(slices):
+        assert np.array_equal(double_mat_cm(ref_mat), 2.0 * ref_mat)
+        assert np.array_equal(double_mat_rm(ref_mat), 2.0 * ref_mat)
+
+
+@pytest.requires_eigen_and_numpy
+def test_nonunit_stride_to_python():
+    from pybind11_tests import diagonal, diagonal_1, diagonal_n, block
+
+    assert np.all(diagonal(ref) == ref.diagonal())
+    assert np.all(diagonal_1(ref) == ref.diagonal(1))
+    for i in range(-5, 7):
+        assert np.all(diagonal_n(ref, i) == ref.diagonal(i)), "diagonal_n({})".format(i)
+
+    assert np.all(block(ref, 2, 1, 3, 3) == ref[2:5, 1:4])
+    assert np.all(block(ref, 1, 4, 4, 2) == ref[1:, 4:])
+    assert np.all(block(ref, 1, 4, 3, 2) == ref[1:4, 4:])
+
+
+@pytest.requires_eigen_and_numpy
+def test_eigen_ref_to_python():
+    from pybind11_tests import cholesky1, cholesky2, cholesky3, cholesky4, cholesky5, cholesky6
+
+    chols = [cholesky1, cholesky2, cholesky3, cholesky4, cholesky5, cholesky6]
+    for i, chol in enumerate(chols, start=1):
+        mymat = chol(np.array([[1, 2, 4], [2, 13, 23], [4, 23, 77]]))
+        assert np.all(mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])), "cholesky{}".format(i)
+
+
+@pytest.requires_eigen_and_numpy
+def test_special_matrix_objects():
+    from pybind11_tests import incr_diag, symmetric_upper, symmetric_lower
+
+    assert np.all(incr_diag(7) == np.diag([1, 2, 3, 4, 5, 6, 7]))
+
+    asymm = np.array([[ 1,  2,  3,  4],
+                      [ 5,  6,  7,  8],
+                      [ 9, 10, 11, 12],
+                      [13, 14, 15, 16]])
+    symm_lower = np.array(asymm)
+    symm_upper = np.array(asymm)
+    for i in range(4):
+        for j in range(i + 1, 4):
+            symm_lower[i, j] = symm_lower[j, i]
+            symm_upper[j, i] = symm_upper[i, j]
+
+    assert np.all(symmetric_lower(asymm) == symm_lower)
+    assert np.all(symmetric_upper(asymm) == symm_upper)
+
+
+@pytest.requires_eigen_and_numpy
+def test_dense_signature(doc):
+    from pybind11_tests import double_col, double_row, double_mat_rm
+
+    assert doc(double_col) == "double_col(arg0: numpy.ndarray[float32[m, 1]]) -> numpy.ndarray[float32[m, 1]]"
+    assert doc(double_row) == "double_row(arg0: numpy.ndarray[float32[1, n]]) -> numpy.ndarray[float32[1, n]]"
+    assert doc(double_mat_rm) == "double_mat_rm(arg0: numpy.ndarray[float32[m, n]]) -> numpy.ndarray[float32[m, n]]"
+
+
+@pytest.requires_eigen_and_scipy
+def test_sparse():
+    from pybind11_tests import sparse_r, sparse_c, sparse_passthrough_r, sparse_passthrough_c
+
+    assert_sparse_equal_ref(sparse_r())
+    assert_sparse_equal_ref(sparse_c())
+    assert_sparse_equal_ref(sparse_passthrough_r(sparse_r()))
+    assert_sparse_equal_ref(sparse_passthrough_c(sparse_c()))
+    assert_sparse_equal_ref(sparse_passthrough_r(sparse_c()))
+    assert_sparse_equal_ref(sparse_passthrough_c(sparse_r()))
+
+
+@pytest.requires_eigen_and_scipy
+def test_sparse_signature(doc):
+    from pybind11_tests import sparse_passthrough_r, sparse_passthrough_c
+
+    assert doc(sparse_passthrough_r) == "sparse_passthrough_r(arg0: scipy.sparse.csr_matrix[float32]) -> scipy.sparse.csr_matrix[float32]"
+    assert doc(sparse_passthrough_c) == "sparse_passthrough_c(arg0: scipy.sparse.csc_matrix[float32]) -> scipy.sparse.csc_matrix[float32]"
diff --git a/example/example-eval.cpp b/tests/test_eval.cpp
similarity index 90%
rename from example/example-eval.cpp
rename to tests/test_eval.cpp
index f6de893..21098ac 100644
--- a/example/example-eval.cpp
+++ b/tests/test_eval.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-eval.cpp -- Usage of eval() and eval_file()
+    tests/test_eval.cpp -- Usage of eval() and eval_file()
 
     Copyright (c) 2016 Klemens D. Morgenstern
 
@@ -9,7 +9,7 @@
 
 
 #include <pybind11/eval.h>
-#include "example.h"
+#include "pybind11_tests.h"
 
 void example_eval() {
     py::module main_module = py::module::import("__main__");
@@ -59,9 +59,9 @@
     main_module.def("call_test2", [&](int value) {val_out = value;});
 
     try {
-        result = py::eval_file("example-eval_call.py", main_namespace);
+        result = py::eval_file("test_eval_call.py", main_namespace);
     } catch (...) {
-        result = py::eval_file("example/example-eval_call.py", main_namespace);
+        result = py::eval_file("tests/test_eval_call.py", main_namespace);
     }
 
     if (val_out == 42 && result == py::none())
diff --git a/tests/test_eval.py b/tests/test_eval.py
new file mode 100644
index 0000000..2d7611c
--- /dev/null
+++ b/tests/test_eval.py
@@ -0,0 +1,22 @@
+
+
+def test_eval(capture):
+    from pybind11_tests import example_eval
+
+    with capture:
+        example_eval()
+    assert capture == """
+        eval_statements test
+        Hello World!
+        eval_statements passed
+        eval test
+        eval passed
+        eval_single_statement test
+        eval_single_statement passed
+        eval_file test
+        eval_file passed
+        eval failure test
+        eval failure test passed
+        eval_file failure test
+        eval_file failure test passed
+    """
diff --git a/tests/test_eval_call.py b/tests/test_eval_call.py
new file mode 100644
index 0000000..b8a7603
--- /dev/null
+++ b/tests/test_eval_call.py
@@ -0,0 +1,4 @@
+# This file is called from 'test_eval.py'
+
+if 'call_test2' in globals():
+    call_test2(y)
diff --git a/example/example-custom-exceptions.cpp b/tests/test_exceptions.cpp
similarity index 96%
rename from example/example-custom-exceptions.cpp
rename to tests/test_exceptions.cpp
index 41d51d8..492308f 100644
--- a/example/example-custom-exceptions.cpp
+++ b/tests/test_exceptions.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-custom-exceptions.cpp -- exception translation
+    tests/test_custom-exceptions.cpp -- exception translation
 
     Copyright (c) 2016 Pim Schellart <P.Schellart@princeton.edu>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 // A type that should be raised as an exeption in Python
 class MyException : public std::exception {
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
new file mode 100644
index 0000000..24f9769
--- /dev/null
+++ b/tests/test_exceptions.py
@@ -0,0 +1,31 @@
+import pytest
+
+
+def test_custom(msg):
+    from pybind11_tests import (MyException, throws1, throws2, throws3, throws4,
+                                throws_logic_error)
+
+    # Can we catch a MyException?"
+    with pytest.raises(MyException) as excinfo:
+        throws1()
+    assert msg(excinfo.value) == "this error should go to a custom type"
+
+    # Can we translate to standard Python exceptions?
+    with pytest.raises(RuntimeError) as excinfo:
+        throws2()
+    assert msg(excinfo.value) == "this error should go to a standard Python exception"
+
+    # Can we handle unknown exceptions?
+    with pytest.raises(RuntimeError) as excinfo:
+        throws3()
+    assert msg(excinfo.value) == "Caught an unknown exception!"
+
+    # Can we delegate to another handler by rethrowing?
+    with pytest.raises(MyException) as excinfo:
+        throws4()
+    assert msg(excinfo.value) == "this error is rethrown"
+
+    # "Can we fall-through to the default handler?"
+    with pytest.raises(RuntimeError) as excinfo:
+        throws_logic_error()
+    assert msg(excinfo.value) == "this error should fall through to the standard handler"
diff --git a/example/example-inheritance.cpp b/tests/test_inheritance.cpp
similarity index 94%
rename from example/example-inheritance.cpp
rename to tests/test_inheritance.cpp
index 082978b..b70ea77 100644
--- a/example/example-inheritance.cpp
+++ b/tests/test_inheritance.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-inheritance.cpp -- inheritance, automatic upcasting for polymorphic types
+    tests/test_inheritance.cpp -- inheritance, automatic upcasting for polymorphic types
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 class Pet {
 public:
diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py
new file mode 100644
index 0000000..a7a9778
--- /dev/null
+++ b/tests/test_inheritance.py
@@ -0,0 +1,8 @@
+
+
+def test_automatic_upcasting():
+    from pybind11_tests import return_class_1, return_class_2, return_none
+
+    assert type(return_class_1()).__name__ == "DerivedClass1"
+    assert type(return_class_2()).__name__ == "DerivedClass2"
+    assert type(return_none()).__name__ == "NoneType"
diff --git a/example/issues.cpp b/tests/test_issues.cpp
similarity index 97%
rename from example/issues.cpp
rename to tests/test_issues.cpp
index 7dfa9f5..085dff9 100644
--- a/example/issues.cpp
+++ b/tests/test_issues.cpp
@@ -1,5 +1,5 @@
 /*
-    example/issues.cpp -- collection of testcases for miscellaneous issues
+    tests/test_issues.cpp -- collection of testcases for miscellaneous issues
 
     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/stl.h>
 #include <pybind11/operators.h>
 
diff --git a/tests/test_issues.py b/tests/test_issues.py
new file mode 100644
index 0000000..0ab2e36
--- /dev/null
+++ b/tests/test_issues.py
@@ -0,0 +1,176 @@
+import pytest
+import gc
+
+
+def test_regressions(capture):
+    from pybind11_tests.issues import print_cchar, print_char
+
+    with capture:
+        print_cchar("const char *")  # #137: const char* isn't handled properly
+    assert capture == "const char *"
+    with capture:
+        print_char("c")  # #150: char bindings broken
+    assert capture == "c"
+
+
+def test_dispatch_issue(capture, msg):
+    """#159: virtual function dispatch has problems with similar-named functions"""
+    from pybind11_tests.issues import DispatchIssue, dispatch_issue_go
+
+    class PyClass1(DispatchIssue):
+        def dispatch(self):
+            print("Yay..")
+
+    class PyClass2(DispatchIssue):
+        def dispatch(self):
+            with pytest.raises(RuntimeError) as excinfo:
+                super(PyClass2, self).dispatch()
+            assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"'
+
+            p = PyClass1()
+            dispatch_issue_go(p)
+
+    b = PyClass2()
+    with capture:
+        dispatch_issue_go(b)
+    assert capture == "Yay.."
+
+
+def test_reference_wrapper():
+    """#171: Can't return reference wrappers (or STL data structures containing them)"""
+    from pybind11_tests.issues import Placeholder, return_vec_of_reference_wrapper
+
+    assert str(return_vec_of_reference_wrapper(Placeholder(4))) == \
+        "[Placeholder[1], Placeholder[2], Placeholder[3], Placeholder[4]]"
+
+
+def test_iterator_passthrough():
+    """#181: iterator passthrough did not compile"""
+    from pybind11_tests.issues import iterator_passthrough
+
+    assert list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))) == [3, 5, 7, 9, 11, 13, 15]
+
+
+def test_shared_ptr_gc():
+    """// #187: issue involving std::shared_ptr<> return value policy & garbage collection"""
+    from pybind11_tests.issues import ElementList, ElementA
+
+    el = ElementList()
+    for i in range(10):
+        el.add(ElementA(i))
+    gc.collect()
+    for i, v in enumerate(el.get()):
+        assert i == v.value()
+
+
+def test_no_id(capture, msg):
+    from pybind11_tests.issues import print_element, expect_float, expect_int
+
+    with pytest.raises(TypeError) as excinfo:
+        print_element(None)
+    assert msg(excinfo.value) == """
+        Incompatible function arguments. The following argument types are supported:
+            1. (arg0: m.issues.ElementA) -> None
+            Invoked with: None
+    """
+
+    with pytest.raises(TypeError) as excinfo:
+        expect_int(5.2)
+    assert msg(excinfo.value) == """
+        Incompatible function arguments. The following argument types are supported:
+            1. (arg0: int) -> int
+            Invoked with: 5.2
+    """
+    assert expect_float(12) == 12
+
+    from pybind11_tests.issues import A, call_f
+
+    class B(A):
+        def __init__(self):
+            super(B, self).__init__()
+
+        def f(self):
+            print("In python f()")
+
+    # C++ version
+    with capture:
+        a = A()
+        call_f(a)
+    assert capture == "A.f()"
+
+    # Python version
+    with capture:
+        b = B()
+        call_f(b)
+    assert capture == """
+        PyA.PyA()
+        PyA.f()
+        In python f()
+    """
+
+
+def test_str_issue(capture, msg):
+    """Issue #283: __str__ called on uninitialized instance when constructor arguments invalid"""
+    from pybind11_tests.issues import StrIssue
+
+    with capture:
+        assert str(StrIssue(3)) == "StrIssue[3]"
+    assert capture == "StrIssue.__str__ called"
+
+    with pytest.raises(TypeError) as excinfo:
+        str(StrIssue("no", "such", "constructor"))
+    assert msg(excinfo.value) == """
+        Incompatible constructor arguments. The following argument types are supported:
+            1. m.issues.StrIssue(arg0: int)
+            2. m.issues.StrIssue()
+            Invoked with: no, such, constructor
+    """
+
+
+def test_nested(capture):
+    """ #328: first member in a class can't be used in operators"""
+    from pybind11_tests.issues import NestA, NestB, NestC, print_NestA, print_NestB, print_NestC
+
+    a = NestA()
+    b = NestB()
+    c = NestC()
+
+    a += 10
+    b.a += 100
+    c.b.a += 1000
+    b -= 1
+    c.b -= 3
+    c *= 7
+
+    with capture:
+        print_NestA(a)
+        print_NestA(b.a)
+        print_NestA(c.b.a)
+        print_NestB(b)
+        print_NestB(c.b)
+        print_NestC(c)
+    assert capture == """
+        13
+        103
+        1003
+        3
+        1
+        35
+    """
+
+    abase = a.as_base()
+    assert abase.value == -2
+    a.as_base().value += 44
+    assert abase.value == 42
+    assert c.b.a.as_base().value == -2
+    c.b.a.as_base().value += 44
+    assert c.b.a.as_base().value == 42
+
+    del c
+    gc.collect()
+    del a  # Should't delete while abase is still alive
+    gc.collect()
+
+    assert abase.value == 42
+    del abase, b
+    gc.collect()
diff --git a/example/example-keep-alive.cpp b/tests/test_keep_alive.cpp
similarity index 92%
rename from example/example-keep-alive.cpp
rename to tests/test_keep_alive.cpp
index c2aeaee..25f852e 100644
--- a/example/example-keep-alive.cpp
+++ b/tests/test_keep_alive.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-keep-alive.cpp -- keep_alive modifier (pybind11's version
+    tests/test_keep_alive.cpp -- keep_alive modifier (pybind11's version
     of Boost.Python's with_custodian_and_ward / with_custodian_and_ward_postcall)
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,7 +8,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 class Child {
 public:
diff --git a/tests/test_keep_alive.py b/tests/test_keep_alive.py
new file mode 100644
index 0000000..c83d5d2
--- /dev/null
+++ b/tests/test_keep_alive.py
@@ -0,0 +1,98 @@
+import gc
+
+
+def test_keep_alive_argument(capture):
+    from pybind11_tests import Parent, Child
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.addChild(Child())
+        gc.collect()
+    assert capture == """
+        Allocating child.
+        Releasing child.
+    """
+    with capture:
+        del p
+        gc.collect()
+    assert capture == "Releasing parent."
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.addChildKeepAlive(Child())
+        gc.collect()
+    assert capture == "Allocating child."
+    with capture:
+        del p
+        gc.collect()
+    assert capture == """
+        Releasing parent.
+        Releasing child.
+    """
+
+
+def test_keep_alive_return_value(capture):
+    from pybind11_tests import Parent
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.returnChild()
+        gc.collect()
+    assert capture == """
+        Allocating child.
+        Releasing child.
+    """
+    with capture:
+        del p
+        gc.collect()
+    assert capture == "Releasing parent."
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.returnChildKeepAlive()
+        gc.collect()
+    assert capture == "Allocating child."
+    with capture:
+        del p
+        gc.collect()
+    assert capture == """
+        Releasing parent.
+        Releasing child.
+    """
+
+
+def test_return_none(capture):
+    from pybind11_tests import Parent
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.returnNullChildKeepAliveChild()
+        gc.collect()
+    assert capture == ""
+    with capture:
+        del p
+        gc.collect()
+    assert capture == "Releasing parent."
+
+    with capture:
+        p = Parent()
+    assert capture == "Allocating parent."
+    with capture:
+        p.returnNullChildKeepAliveParent()
+        gc.collect()
+    assert capture == ""
+    with capture:
+        del p
+        gc.collect()
+    assert capture == "Releasing parent."
+
diff --git a/example/example-arg-keywords-and-defaults.cpp b/tests/test_kwargs_and_defaults.cpp
similarity index 94%
rename from example/example-arg-keywords-and-defaults.cpp
rename to tests/test_kwargs_and_defaults.cpp
index 9c58605..2816246 100644
--- a/example/example-arg-keywords-and-defaults.cpp
+++ b/tests/test_kwargs_and_defaults.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-arg-keywords-and-defaults.cpp -- keyword arguments and default values
+    tests/test_kwargs_and_defaults.cpp -- keyword arguments and default values
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include <pybind11/stl.h>
 
 void kw_func(int x, int y) { std::cout << "kw_func(x=" << x << ", y=" << y << ")" << std::endl; }
diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py
new file mode 100644
index 0000000..0d785a4
--- /dev/null
+++ b/tests/test_kwargs_and_defaults.py
@@ -0,0 +1,93 @@
+import pytest
+from pybind11_tests import (kw_func0, kw_func1, kw_func2, kw_func3, kw_func4, call_kw_func,
+                            args_function, args_kwargs_function, kw_func_udl, kw_func_udl_z,
+                            KWClass)
+
+
+def test_function_signatures(doc):
+    assert doc(kw_func0) == "kw_func0(arg0: int, arg1: int) -> None"
+    assert doc(kw_func1) == "kw_func1(x: int, y: int) -> None"
+    assert doc(kw_func2) == "kw_func2(x: int=100, y: int=200) -> None"
+    assert doc(kw_func3) == "kw_func3(data: str='Hello world!') -> None"
+    assert doc(kw_func4) == "kw_func4(myList: List[int]=[13, 17]) -> None"
+    assert doc(kw_func_udl) == "kw_func_udl(x: int, y: int=300) -> None"
+    assert doc(kw_func_udl_z) == "kw_func_udl_z(x: int, y: int=0) -> None"
+    assert doc(args_function) == "args_function(*args) -> None"
+    assert doc(args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> None"
+    assert doc(KWClass.foo0) == "foo0(self: m.KWClass, arg0: int, arg1: float) -> None"
+    assert doc(KWClass.foo1) == "foo1(self: m.KWClass, x: int, y: float) -> None"
+
+
+def test_named_arguments(capture, msg):
+    with capture:
+        kw_func1(5, 10)
+    assert capture == "kw_func(x=5, y=10)"
+    with capture:
+        kw_func1(5, y=10)
+    assert capture == "kw_func(x=5, y=10)"
+    with capture:
+        kw_func1(y=10, x=5)
+    assert capture == "kw_func(x=5, y=10)"
+
+    with capture:
+        kw_func2()
+    assert capture == "kw_func(x=100, y=200)"
+    with capture:
+        kw_func2(5)
+    assert capture == "kw_func(x=5, y=200)"
+    with capture:
+        kw_func2(x=5)
+    assert capture == "kw_func(x=5, y=200)"
+    with capture:
+        kw_func2(y=10)
+    assert capture == "kw_func(x=100, y=10)"
+    with capture:
+        kw_func2(5, 10)
+    assert capture == "kw_func(x=5, y=10)"
+    with capture:
+        kw_func2(x=5, y=10)
+    assert capture == "kw_func(x=5, y=10)"
+
+    with pytest.raises(TypeError) as excinfo:
+        # noinspection PyArgumentList
+        kw_func2(x=5, y=10, z=12)
+    assert msg(excinfo.value) == """
+        Incompatible function arguments. The following argument types are supported:
+            1. (x: int=100, y: int=200) -> None
+            Invoked with:
+    """
+
+    with capture:
+        kw_func4()
+    assert capture == "kw_func4: 13 17"
+    with capture:
+        kw_func4(myList=[1, 2, 3])
+    assert capture == "kw_func4: 1 2 3"
+
+    with capture:
+        kw_func_udl(x=5, y=10)
+    assert capture == "kw_func(x=5, y=10)"
+    with capture:
+        kw_func_udl_z(x=5)
+    assert capture == "kw_func(x=5, y=0)"
+
+
+def test_arg_and_kwargs(capture):
+    with capture:
+        call_kw_func(kw_func2)
+    assert capture == "kw_func(x=1234, y=5678)"
+    with capture:
+        args_function('arg1_value', 'arg2_value', 3)
+    assert capture.unordered == """
+        got argument: arg1_value
+        got argument: arg2_value
+        got argument: 3
+    """
+    with capture:
+        args_kwargs_function('arg1_value', 'arg2_value', arg3='arg3_value', arg4=4)
+    assert capture.unordered == """
+        got argument: arg1_value
+        got argument: arg2_value
+        got keyword argument: arg3 -> arg3_value
+        got keyword argument: arg4 -> 4
+    """
diff --git a/example/example-methods-and-attributes.cpp b/tests/test_methods_and_attributes.cpp
similarity index 95%
rename from example/example-methods-and-attributes.cpp
rename to tests/test_methods_and_attributes.cpp
index 9056e3c..9317d78 100644
--- a/example/example-methods-and-attributes.cpp
+++ b/tests/test_methods_and_attributes.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-methods-and-attributes.cpp -- constructors, deconstructors, attribute access,
+    tests/test_methods_and_attributes.cpp -- constructors, deconstructors, attribute access,
     __str__, argument and return value conventions
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,8 +8,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"
 
 class ExampleMandA {
 public:
diff --git a/tests/test_methods_and_attributes.py b/tests/test_methods_and_attributes.py
new file mode 100644
index 0000000..9340e6f
--- /dev/null
+++ b/tests/test_methods_and_attributes.py
@@ -0,0 +1,46 @@
+from pybind11_tests import ExampleMandA, ConstructorStats
+
+
+def test_methods_and_attributes():
+    instance1 = ExampleMandA()
+    instance2 = ExampleMandA(32)
+
+    instance1.add1(instance2)
+    instance1.add2(instance2)
+    instance1.add3(instance2)
+    instance1.add4(instance2)
+    instance1.add5(instance2)
+    instance1.add6(32)
+    instance1.add7(32)
+    instance1.add8(32)
+    instance1.add9(32)
+    instance1.add10(32)
+
+    assert str(instance1) == "ExampleMandA[value=320]"
+    assert str(instance2) == "ExampleMandA[value=32]"
+    assert str(instance1.self1()) == "ExampleMandA[value=320]"
+    assert str(instance1.self2()) == "ExampleMandA[value=320]"
+    assert str(instance1.self3()) == "ExampleMandA[value=320]"
+    assert str(instance1.self4()) == "ExampleMandA[value=320]"
+    assert str(instance1.self5()) == "ExampleMandA[value=320]"
+
+    assert instance1.internal1() == 320
+    assert instance1.internal2() == 320
+    assert instance1.internal3() == 320
+    assert instance1.internal4() == 320
+    assert instance1.internal5() == 320
+
+    assert instance1.value == 320
+    instance1.value = 100
+    assert str(instance1) == "ExampleMandA[value=100]"
+
+    cstats = ConstructorStats.get(ExampleMandA)
+    assert cstats.alive() == 2
+    del instance1, instance2
+    assert cstats.alive() == 0
+    assert cstats.values() == ["32"]
+    assert cstats.default_constructions == 1
+    assert cstats.copy_constructions == 3
+    assert cstats.move_constructions >= 1
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
diff --git a/example/example-modules.cpp b/tests/test_modules.cpp
similarity index 92%
rename from example/example-modules.cpp
rename to tests/test_modules.cpp
index bd25af1..3d96df6 100644
--- a/example/example-modules.cpp
+++ b/tests/test_modules.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-modules.cpp -- nested modules, importing modules, and
+    tests/test_modules.cpp -- nested modules, importing modules, and
                             internal references
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,8 +8,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"
 
 void submodule_func() {
     std::cout << "submodule_func()" << std::endl;
diff --git a/tests/test_modules.py b/tests/test_modules.py
new file mode 100644
index 0000000..3deb02e
--- /dev/null
+++ b/tests/test_modules.py
@@ -0,0 +1,56 @@
+
+def test_nested_modules(capture):
+    import pybind11_tests
+    from pybind11_tests.submodule import submodule_func
+
+    assert pybind11_tests.__name__ == "pybind11_tests"
+    assert pybind11_tests.submodule.__name__ == "pybind11_tests.submodule"
+
+    with capture:
+        submodule_func()
+    assert capture == "submodule_func()"
+
+
+def test_reference_internal():
+    from pybind11_tests import ConstructorStats
+    from pybind11_tests.submodule import A, B
+
+    b = B()
+    assert str(b.get_a1()) == "A[1]"
+    assert str(b.a1) == "A[1]"
+    assert str(b.get_a2()) == "A[2]"
+    assert str(b.a2) == "A[2]"
+
+    b.a1 = A(42)
+    b.a2 = A(43)
+    assert str(b.get_a1()) == "A[42]"
+    assert str(b.a1) == "A[42]"
+    assert str(b.get_a2()) == "A[43]"
+    assert str(b.a2) == "A[43]"
+
+    astats, bstats = ConstructorStats.get(A), ConstructorStats.get(B)
+    assert astats.alive() == 2
+    assert bstats.alive() == 1
+    del b
+    assert astats.alive() == 0
+    assert bstats.alive() == 0
+    assert astats.values() == ['1', '2', '42', '43']
+    assert bstats.values() == []
+    assert astats.default_constructions == 0
+    assert bstats.default_constructions == 1
+    assert astats.copy_constructions == 0
+    assert bstats.copy_constructions == 0
+    # assert astats.move_constructions >= 0  # Don't invoke any
+    # assert bstats.move_constructions >= 0  # Don't invoke any
+    assert astats.copy_assignments == 2
+    assert bstats.copy_assignments == 0
+    assert astats.move_assignments == 0
+    assert bstats.move_assignments == 0
+
+
+def test_importing():
+    from pybind11_tests import OD
+    from collections import OrderedDict
+
+    assert OD is OrderedDict
+    assert str(OD([(1, 'a'), (2, 'b')])) == "OrderedDict([(1, 'a'), (2, 'b')])"
diff --git a/example/example-numpy-dtypes.cpp b/tests/test_numpy_dtypes.cpp
similarity index 97%
rename from example/example-numpy-dtypes.cpp
rename to tests/test_numpy_dtypes.cpp
index e5292bb..9afd342 100644
--- a/example/example-numpy-dtypes.cpp
+++ b/tests/test_numpy_dtypes.cpp
@@ -1,5 +1,5 @@
 /*
-  example/example-numpy-dtypes.cpp -- Structured and compound NumPy dtypes
+  tests/test_numpy_dtypes.cpp -- Structured and compound NumPy dtypes
 
   Copyright (c) 2016 Ivan Smirnov
 
@@ -7,11 +7,9 @@
   BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 #include <pybind11/numpy.h>
-#include <cstdint>
-#include <iostream>
 
 #ifdef __GNUC__
 #define PYBIND11_PACKED(cls) cls __attribute__((__packed__))
diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py
new file mode 100644
index 0000000..783f6ad
--- /dev/null
+++ b/tests/test_numpy_dtypes.py
@@ -0,0 +1,169 @@
+import pytest
+with pytest.suppress(ImportError):
+    import numpy as np
+
+
+def assert_equal(actual, expected_data, expected_dtype):
+    np.testing.assert_equal(actual, np.array(expected_data, dtype=expected_dtype))
+
+simple_dtype = np.dtype({'names': ['x', 'y', 'z'],
+                         'formats': ['?', 'u4', 'f4'],
+                         'offsets': [0, 4, 8]})
+packed_dtype = np.dtype([('x', '?'), ('y', 'u4'), ('z', 'f4')])
+
+
+@pytest.requires_numpy
+def test_format_descriptors(capture):
+    from pybind11_tests import get_format_unbound, print_format_descriptors
+
+    with pytest.raises(RuntimeError) as excinfo:
+        get_format_unbound()
+    assert 'unsupported buffer format' in str(excinfo.value)
+
+    with capture:
+        print_format_descriptors()
+    assert capture == """
+        T{=?:x:3x=I:y:=f:z:}
+        T{=?:x:=I:y:=f:z:}
+        T{=T{=?:x:3x=I:y:=f:z:}:a:=T{=?:x:=I:y:=f:z:}:b:}
+        T{=?:x:3x=I:y:=f:z:12x}
+        T{8x=T{=?:x:3x=I:y:=f:z:12x}:a:8x}
+        T{=3s:a:=3s:b:}
+    """
+
+
+@pytest.requires_numpy
+def test_dtype(capture):
+    from pybind11_tests import print_dtypes, test_dtype_ctors, test_dtype_methods
+
+    with capture:
+        print_dtypes()
+    assert capture == """
+        {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}
+        [('x', '?'), ('y', '<u4'), ('z', '<f4')]
+        [('a', {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':12}), ('b', [('x', '?'), ('y', '<u4'), ('z', '<f4')])]
+        {'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}
+        {'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}
+        [('a', 'S3'), ('b', 'S3')]
+    """
+
+    d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
+                   'offsets': [1, 10], 'itemsize': 20})
+    d2 = np.dtype([('a', 'i4'), ('b', 'f4')])
+    assert test_dtype_ctors() == [np.dtype('int32'), np.dtype('float64'),
+                                  np.dtype('bool'), d1, d1, np.dtype('uint32'), d2]
+
+    assert test_dtype_methods() == [np.dtype('int32'), simple_dtype, False, True,
+                                    np.dtype('int32').itemsize, simple_dtype.itemsize]
+
+
+@pytest.requires_numpy
+def test_recarray(capture):
+    from pybind11_tests import (create_rec_simple, create_rec_packed, create_rec_nested,
+                                print_rec_simple, print_rec_packed, print_rec_nested,
+                                create_rec_partial, create_rec_partial_nested)
+
+    elements = [(False, 0, 0.0), (True, 1, 1.5), (False, 2, 3.0)]
+
+    for func, dtype in [(create_rec_simple, simple_dtype), (create_rec_packed, packed_dtype)]:
+        arr = func(0)
+        assert arr.dtype == dtype
+        assert_equal(arr, [], simple_dtype)
+        assert_equal(arr, [], packed_dtype)
+
+        arr = func(3)
+        assert arr.dtype == dtype
+        assert_equal(arr, elements, simple_dtype)
+        assert_equal(arr, elements, packed_dtype)
+
+        if dtype == simple_dtype:
+            with capture:
+                print_rec_simple(arr)
+            assert capture == """
+                s:0,0,0
+                s:1,1,1.5
+                s:0,2,3
+            """
+        else:
+            with capture:
+                print_rec_packed(arr)
+            assert capture == """
+                p:0,0,0
+                p:1,1,1.5
+                p:0,2,3
+            """
+
+    nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)])
+
+    arr = create_rec_nested(0)
+    assert arr.dtype == nested_dtype
+    assert_equal(arr, [], nested_dtype)
+
+    arr = create_rec_nested(3)
+    assert arr.dtype == nested_dtype
+    assert_equal(arr, [((False, 0, 0.0), (True, 1, 1.5)),
+                       ((True, 1, 1.5), (False, 2, 3.0)),
+                       ((False, 2, 3.0), (True, 3, 4.5))], nested_dtype)
+    with capture:
+        print_rec_nested(arr)
+    assert capture == """
+        n:a=s:0,0,0;b=p:1,1,1.5
+        n:a=s:1,1,1.5;b=p:0,2,3
+        n:a=s:0,2,3;b=p:1,3,4.5
+    """
+
+    arr = create_rec_partial(3)
+    assert str(arr.dtype) == "{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}"
+    partial_dtype = arr.dtype
+    assert '' not in arr.dtype.fields
+    assert partial_dtype.itemsize > simple_dtype.itemsize
+    assert_equal(arr, elements, simple_dtype)
+    assert_equal(arr, elements, packed_dtype)
+
+    arr = create_rec_partial_nested(3)
+    assert str(arr.dtype) == "{'names':['a'], 'formats':[{'names':['x','y','z'], 'formats':['?','<u4','<f4'], 'offsets':[0,4,8], 'itemsize':24}], 'offsets':[8], 'itemsize':40}"
+    assert '' not in arr.dtype.fields
+    assert '' not in arr.dtype.fields['a'][0].fields
+    assert arr.dtype.itemsize > partial_dtype.itemsize
+    np.testing.assert_equal(arr['a'], create_rec_partial(3))
+
+
+@pytest.requires_numpy
+def test_array_constructors():
+    from pybind11_tests import test_array_ctors
+
+    data = np.arange(1, 7, dtype='int32')
+    for i in range(8):
+        np.testing.assert_array_equal(test_array_ctors(10 + i), data.reshape((3, 2)))
+        np.testing.assert_array_equal(test_array_ctors(20 + i), data.reshape((3, 2)))
+    for i in range(5):
+        np.testing.assert_array_equal(test_array_ctors(30 + i), data)
+        np.testing.assert_array_equal(test_array_ctors(40 + i), data)
+
+
+@pytest.requires_numpy
+def test_string_array(capture):
+    from pybind11_tests import create_string_array, print_string_array
+
+    arr = create_string_array(True)
+    assert str(arr.dtype) == "[('a', 'S3'), ('b', 'S3')]"
+    with capture:
+        print_string_array(arr)
+    assert capture == """
+        a='',b=''
+        a='a',b='a'
+        a='ab',b='ab'
+        a='abc',b='abc'
+    """
+    dtype = arr.dtype
+    assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc']
+    assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc']
+    arr = create_string_array(False)
+    assert dtype == arr.dtype
+
+
+@pytest.requires_numpy
+def test_signature(doc):
+    from pybind11_tests import create_rec_nested
+
+    assert doc(create_rec_nested) == "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]"
diff --git a/example/example-numpy-vectorize.cpp b/tests/test_numpy_vectorize.cpp
similarity index 84%
rename from example/example-numpy-vectorize.cpp
rename to tests/test_numpy_vectorize.cpp
index 8780d28..a36b7d0 100644
--- a/example/example-numpy-vectorize.cpp
+++ b/tests/test_numpy_vectorize.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-numpy-vectorize.cpp -- auto-vectorize functions over NumPy array
+    tests/test_numpy_vectorize.cpp -- auto-vectorize functions over NumPy array
     arguments
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,7 +8,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include <pybind11/numpy.h>
 
 double my_func(int x, float y, double z) {
@@ -35,7 +35,7 @@
     m.def("vectorized_func3", py::vectorize(my_func3));
 
     /// Numpy function which only accepts specific data types
-    m.def("selective_func", [](py::array_t<int, py::array::c_style>) { std::cout << "Int branch taken. "<< std::endl; });
-    m.def("selective_func", [](py::array_t<float, py::array::c_style>) { std::cout << "Float branch taken. "<< std::endl; });
-    m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { std::cout << "Complex float branch taken. "<< std::endl; });
+    m.def("selective_func", [](py::array_t<int, py::array::c_style>) { std::cout << "Int branch taken." << std::endl; });
+    m.def("selective_func", [](py::array_t<float, py::array::c_style>) { std::cout << "Float branch taken." << std::endl; });
+    m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { std::cout << "Complex float branch taken." << std::endl; });
 }
diff --git a/tests/test_numpy_vectorize.py b/tests/test_numpy_vectorize.py
new file mode 100644
index 0000000..6fcf808
--- /dev/null
+++ b/tests/test_numpy_vectorize.py
@@ -0,0 +1,80 @@
+import pytest
+
+with pytest.suppress(ImportError):
+    import numpy as np
+
+
+@pytest.requires_numpy
+def test_vectorize(capture):
+    from pybind11_tests import vectorized_func, vectorized_func2, vectorized_func3
+
+    assert np.isclose(vectorized_func3(np.array(3 + 7j)), [6 + 14j])
+
+    for f in [vectorized_func, vectorized_func2]:
+        with capture:
+            assert np.isclose(f(1, 2, 3), 6)
+        assert capture == "my_func(x:int=1, y:float=2, z:float=3)"
+        with capture:
+            assert np.isclose(f(np.array(1), np.array(2), 3), 6)
+        assert capture == "my_func(x:int=1, y:float=2, z:float=3)"
+        with capture:
+            assert np.allclose(f(np.array([1, 3]), np.array([2, 4]), 3), [6, 36])
+        assert capture == """
+            my_func(x:int=1, y:float=2, z:float=3)
+            my_func(x:int=3, y:float=4, z:float=3)
+        """
+        with capture:
+            a, b, c = np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3
+            assert np.allclose(f(a, b, c), a * b * c)
+        assert capture == """
+            my_func(x:int=1, y:float=2, z:float=3)
+            my_func(x:int=3, y:float=4, z:float=3)
+            my_func(x:int=5, y:float=6, z:float=3)
+            my_func(x:int=7, y:float=8, z:float=3)
+            my_func(x:int=9, y:float=10, z:float=3)
+            my_func(x:int=11, y:float=12, z:float=3)
+        """
+        with capture:
+            a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2
+            assert np.allclose(f(a, b, c), a * b * c)
+        assert capture == """
+            my_func(x:int=1, y:float=2, z:float=2)
+            my_func(x:int=2, y:float=3, z:float=2)
+            my_func(x:int=3, y:float=4, z:float=2)
+            my_func(x:int=4, y:float=2, z:float=2)
+            my_func(x:int=5, y:float=3, z:float=2)
+            my_func(x:int=6, y:float=4, z:float=2)
+        """
+        with capture:
+            a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2
+            assert np.allclose(f(a, b, c), a * b * c)
+        assert capture == """
+            my_func(x:int=1, y:float=2, z:float=2)
+            my_func(x:int=2, y:float=2, z:float=2)
+            my_func(x:int=3, y:float=2, z:float=2)
+            my_func(x:int=4, y:float=3, z:float=2)
+            my_func(x:int=5, y:float=3, z:float=2)
+            my_func(x:int=6, y:float=3, z:float=2)
+        """
+
+
+@pytest.requires_numpy
+def test_type_selection(capture):
+    from pybind11_tests import selective_func
+
+    with capture:
+        selective_func(np.array([1], dtype=np.int32))
+        selective_func(np.array([1.0], dtype=np.float32))
+        selective_func(np.array([1.0j], dtype=np.complex64))
+    assert capture == """
+        Int branch taken.
+        Float branch taken.
+        Complex float branch taken.
+    """
+
+
+@pytest.requires_numpy
+def test_docs(doc):
+    from pybind11_tests import vectorized_func
+
+    assert doc(vectorized_func) == "vectorized_func(arg0: numpy.ndarray[int], arg1: numpy.ndarray[float], arg2: numpy.ndarray[float]) -> object"
diff --git a/example/example-opaque-types.cpp b/tests/test_opaque_types.cpp
similarity index 88%
rename from example/example-opaque-types.cpp
rename to tests/test_opaque_types.cpp
index 2c24f35..0ede5e3 100644
--- a/example/example-opaque-types.cpp
+++ b/tests/test_opaque_types.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-opaque-types.cpp -- opaque types, passing void pointers
+    tests/test_opaque_types.cpp -- opaque types, passing void pointers
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include <pybind11/stl.h>
 #include <vector>
 
@@ -50,9 +50,9 @@
     });
 
     m.def("return_void_ptr", []() { return (void *) 0x1234; });
-    m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::endl; });
+    m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : 0x" << std::hex << (uint64_t) ptr << std::dec << std::endl; });
     m.def("return_null_str", []() { return (char *) nullptr; });
-    m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::endl; });
+    m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : 0x" << std::hex << (uint64_t) ptr << std::dec << std::endl; });
 
     m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
         StringList *result = new StringList();
diff --git a/tests/test_opaque_types.py b/tests/test_opaque_types.py
new file mode 100644
index 0000000..5c2ca92
--- /dev/null
+++ b/tests/test_opaque_types.py
@@ -0,0 +1,64 @@
+import pytest
+
+
+def test_string_list(capture):
+    from pybind11_tests import StringList, ClassWithSTLVecProperty, print_opaque_list
+
+    l = StringList()
+    l.push_back("Element 1")
+    l.push_back("Element 2")
+    with capture:
+        print_opaque_list(l)
+    assert capture == "Opaque list: [Element 1, Element 2]"
+    assert l.back() == "Element 2"
+
+    for i, k in enumerate(l, start=1):
+        assert k == "Element {}".format(i)
+    l.pop_back()
+    with capture:
+        print_opaque_list(l)
+    assert capture == "Opaque list: [Element 1]"
+
+    cvp = ClassWithSTLVecProperty()
+    with capture:
+        print_opaque_list(cvp.stringList)
+    assert capture == "Opaque list: []"
+
+    cvp.stringList = l
+    cvp.stringList.push_back("Element 3")
+    with capture:
+        print_opaque_list(cvp.stringList)
+    assert capture == "Opaque list: [Element 1, Element 3]"
+
+
+def test_pointers(capture, msg):
+    from pybind11_tests import (return_void_ptr, print_void_ptr, ExampleMandA,
+                                print_opaque_list, return_null_str, print_null_str,
+                                return_unique_ptr, ConstructorStats)
+
+    with capture:
+        print_void_ptr(return_void_ptr())
+    assert capture == "Got void ptr : 0x1234"
+    with capture:
+        print_void_ptr(ExampleMandA())  # Should also work for other C++ types
+    assert "Got void ptr" in capture
+    assert ConstructorStats.get(ExampleMandA).alive() == 0
+
+    with pytest.raises(TypeError) as excinfo:
+        print_void_ptr([1, 2, 3])  # This should not work
+    assert msg(excinfo.value) == """
+        Incompatible function arguments. The following argument types are supported:
+            1. (arg0: capsule) -> None
+            Invoked with: [1, 2, 3]
+    """
+
+    assert return_null_str() is None
+    with capture:
+        print_null_str(return_null_str())
+    assert capture == "Got null str : 0x0"
+
+    ptr = return_unique_ptr()
+    assert "StringList" in repr(ptr)
+    with capture:
+        print_opaque_list(ptr)
+    assert capture == "Opaque list: [some value]"
diff --git a/example/example-operator-overloading.cpp b/tests/test_operator_overloading.cpp
similarity index 95%
rename from example/example-operator-overloading.cpp
rename to tests/test_operator_overloading.cpp
index f6b9967..b84a5b8 100644
--- a/example/example-operator-overloading.cpp
+++ b/tests/test_operator_overloading.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-operator-overloading.cpp -- operator overloading
+    tests/test_operator_overloading.cpp -- operator overloading
 
     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/operators.h>
 
 class Vector2 {
diff --git a/tests/test_operator_overloading.py b/tests/test_operator_overloading.py
new file mode 100644
index 0000000..e0d4239
--- /dev/null
+++ b/tests/test_operator_overloading.py
@@ -0,0 +1,41 @@
+
+def test_operator_overloading():
+    from pybind11_tests import Vector2, Vector, ConstructorStats
+
+    v1 = Vector2(1, 2)
+    v2 = Vector(3, -1)
+    assert str(v1) == "[1.000000, 2.000000]"
+    assert str(v2) == "[3.000000, -1.000000]"
+
+    assert str(v1 + v2) == "[4.000000, 1.000000]"
+    assert str(v1 - v2) == "[-2.000000, 3.000000]"
+    assert str(v1 - 8) == "[-7.000000, -6.000000]"
+    assert str(v1 + 8) == "[9.000000, 10.000000]"
+    assert str(v1 * 8) == "[8.000000, 16.000000]"
+    assert str(v1 / 8) == "[0.125000, 0.250000]"
+    assert str(8 - v1) == "[7.000000, 6.000000]"
+    assert str(8 + v1) == "[9.000000, 10.000000]"
+    assert str(8 * v1) == "[8.000000, 16.000000]"
+    assert str(8 / v1) == "[8.000000, 4.000000]"
+
+    v1 += v2
+    v1 *= 2
+    assert str(v1) == "[8.000000, 2.000000]"
+
+    cstats = ConstructorStats.get(Vector2)
+    assert cstats.alive() == 2
+    del v1
+    assert cstats.alive() == 1
+    del v2
+    assert cstats.alive() == 0
+    assert cstats.values() == ['[1.000000, 2.000000]', '[3.000000, -1.000000]',
+                               '[4.000000, 1.000000]', '[-2.000000, 3.000000]',
+                               '[-7.000000, -6.000000]', '[9.000000, 10.000000]',
+                               '[8.000000, 16.000000]', '[0.125000, 0.250000]',
+                               '[7.000000, 6.000000]', '[9.000000, 10.000000]',
+                               '[8.000000, 16.000000]', '[8.000000, 4.000000]']
+    assert cstats.default_constructions == 0
+    assert cstats.copy_constructions == 0
+    assert cstats.move_constructions >= 10
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
diff --git a/example/example-pickling.cpp b/tests/test_pickling.cpp
similarity index 95%
rename from example/example-pickling.cpp
rename to tests/test_pickling.cpp
index b89f78a..4a48452 100644
--- a/example/example-pickling.cpp
+++ b/tests/test_pickling.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-pickling.cpp -- pickle support
+    tests/test_pickling.cpp -- pickle support
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 class Pickleable {
 public:
diff --git a/tests/test_pickling.py b/tests/test_pickling.py
new file mode 100644
index 0000000..f6e4c04
--- /dev/null
+++ b/tests/test_pickling.py
@@ -0,0 +1,18 @@
+try:
+    import cPickle as pickle  # Use cPickle on Python 2.7
+except ImportError:
+    import pickle
+
+from pybind11_tests import Pickleable
+
+
+def test_roundtrip():
+    p = Pickleable("test_value")
+    p.setExtra1(15)
+    p.setExtra2(48)
+
+    data = pickle.dumps(p, 2)  # Must use pickle protocol >= 2
+    p2 = pickle.loads(data)
+    assert p2.value() == p.value()
+    assert p2.extra1() == p.extra1()
+    assert p2.extra2() == p.extra2()
diff --git a/example/example-python-types.cpp b/tests/test_python_types.cpp
similarity index 97%
rename from example/example-python-types.cpp
rename to tests/test_python_types.cpp
index 55066a8..39e43eb 100644
--- a/example/example-python-types.cpp
+++ b/tests/test_python_types.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-python-types.cpp2 -- singleton design pattern, static functions and
+    tests/test_python_types.cpp -- singleton design pattern, static functions and
     variables, passing and interacting with Python types
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,8 +8,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/stl.h>
 
 #ifdef _WIN32
diff --git a/tests/test_python_types.py b/tests/test_python_types.py
new file mode 100644
index 0000000..3738d41
--- /dev/null
+++ b/tests/test_python_types.py
@@ -0,0 +1,220 @@
+import pytest
+
+from pybind11_tests import ExamplePythonTypes, ConstructorStats
+
+
+def test_static():
+    ExamplePythonTypes.value = 15
+    assert ExamplePythonTypes.value == 15
+    assert ExamplePythonTypes.value2 == 5
+
+    with pytest.raises(AttributeError) as excinfo:
+        ExamplePythonTypes.value2 = 15
+    assert str(excinfo.value) == "can't set attribute"
+
+
+def test_instance(capture):
+    with pytest.raises(TypeError) as excinfo:
+        ExamplePythonTypes()
+    assert str(excinfo.value) == "pybind11_tests.ExamplePythonTypes: No constructor defined!"
+
+    instance = ExamplePythonTypes.new_instance()
+
+    with capture:
+        dict_result = instance.get_dict()
+        dict_result['key2'] = 'value2'
+        instance.print_dict(dict_result)
+    assert capture.unordered == """
+        key: key, value=value
+        key: key2, value=value2
+    """
+    with capture:
+        dict_result = instance.get_dict_2()
+        dict_result['key2'] = 'value2'
+        instance.print_dict_2(dict_result)
+    assert capture.unordered == """
+        key: key, value=value
+        key: key2, value=value2
+    """
+    with capture:
+        set_result = instance.get_set()
+        set_result.add('key3')
+        instance.print_set(set_result)
+    assert capture.unordered == """
+        key: key1
+        key: key2
+        key: key3
+    """
+    with capture:
+        set_result = instance.get_set2()
+        set_result.add('key3')
+        instance.print_set_2(set_result)
+    assert capture.unordered == """
+        key: key1
+        key: key2
+        key: key3
+    """
+    with capture:
+        list_result = instance.get_list()
+        list_result.append('value2')
+        instance.print_list(list_result)
+    assert capture.unordered == """
+        Entry at positon 0: value
+        list item 0: overwritten
+        list item 1: value2
+    """
+    with capture:
+        list_result = instance.get_list_2()
+        list_result.append('value2')
+        instance.print_list_2(list_result)
+    assert capture.unordered == """
+        list item 0: value
+        list item 1: value2
+    """
+    array_result = instance.get_array()
+    assert array_result == ['array entry 1', 'array entry 2']
+    with capture:
+        instance.print_array(array_result)
+    assert capture.unordered == """
+        array item 0: array entry 1
+        array item 1: array entry 2
+    """
+    with pytest.raises(RuntimeError) as excinfo:
+        instance.throw_exception()
+    assert str(excinfo.value) == "This exception was intentionally thrown."
+
+    assert instance.pair_passthrough((True, "test")) == ("test", True)
+    assert instance.tuple_passthrough((True, "test", 5)) == (5, "test", True)
+
+    assert instance.get_bytes_from_string().decode() == "foo"
+    assert instance.get_bytes_from_str().decode() == "bar"
+    assert instance.get_str_from_string().encode().decode() == "baz"
+    assert instance.get_str_from_bytes().encode().decode() == "boo"
+
+    class A(object):
+        def __str__(self):
+            return "this is a str"
+
+        def __repr__(self):
+            return "this is a repr"
+
+    with capture:
+        instance.test_print(A())
+    assert capture == """
+        this is a str
+        this is a repr
+    """
+
+    cstats = ConstructorStats.get(ExamplePythonTypes)
+    assert cstats.alive() == 1
+    del instance
+    assert cstats.alive() == 0
+
+
+def test_docs(doc):
+    assert doc(ExamplePythonTypes) == "Example 2 documentation"
+    assert doc(ExamplePythonTypes.get_dict) == """
+        get_dict(self: m.ExamplePythonTypes) -> dict
+
+        Return a Python dictionary
+    """
+    assert doc(ExamplePythonTypes.get_dict_2) == """
+        get_dict_2(self: m.ExamplePythonTypes) -> Dict[str, str]
+
+        Return a C++ dictionary
+    """
+    assert doc(ExamplePythonTypes.get_list) == """
+        get_list(self: m.ExamplePythonTypes) -> list
+
+        Return a Python list
+    """
+    assert doc(ExamplePythonTypes.get_list_2) == """
+        get_list_2(self: m.ExamplePythonTypes) -> List[str]
+
+        Return a C++ list
+    """
+    assert doc(ExamplePythonTypes.get_dict) == """
+        get_dict(self: m.ExamplePythonTypes) -> dict
+
+        Return a Python dictionary
+    """
+    assert doc(ExamplePythonTypes.get_set) == """
+        get_set(self: m.ExamplePythonTypes) -> set
+
+        Return a Python set
+    """
+    assert doc(ExamplePythonTypes.get_set2) == """
+        get_set2(self: m.ExamplePythonTypes) -> Set[str]
+
+        Return a C++ set
+    """
+    assert doc(ExamplePythonTypes.get_array) == """
+        get_array(self: m.ExamplePythonTypes) -> List[str[2]]
+
+        Return a C++ array
+    """
+    assert doc(ExamplePythonTypes.print_dict) == """
+        print_dict(self: m.ExamplePythonTypes, arg0: dict) -> None
+
+        Print entries of a Python dictionary
+    """
+    assert doc(ExamplePythonTypes.print_dict_2) == """
+        print_dict_2(self: m.ExamplePythonTypes, arg0: Dict[str, str]) -> None
+
+        Print entries of a C++ dictionary
+    """
+    assert doc(ExamplePythonTypes.print_set) == """
+        print_set(self: m.ExamplePythonTypes, arg0: set) -> None
+
+        Print entries of a Python set
+    """
+    assert doc(ExamplePythonTypes.print_set_2) == """
+        print_set_2(self: m.ExamplePythonTypes, arg0: Set[str]) -> None
+
+        Print entries of a C++ set
+    """
+    assert doc(ExamplePythonTypes.print_list) == """
+        print_list(self: m.ExamplePythonTypes, arg0: list) -> None
+
+        Print entries of a Python list
+    """
+    assert doc(ExamplePythonTypes.print_list_2) == """
+        print_list_2(self: m.ExamplePythonTypes, arg0: List[str]) -> None
+
+        Print entries of a C++ list
+    """
+    assert doc(ExamplePythonTypes.print_array) == """
+        print_array(self: m.ExamplePythonTypes, arg0: List[str[2]]) -> None
+
+        Print entries of a C++ array
+    """
+    assert doc(ExamplePythonTypes.pair_passthrough) == """
+        pair_passthrough(self: m.ExamplePythonTypes, arg0: Tuple[bool, str]) -> Tuple[str, bool]
+
+        Return a pair in reversed order
+    """
+    assert doc(ExamplePythonTypes.tuple_passthrough) == """
+        tuple_passthrough(self: m.ExamplePythonTypes, arg0: Tuple[bool, str, int]) -> Tuple[int, str, bool]
+
+        Return a triple in reversed order
+    """
+    assert doc(ExamplePythonTypes.throw_exception) == """
+        throw_exception(self: m.ExamplePythonTypes) -> None
+
+        Throw an exception
+    """
+    assert doc(ExamplePythonTypes.new_instance) == """
+        new_instance() -> m.ExamplePythonTypes
+
+        Return an instance
+    """
+
+
+def test_module():
+    import pybind11_tests
+
+    assert pybind11_tests.__name__ == "pybind11_tests"
+    assert ExamplePythonTypes.__name__ == "ExamplePythonTypes"
+    assert ExamplePythonTypes.__module__ == "pybind11_tests"
+    assert ExamplePythonTypes.get_set.__name__ == "get_set"
+    assert ExamplePythonTypes.get_set.__module__ == "pybind11_tests"
diff --git a/example/example-sequences-and-iterators.cpp b/tests/test_sequences_and_iterators.cpp
similarity index 97%
rename from example/example-sequences-and-iterators.cpp
rename to tests/test_sequences_and_iterators.cpp
index 791a929..a92c6bf 100644
--- a/example/example-sequences-and-iterators.cpp
+++ b/tests/test_sequences_and_iterators.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-sequences-and-iterators.cpp -- supporting Pythons' sequence protocol, iterators,
+    tests/test_sequences_and_iterators.cpp -- supporting Pythons' sequence protocol, iterators,
     etc.
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,8 +8,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/operators.h>
 #include <pybind11/stl.h>
 
diff --git a/tests/test_sequences_and_iterators.py b/tests/test_sequences_and_iterators.py
new file mode 100644
index 0000000..a35dc58
--- /dev/null
+++ b/tests/test_sequences_and_iterators.py
@@ -0,0 +1,78 @@
+import pytest
+
+
+def isclose(a, b, rel_tol=1e-05, abs_tol=0.0):
+    """Like to math.isclose() from Python 3.5"""
+    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
+
+
+def allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0):
+    return all(isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list))
+
+
+def test_sequence():
+    from pybind11_tests import Sequence, ConstructorStats
+
+    cstats = ConstructorStats.get(Sequence)
+
+    s = Sequence(5)
+    assert cstats.values() == ['of size', '5']
+
+    assert "Sequence" in repr(s)
+    assert len(s) == 5
+    assert s[0] == 0 and s[3] == 0
+    assert 12.34 not in s
+    s[0], s[3] = 12.34, 56.78
+    assert 12.34 in s
+    assert isclose(s[0], 12.34) and isclose(s[3], 56.78)
+
+    rev = reversed(s)
+    assert cstats.values() == ['of size', '5']
+
+    rev2 = s[::-1]
+    assert cstats.values() == ['of size', '5']
+
+    expected = [0, 56.78, 0, 0, 12.34]
+    assert allclose(rev, expected)
+    assert allclose(rev2, expected)
+    assert rev == rev2
+
+    rev[0::2] = Sequence([2.0, 2.0, 2.0])
+    assert cstats.values() == ['of size', '3', 'from std::vector']
+
+    assert allclose(rev, [2, 56.78, 2, 0, 2])
+
+    assert cstats.alive() == 3
+    del s
+    assert cstats.alive() == 2
+    del rev
+    assert cstats.alive() == 1
+    del rev2
+    assert cstats.alive() == 0
+
+    assert cstats.values() == []
+    assert cstats.default_constructions == 0
+    assert cstats.copy_constructions == 0
+    assert cstats.move_constructions >= 1
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+
+def test_map_iterator():
+    from pybind11_tests import StringMap
+
+    m = StringMap({'hi': 'bye', 'black': 'white'})
+    assert m['hi'] == 'bye'
+    assert len(m) == 2
+    assert m['black'] == 'white'
+
+    with pytest.raises(KeyError):
+        assert m['orange']
+    m['orange'] = 'banana'
+    assert m['orange'] == 'banana'
+
+    expected = {'hi': 'bye', 'black': 'white', 'orange': 'banana'}
+    for k in m:
+        assert m[k] == expected[k]
+    for k, v in m.items():
+        assert v == expected[k]
diff --git a/example/example-smart-ptr.cpp b/tests/test_smart_ptr.cpp
similarity index 97%
rename from example/example-smart-ptr.cpp
rename to tests/test_smart_ptr.cpp
index c4dd2c8..46c83b3 100644
--- a/example/example-smart-ptr.cpp
+++ b/tests/test_smart_ptr.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-smart-ptr.cpp -- binding classes with custom reference counting,
+    tests/test_smart_ptr.cpp -- binding classes with custom reference counting,
     implicit conversions between types
 
     Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -8,7 +8,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 #include "object.h"
 
 /// Custom object with builtin reference counting (see 'object.h' for the implementation)
diff --git a/tests/test_smart_ptr.py b/tests/test_smart_ptr.py
new file mode 100644
index 0000000..ffc407d
--- /dev/null
+++ b/tests/test_smart_ptr.py
@@ -0,0 +1,115 @@
+from pybind11_tests import ConstructorStats
+
+
+def test_smart_ptr(capture):
+    # Object1
+    from pybind11_tests import (MyObject1, make_object_1, make_object_2,
+                                print_object_1, print_object_2, print_object_3, print_object_4)
+
+    for i, o in enumerate([make_object_1(), make_object_2(), MyObject1(3)], start=1):
+        assert o.getRefCount() == 1
+        with capture:
+            print_object_1(o)
+            print_object_2(o)
+            print_object_3(o)
+            print_object_4(o)
+        assert capture == "MyObject1[{i}]\n".format(i=i) * 4
+
+    from pybind11_tests import (make_myobject1_1, make_myobject1_2,
+                                print_myobject1_1, print_myobject1_2,
+                                print_myobject1_3, print_myobject1_4)
+
+    for i, o in enumerate([make_myobject1_1(), make_myobject1_2(), MyObject1(6), 7], start=4):
+        print(o)
+        with capture:
+            if not isinstance(o, int):
+                print_object_1(o)
+                print_object_2(o)
+                print_object_3(o)
+                print_object_4(o)
+            print_myobject1_1(o)
+            print_myobject1_2(o)
+            print_myobject1_3(o)
+            print_myobject1_4(o)
+        assert capture == "MyObject1[{i}]\n".format(i=i) * (4 if isinstance(o, int) else 8)
+
+    cstats = ConstructorStats.get(MyObject1)
+    assert cstats.alive() == 0
+    expected_values = ['MyObject1[{}]'.format(i) for i in range(1, 7)] + ['MyObject1[7]'] * 4
+    assert cstats.values() == expected_values
+    assert cstats.default_constructions == 0
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0 # Doesn't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+    # Object2
+    from pybind11_tests import (MyObject2, make_myobject2_1, make_myobject2_2,
+                                make_myobject3_1, make_myobject3_2,
+                                print_myobject2_1, print_myobject2_2,
+                                print_myobject2_3, print_myobject2_4)
+
+    for i, o in zip([8, 6, 7], [MyObject2(8), make_myobject2_1(), make_myobject2_2()]):
+        print(o)
+        with capture:
+            print_myobject2_1(o)
+            print_myobject2_2(o)
+            print_myobject2_3(o)
+            print_myobject2_4(o)
+        assert capture == "MyObject2[{i}]\n".format(i=i) * 4
+
+    cstats = ConstructorStats.get(MyObject2)
+    assert cstats.alive() == 1
+    o = None
+    assert cstats.alive() == 0
+    assert cstats.values() == ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]']
+    assert cstats.default_constructions == 0
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0 # Doesn't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+    # Object3
+    from pybind11_tests import (MyObject3, print_myobject3_1, print_myobject3_2,
+                                print_myobject3_3, print_myobject3_4)
+
+    for i, o in zip([9, 8, 9], [MyObject3(9), make_myobject3_1(), make_myobject3_2()]):
+        print(o)
+        with capture:
+            print_myobject3_1(o)
+            print_myobject3_2(o)
+            print_myobject3_3(o)
+            print_myobject3_4(o)
+        assert capture == "MyObject3[{i}]\n".format(i=i) * 4
+
+    cstats = ConstructorStats.get(MyObject3)
+    assert cstats.alive() == 1
+    o = None
+    assert cstats.alive() == 0
+    assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]']
+    assert cstats.default_constructions == 0
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0 # Doesn't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+    # Object and ref
+    from pybind11_tests import Object, cstats_ref
+
+    cstats = ConstructorStats.get(Object)
+    assert cstats.alive() == 0
+    assert cstats.values() == []
+    assert cstats.default_constructions == 10
+    assert cstats.copy_constructions == 0
+    # assert cstats.move_constructions >= 0 # Doesn't invoke any
+    assert cstats.copy_assignments == 0
+    assert cstats.move_assignments == 0
+
+    cstats = cstats_ref()
+    assert cstats.alive() == 0
+    assert cstats.values() == ['from pointer'] * 10
+    assert cstats.default_constructions == 30
+    assert cstats.copy_constructions == 12
+    # assert cstats.move_constructions >= 0 # Doesn't invoke any
+    assert cstats.copy_assignments == 30
+    assert cstats.move_assignments == 0
diff --git a/example/example-stl-binder-vector.cpp b/tests/test_stl_binders.cpp
similarity index 86%
rename from example/example-stl-binder-vector.cpp
rename to tests/test_stl_binders.cpp
index d02ed09..e2a44e1 100644
--- a/example/example-stl-binder-vector.cpp
+++ b/tests/test_stl_binders.cpp
@@ -1,5 +1,5 @@
 /*
-    example/example-stl-binder-vector.cpp -- Usage of stl_binders functions
+    tests/test_stl_binders.cpp -- Usage of stl_binders functions
 
     Copyright (c) 2016 Sergey Lyskov
 
@@ -7,7 +7,7 @@
     BSD-style license that can be found in the LICENSE file.
 */
 
-#include "example.h"
+#include "pybind11_tests.h"
 
 #include <pybind11/stl_bind.h>
 
diff --git a/tests/test_stl_binders.py b/tests/test_stl_binders.py
new file mode 100644
index 0000000..2aaaf3a
--- /dev/null
+++ b/tests/test_stl_binders.py
@@ -0,0 +1,53 @@
+
+
+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]"
diff --git a/example/example-virtual-functions.cpp b/tests/test_virtual_functions.cpp
similarity index 98%
rename from example/example-virtual-functions.cpp
rename to tests/test_virtual_functions.cpp
index b24925f..6ea7c2c 100644
--- a/example/example-virtual-functions.cpp
+++ b/tests/test_virtual_functions.cpp
@@ -1,5 +1,5 @@
 /*
-    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 */
diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py
new file mode 100644
index 0000000..f2efb6b
--- /dev/null
+++ b/tests/test_virtual_functions.py
@@ -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