Commit 52f4be89 authored by Jason Rhinelander's avatar Jason Rhinelander
Browse files

Make test initialization self-registering

Adding or removing tests is a little bit cumbersome currently: the test
needs to be added to CMakeLists.txt, the init function needs to be
predeclared in pybind11_tests.cpp, then called in the plugin
initialization.  While this isn't a big deal for tests that are being
committed, it's more of a hassle when working on some new feature or
test code for which I temporarily only care about building and linking
the test being worked on rather than the entire test suite.

This commit changes tests to self-register their initialization by
having each test initialize a local object (which stores the
initialization function in a static variable).  This makes changing the
set of tests being build easy: one only needs to add or comment out
test names in tests/CMakeLists.txt.

A couple other minor changes that go along with this:

- test_eigen.cpp is now included in the test list, then removed if eigen
  isn't available.  This lets you disable the eigen tests by commenting
  it out, just like all the other tests, but keeps the build working
  without eigen eigen isn't available.  (Also, if it's commented out, we
  don't even bother looking for and reporting the building with/without
  eigen status message).

- pytest is now invoked with all the built test names (with .cpp changed
  to .py) so that it doesn't try to run tests that weren't built.
parent 06d8de11
...@@ -24,7 +24,7 @@ private: ...@@ -24,7 +24,7 @@ private:
int m_extra2 = 0; int m_extra2 = 0;
}; };
void init_ex_pickling(py::module &m) { test_initializer pickling([](py::module &m) {
py::class_<Pickleable>(m, "Pickleable") py::class_<Pickleable>(m, "Pickleable")
.def(py::init<std::string>()) .def(py::init<std::string>())
.def("value", &Pickleable::value) .def("value", &Pickleable::value)
...@@ -48,4 +48,4 @@ void init_ex_pickling(py::module &m) { ...@@ -48,4 +48,4 @@ void init_ex_pickling(py::module &m) {
p.setExtra1(t[1].cast<int>()); p.setExtra1(t[1].cast<int>());
p.setExtra2(t[2].cast<int>()); p.setExtra2(t[2].cast<int>());
}); });
} });
...@@ -167,7 +167,7 @@ public: ...@@ -167,7 +167,7 @@ public:
int ExamplePythonTypes::value = 0; int ExamplePythonTypes::value = 0;
const int ExamplePythonTypes::value2 = 5; const int ExamplePythonTypes::value2 = 5;
void init_ex_python_types(py::module &m) { test_initializer python_types([](py::module &m) {
/* No constructor is explicitly defined below. An exception is raised when /* No constructor is explicitly defined below. An exception is raised when
trying to construct it directly from Python */ trying to construct it directly from Python */
py::class_<ExamplePythonTypes>(m, "ExamplePythonTypes", "Example 2 documentation") py::class_<ExamplePythonTypes>(m, "ExamplePythonTypes", "Example 2 documentation")
...@@ -197,4 +197,4 @@ void init_ex_python_types(py::module &m) { ...@@ -197,4 +197,4 @@ void init_ex_python_types(py::module &m) {
.def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member") .def_readwrite_static("value", &ExamplePythonTypes::value, "Static value member")
.def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)") .def_readonly_static("value2", &ExamplePythonTypes::value2, "Static value member (readonly)")
; ;
} });
...@@ -168,7 +168,7 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine ...@@ -168,7 +168,7 @@ bool operator==(const NonZeroIterator<std::pair<A, B>>& it, const NonZeroSentine
return !(*it).first || !(*it).second; return !(*it).first || !(*it).second;
} }
void init_ex_sequences_and_iterators(py::module &m) { test_initializer sequences_and_iterators([](py::module &m) {
py::class_<Sequence> seq(m, "Sequence"); py::class_<Sequence> seq(m, "Sequence");
...@@ -271,4 +271,4 @@ void init_ex_sequences_and_iterators(py::module &m) { ...@@ -271,4 +271,4 @@ void init_ex_sequences_and_iterators(py::module &m) {
On the actual Sequence object, the iterator would be constructed as follows: On the actual Sequence object, the iterator would be constructed as follows:
.def("__iter__", [](py::object s) { return PySequenceIterator(s.cast<const Sequence &>(), s); }) .def("__iter__", [](py::object s) { return PySequenceIterator(s.cast<const Sequence &>(), s); })
#endif #endif
} });
...@@ -105,7 +105,7 @@ void print_myobject3_2(std::shared_ptr<MyObject3> obj) { std::cout << obj->toStr ...@@ -105,7 +105,7 @@ void print_myobject3_2(std::shared_ptr<MyObject3> obj) { std::cout << obj->toStr
void print_myobject3_3(const std::shared_ptr<MyObject3> &obj) { std::cout << obj->toString() << std::endl; } void print_myobject3_3(const std::shared_ptr<MyObject3> &obj) { std::cout << obj->toString() << std::endl; }
void print_myobject3_4(const std::shared_ptr<MyObject3> *obj) { std::cout << (*obj)->toString() << std::endl; } void print_myobject3_4(const std::shared_ptr<MyObject3> *obj) { std::cout << (*obj)->toString() << std::endl; }
void init_ex_smart_ptr(py::module &m) { test_initializer smart_ptr([](py::module &m) {
py::class_<Object, ref<Object>> obj(m, "Object"); py::class_<Object, ref<Object>> obj(m, "Object");
obj.def("getRefCount", &Object::getRefCount); obj.def("getRefCount", &Object::getRefCount);
...@@ -147,4 +147,4 @@ void init_ex_smart_ptr(py::module &m) { ...@@ -147,4 +147,4 @@ void init_ex_smart_ptr(py::module &m) {
// Expose constructor stats for the ref type // Expose constructor stats for the ref type
m.def("cstats_ref", &ConstructorStats::get<ref_tag>); m.def("cstats_ref", &ConstructorStats::get<ref_tag>);
} });
...@@ -24,7 +24,7 @@ std::ostream & operator<<(std::ostream &s, El const&v) { ...@@ -24,7 +24,7 @@ std::ostream & operator<<(std::ostream &s, El const&v) {
return s; return s;
} }
void init_ex_stl_binder_vector(py::module &m) { test_initializer stl_binder_vector([](py::module &m) {
py::class_<El>(m, "El") py::class_<El>(m, "El")
.def(py::init<int>()); .def(py::init<int>());
...@@ -34,4 +34,4 @@ void init_ex_stl_binder_vector(py::module &m) { ...@@ -34,4 +34,4 @@ void init_ex_stl_binder_vector(py::module &m) {
py::bind_vector<El>(m, "VectorEl"); py::bind_vector<El>(m, "VectorEl");
py::bind_vector<std::vector<El>>(m, "VectorVectorEl"); py::bind_vector<std::vector<El>>(m, "VectorVectorEl");
} });
...@@ -283,7 +283,7 @@ void initialize_inherited_virtuals(py::module &m) { ...@@ -283,7 +283,7 @@ void initialize_inherited_virtuals(py::module &m) {
}; };
void init_ex_virtual_functions(py::module &m) { test_initializer virtual_functions([](py::module &m) {
/* Important: indicate the trampoline class PyExampleVirt using the third /* Important: indicate the trampoline class PyExampleVirt using the third
argument to py::class_. The second argument with the unique pointer argument to py::class_. The second argument with the unique pointer
is simply the default holder type used by pybind11. */ is simply the default holder type used by pybind11. */
...@@ -315,4 +315,4 @@ void init_ex_virtual_functions(py::module &m) { ...@@ -315,4 +315,4 @@ void init_ex_virtual_functions(py::module &m) {
m.def("cstats_debug", &ConstructorStats::get<ExampleVirt>); m.def("cstats_debug", &ConstructorStats::get<ExampleVirt>);
initialize_inherited_virtuals(m); initialize_inherited_virtuals(m);
} });
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment