Simplify more tests by replacing capture with assert
diff --git a/tests/test_issues.cpp b/tests/test_issues.cpp
index a0d1fd5..5f680eb 100644
--- a/tests/test_issues.cpp
+++ b/tests/test_issues.cpp
@@ -111,7 +111,7 @@
         });
 
     // (no id): should not be able to pass 'None' to a reference argument
-    m2.def("print_element", [](ElementA &el) { std::cout << el.value() << std::endl; });
+    m2.def("get_element", [](ElementA &el) { return el.value(); });
 
     // (no id): don't cast doubles to ints
     m2.def("expect_float", [](float f) { return f; });
@@ -160,10 +160,7 @@
     py::class_<StrIssue> si(m2, "StrIssue");
     si  .def(py::init<int>())
         .def(py::init<>())
-        .def("__str__", [](const StrIssue &si) {
-                std::cout << "StrIssue.__str__ called" << std::endl;
-                return "StrIssue[" + std::to_string(si.value()) + "]";
-                })
+        .def("__str__", [](const StrIssue &si) { return "StrIssue[" + std::to_string(si.value()) + "]"; })
         ;
 
     // Issue #328: first member in a class can't be used in operators
diff --git a/tests/test_issues.py b/tests/test_issues.py
index f768139..38a5324 100644
--- a/tests/test_issues.py
+++ b/tests/test_issues.py
@@ -60,13 +60,13 @@
 
 
 def test_no_id(capture, msg):
-    from pybind11_tests.issues import print_element, expect_float, expect_int
+    from pybind11_tests.issues import get_element, expect_float, expect_int
 
     with pytest.raises(TypeError) as excinfo:
-        print_element(None)
+        get_element(None)
     assert msg(excinfo.value) == """
         Incompatible function arguments. The following argument types are supported:
-            1. (arg0: m.issues.ElementA) -> None
+            1. (arg0: m.issues.ElementA) -> int
             Invoked with: None
     """
 
@@ -105,13 +105,11 @@
     """
 
 
-def test_str_issue(capture, msg):
+def test_str_issue(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"
+    assert str(StrIssue(3)) == "StrIssue[3]"
 
     with pytest.raises(TypeError) as excinfo:
         str(StrIssue("no", "such", "constructor"))
diff --git a/tests/test_kwargs_and_defaults.cpp b/tests/test_kwargs_and_defaults.cpp
index 3fefc79..349b7ea 100644
--- a/tests/test_kwargs_and_defaults.cpp
+++ b/tests/test_kwargs_and_defaults.cpp
@@ -27,18 +27,12 @@
     return f(*args, **kwargs);
 }
 
-void args_function(py::args args) {
-    for (size_t it=0; it<args.size(); ++it)
-        std::cout << "got argument: " << py::object(args[it]) << std::endl;
+py::tuple args_function(py::args args) {
+    return args;
 }
 
-void args_kwargs_function(py::args args, py::kwargs kwargs) {
-    for (auto item : args)
-        std::cout << "got argument: " << item << std::endl;
-    if (kwargs) {
-        for (auto item : kwargs)
-            std::cout << "got keyword argument: " << item.first << " -> " << item.second << std::endl;
-    }
+py::tuple args_kwargs_function(py::args args, py::kwargs kwargs) {
+    return py::make_tuple(args, kwargs);
 }
 
 struct KWClass {
diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py
index 735722d..14d9c5a 100644
--- a/tests/test_kwargs_and_defaults.py
+++ b/tests/test_kwargs_and_defaults.py
@@ -12,8 +12,8 @@
     assert doc(kw_func4) == "kw_func4(myList: List[int]=[13, 17]) -> str"
     assert doc(kw_func_udl) == "kw_func_udl(x: int, y: int=300) -> str"
     assert doc(kw_func_udl_z) == "kw_func_udl_z(x: int, y: int=0) -> str"
-    assert doc(args_function) == "args_function(*args) -> None"
-    assert doc(args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> None"
+    assert doc(args_function) == "args_function(*args) -> tuple"
+    assert doc(args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple"
     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"
 
@@ -48,20 +48,12 @@
     assert kw_func_udl_z(x=5) == "x=5, y=0"
 
 
-def test_arg_and_kwargs(capture):
+def test_arg_and_kwargs():
     assert call_kw_func(kw_func2) == "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
-    """
+
+    args = 'arg1_value', 'arg2_value', 3
+    assert args_function(*args) == args
+
+    args = 'a1', 'a2'
+    kwargs = dict(arg3='a3', arg4=4)
+    assert args_kwargs_function(*args, **kwargs) == (args, kwargs)
diff --git a/tests/test_virtual_functions.cpp b/tests/test_virtual_functions.cpp
index 6ea7c2c..1e2f0ed 100644
--- a/tests/test_virtual_functions.cpp
+++ b/tests/test_virtual_functions.cpp
@@ -91,7 +91,7 @@
     Movable(int a, int b) : value{a+b} { print_created(this, a, b); }
     Movable(const Movable &m) { value = m.value; print_copy_created(this); }
     Movable(Movable &&m) { value = std::move(m.value); print_move_created(this); }
-    int get_value() const { return value; }
+    std::string get_value() const { return std::to_string(value); }
     ~Movable() { print_destroyed(this); }
 private:
     int value;
@@ -102,8 +102,8 @@
     virtual NonCopyable get_noncopyable(int a, int b) { return NonCopyable(a, b); }
     virtual Movable get_movable(int a, int b) = 0;
 
-    void print_nc(int a, int b) { std::cout << get_noncopyable(a, b).get_value() << std::endl; }
-    void print_movable(int a, int b) { std::cout << get_movable(a, b).get_value() << std::endl; }
+    std::string print_nc(int a, int b) { return get_noncopyable(a, b).get_value(); }
+    std::string print_movable(int a, int b) { return get_movable(a, b).get_value(); }
 };
 class NCVirtTrampoline : public NCVirt {
     virtual NonCopyable get_noncopyable(int a, int b) {
@@ -138,9 +138,11 @@
 #define A_METHODS \
 public: \
     virtual int unlucky_number() = 0; \
-    virtual void say_something(unsigned times) { \
-        for (unsigned i = 0; i < times; i++) std::cout << "hi"; \
-        std::cout << std::endl; \
+    virtual std::string say_something(unsigned times) { \
+        std::string s = ""; \
+        for (unsigned i = 0; i < times; ++i) \
+            s += "hi"; \
+        return s; \
     }
 A_METHODS
 };
@@ -148,8 +150,8 @@
 #define B_METHODS \
 public: \
     int unlucky_number() override { return 13; } \
-    void say_something(unsigned times) override { \
-        std::cout << "B says hi " << times << " times" << std::endl; \
+    std::string say_something(unsigned times) override { \
+        return "B says hi " + std::to_string(times) + " times"; \
     } \
     virtual double lucky_number() { return 7.0; }
 B_METHODS
@@ -178,27 +180,27 @@
 public:
     using A_Repeat::A_Repeat;
     int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, A_Repeat, unlucky_number, ); }
-    void say_something(unsigned times) override { PYBIND11_OVERLOAD(void, A_Repeat, say_something, times); }
+    std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, A_Repeat, say_something, times); }
 };
 class PyB_Repeat : public B_Repeat {
 public:
     using B_Repeat::B_Repeat;
     int unlucky_number() override { PYBIND11_OVERLOAD(int, B_Repeat, unlucky_number, ); }
-    void say_something(unsigned times) override { PYBIND11_OVERLOAD(void, B_Repeat, say_something, times); }
+    std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, B_Repeat, say_something, times); }
     double lucky_number() override { PYBIND11_OVERLOAD(double, B_Repeat, lucky_number, ); }
 };
 class PyC_Repeat : public C_Repeat {
 public:
     using C_Repeat::C_Repeat;
     int unlucky_number() override { PYBIND11_OVERLOAD(int, C_Repeat, unlucky_number, ); }
-    void say_something(unsigned times) override { PYBIND11_OVERLOAD(void, C_Repeat, say_something, times); }
+    std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, C_Repeat, say_something, times); }
     double lucky_number() override { PYBIND11_OVERLOAD(double, C_Repeat, lucky_number, ); }
 };
 class PyD_Repeat : public D_Repeat {
 public:
     using D_Repeat::D_Repeat;
     int unlucky_number() override { PYBIND11_OVERLOAD(int, D_Repeat, unlucky_number, ); }
-    void say_something(unsigned times) override { PYBIND11_OVERLOAD(void, D_Repeat, say_something, times); }
+    std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, D_Repeat, say_something, times); }
     double lucky_number() override { PYBIND11_OVERLOAD(double, D_Repeat, lucky_number, ); }
 };
 
@@ -221,7 +223,7 @@
 public:
     using Base::Base; // Inherit constructors
     int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, Base, unlucky_number, ); }
-    void say_something(unsigned times) override { PYBIND11_OVERLOAD(void, Base, say_something, times); }
+    std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, Base, say_something, times); }
 };
 template <class Base = B_Tpl>
 class PyB_Tpl : public PyA_Tpl<Base> {
diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py
index 27b0222..1388b1a 100644
--- a/tests/test_virtual_functions.py
+++ b/tests/test_virtual_functions.py
@@ -54,7 +54,7 @@
     assert cstats.move_constructions >= 0
 
 
-def test_inheriting_repeat(capture):
+def test_inheriting_repeat():
     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):
@@ -66,28 +66,20 @@
             return 999
 
     obj = VI_AR()
-    with capture:
-        obj.say_something(3)
-    assert capture == "hihihi"
+    assert obj.say_something(3) == "hihihi"
     assert obj.unlucky_number() == 99
 
     obj = VI_AT()
-    with capture:
-        obj.say_something(3)
-    assert capture == "hihihi"
+    assert obj.say_something(3) == "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.say_something(3) == "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.say_something(3) == "B says hi 3 times"
         assert obj.unlucky_number() == 4444
         assert obj.lucky_number() == 888.0
 
@@ -96,9 +88,7 @@
             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.say_something(3) == "B says hi 3 times"
     assert obj.unlucky_number() == 4444
     assert obj.lucky_number() == 889.25
 
@@ -106,9 +96,7 @@
         pass
 
     obj = VI_CT()
-    with capture:
-        obj.say_something(3)
-    assert capture == "B says hi 3 times"
+    assert obj.say_something(3) == "B says hi 3 times"
     assert obj.unlucky_number() == 4444
     assert obj.lucky_number() == 888.0
 
@@ -117,9 +105,7 @@
             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.say_something(3) == "B says hi 3 times"
     assert obj.unlucky_number() == 4444
     assert obj.lucky_number() == 8892.5
 
@@ -128,9 +114,7 @@
             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.say_something(3) == "B says hi 3 times"
     assert obj.unlucky_number() == 4444
     assert obj.lucky_number() == 888000.0
 
@@ -142,22 +126,18 @@
             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.say_something(3) == "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.say_something(3) == "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))
+            return "VI_DT says:" + (' quack' * times)
 
         def unlucky_number(self):
             return 1234
@@ -166,14 +146,12 @@
             return -4.25
 
     obj = VI_DT()
-    with capture:
-        obj.say_something(3)
-    assert capture == "VI_DT says: quack quack quack"
+    assert obj.say_something(3) == "VI_DT says: quack quack quack"
     assert obj.unlucky_number() == 1234
     assert obj.lucky_number() == -4.25
 
 
-def test_move_support(capture):
+def test_move_support():
     from pybind11_tests import NCVirt, NonCopyable, Movable
 
     class NCVirtExt(NCVirt):
@@ -198,16 +176,10 @@
             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"
+    assert ncv1.print_nc(2, 3) == "36"
+    assert ncv1.print_movable(4, 5) == "9"
     ncv2 = NCVirtExt2()
-    with capture:
-        ncv2.print_movable(7, 7)
-    assert capture == "14"
+    assert ncv2.print_movable(7, 7) == "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)