Repository: boostcon/cppnow_presentations_2014 Branch: master Commit: 46107645315b Files: 476 Total size: 46.9 MB Directory structure: gitextract_igkvdt0q/ ├── .gitignore ├── README.md └── files/ ├── ConceptClang.pptx ├── CppNow2014Ranges.odp ├── PracticalTypeErasureSlides.odp ├── bounded_integer.odp ├── cxx11-library-design.pptx ├── functional-data-structures.key ├── open-pattern-matching.pptx ├── optimization_boost_asio.key ├── ownership_of_memory.odp ├── test_driven/ │ ├── Boost.Test Documentation Rewrite/ │ │ ├── doc/ │ │ │ └── src/ │ │ │ └── boostbook.css │ │ ├── index.html │ │ └── libs/ │ │ └── test/ │ │ └── doc/ │ │ ├── Jamfile.v2 │ │ ├── html/ │ │ │ ├── index.html │ │ │ ├── test/ │ │ │ │ ├── guide/ │ │ │ │ │ ├── acceptance_tests.html │ │ │ │ │ ├── compilation/ │ │ │ │ │ │ ├── _main_.html │ │ │ │ │ │ ├── header_only.html │ │ │ │ │ │ ├── minimal_header.html │ │ │ │ │ │ ├── shared_library.html │ │ │ │ │ │ └── static_library.html │ │ │ │ │ ├── compilation.html │ │ │ │ │ ├── exception_safety_test.html │ │ │ │ │ ├── manually_registering_test_cases_and_suites.html │ │ │ │ │ ├── mocking_collaborators.html │ │ │ │ │ ├── test_case_design.html │ │ │ │ │ ├── testing__main_.html │ │ │ │ │ ├── testing_file_i_o.html │ │ │ │ │ ├── testing_file_io.html │ │ │ │ │ └── testing_protected_or_private_members.html │ │ │ │ ├── guide.html │ │ │ │ ├── how_to_read_this_documentation.html │ │ │ │ ├── motivation.html │ │ │ │ ├── reference/ │ │ │ │ │ ├── assertion/ │ │ │ │ │ │ ├── _boost____level___bitwise_equal_.html │ │ │ │ │ │ ├── _boost____level___close_.html │ │ │ │ │ │ ├── _boost____level___close_fraction_.html │ │ │ │ │ │ ├── _boost____level___equal_collections_.html │ │ │ │ │ │ ├── _boost____level___exception_.html │ │ │ │ │ │ ├── _boost____level___ge_.html │ │ │ │ │ │ ├── _boost____level___gt_.html │ │ │ │ │ │ ├── _boost____level___le_.html │ │ │ │ │ │ ├── _boost____level___lt_.html │ │ │ │ │ │ ├── _boost____level___message_.html │ │ │ │ │ │ ├── _boost____level___ne_.html │ │ │ │ │ │ ├── _boost____level___no_throw_.html │ │ │ │ │ │ ├── _boost____level___predicate_.html │ │ │ │ │ │ ├── _boost____level___small_.html │ │ │ │ │ │ ├── _boost_test_dont_print_log_value_.html │ │ │ │ │ │ ├── _boost_test_error_.html │ │ │ │ │ │ ├── _boost_test_is_defined_.html │ │ │ │ │ │ ├── boost_fail.html │ │ │ │ │ │ ├── boost_level_equal.html │ │ │ │ │ │ ├── boost_level_exception.html │ │ │ │ │ │ ├── boost_level_message.html │ │ │ │ │ │ ├── boost_level_no_throw.html │ │ │ │ │ │ ├── boost_level_throw.html │ │ │ │ │ │ ├── boost_test_dont_print_log_value.html │ │ │ │ │ │ └── levels.html │ │ │ │ │ ├── assertion.html │ │ │ │ │ ├── configuration_macros.html │ │ │ │ │ ├── headers.html │ │ │ │ │ ├── runner/ │ │ │ │ │ │ ├── argument/ │ │ │ │ │ │ │ ├── ___break_exec_path_.html │ │ │ │ │ │ │ ├── ___build_info_.html │ │ │ │ │ │ │ ├── ___catch_system_errors_.html │ │ │ │ │ │ │ ├── ___color_output_.html │ │ │ │ │ │ │ ├── ___detect_fp_exceptions_.html │ │ │ │ │ │ │ ├── ___detect_memory_leaks_.html │ │ │ │ │ │ │ ├── ___log_level_.html │ │ │ │ │ │ │ ├── ___log_sink_.html │ │ │ │ │ │ │ ├── ___output_format_.html │ │ │ │ │ │ │ ├── ___random_.html │ │ │ │ │ │ │ ├── ___report_level_.html │ │ │ │ │ │ │ ├── ___report_sink_.html │ │ │ │ │ │ │ ├── ___result_code_.html │ │ │ │ │ │ │ ├── ___save_pattern_.html │ │ │ │ │ │ │ ├── ___show_progress_.html │ │ │ │ │ │ │ ├── ___use_alt_stack_.html │ │ │ │ │ │ │ ├── auto_start_dbg.html │ │ │ │ │ │ │ ├── list_content.html │ │ │ │ │ │ │ ├── log_format.html │ │ │ │ │ │ │ ├── log_level.html │ │ │ │ │ │ │ ├── log_sink.html │ │ │ │ │ │ │ ├── output_format.html │ │ │ │ │ │ │ ├── report_format.html │ │ │ │ │ │ │ ├── report_level.html │ │ │ │ │ │ │ ├── report_sink.html │ │ │ │ │ │ │ └── run_test.html │ │ │ │ │ │ ├── argument.html │ │ │ │ │ │ ├── output/ │ │ │ │ │ │ │ ├── _boost_test_checkpoint_.html │ │ │ │ │ │ │ ├── _boost_test_passpoint_.html │ │ │ │ │ │ │ ├── boost_test_checkpoint.html │ │ │ │ │ │ │ ├── boost_test_message.html │ │ │ │ │ │ │ ├── log.html │ │ │ │ │ │ │ ├── report.html │ │ │ │ │ │ │ ├── test_log.html │ │ │ │ │ │ │ └── test_report.html │ │ │ │ │ │ └── output.html │ │ │ │ │ ├── runner.html │ │ │ │ │ ├── test_case/ │ │ │ │ │ │ ├── boost_auto_test_case.html │ │ │ │ │ │ ├── boost_auto_test_case_expected_failures.html │ │ │ │ │ │ ├── boost_auto_test_case_template.html │ │ │ │ │ │ ├── boost_fixture_test_case.html │ │ │ │ │ │ ├── boost_global_fixture.html │ │ │ │ │ │ ├── boost_param_class_test_case.html │ │ │ │ │ │ ├── boost_param_test_case.html │ │ │ │ │ │ ├── boost_test_case.html │ │ │ │ │ │ ├── boost_test_case_template.html │ │ │ │ │ │ └── boost_test_case_template_function.html │ │ │ │ │ ├── test_case.html │ │ │ │ │ ├── test_classes/ │ │ │ │ │ │ ├── assertion/ │ │ │ │ │ │ │ ├── _boost____level___bitwise_equal_.html │ │ │ │ │ │ │ ├── _boost____level___close_.html │ │ │ │ │ │ │ ├── _boost____level___close_fraction_.html │ │ │ │ │ │ │ ├── _boost____level___equal_collections_.html │ │ │ │ │ │ │ ├── _boost____level___exception_.html │ │ │ │ │ │ │ ├── _boost____level___ge_.html │ │ │ │ │ │ │ ├── _boost____level___gt_.html │ │ │ │ │ │ │ ├── _boost____level___le_.html │ │ │ │ │ │ │ ├── _boost____level___lt_.html │ │ │ │ │ │ │ ├── _boost____level___message_.html │ │ │ │ │ │ │ ├── _boost____level___ne_.html │ │ │ │ │ │ │ ├── _boost____level___no_throw_.html │ │ │ │ │ │ │ ├── _boost____level___predicate_.html │ │ │ │ │ │ │ ├── _boost____level___small_.html │ │ │ │ │ │ │ ├── _boost_test_dont_print_log_value_.html │ │ │ │ │ │ │ ├── _boost_test_error_.html │ │ │ │ │ │ │ ├── _boost_test_is_defined_.html │ │ │ │ │ │ │ ├── boost_fail.html │ │ │ │ │ │ │ ├── boost_level_equal.html │ │ │ │ │ │ │ ├── boost_level_throw.html │ │ │ │ │ │ │ └── levels.html │ │ │ │ │ │ ├── assertion.html │ │ │ │ │ │ ├── headers.html │ │ │ │ │ │ ├── init_unit_test_func.html │ │ │ │ │ │ ├── master_test_suite_t.html │ │ │ │ │ │ ├── predicate_result/ │ │ │ │ │ │ │ ├── init_unit_test_func.html │ │ │ │ │ │ │ ├── master_test_suite_t.html │ │ │ │ │ │ │ ├── test_case.html │ │ │ │ │ │ │ ├── test_observer.html │ │ │ │ │ │ │ ├── test_suite.html │ │ │ │ │ │ │ ├── test_unit.html │ │ │ │ │ │ │ ├── unit_test_log_formatter.html │ │ │ │ │ │ │ ├── unit_test_log_t.html │ │ │ │ │ │ │ └── unit_test_main.html │ │ │ │ │ │ ├── predicate_result.html │ │ │ │ │ │ ├── runner/ │ │ │ │ │ │ │ ├── argument.html │ │ │ │ │ │ │ └── output.html │ │ │ │ │ │ ├── runner.html │ │ │ │ │ │ ├── test_case.html │ │ │ │ │ │ ├── test_observer.html │ │ │ │ │ │ ├── test_suite.html │ │ │ │ │ │ ├── test_unit.html │ │ │ │ │ │ ├── unit_test_log_formatter.html │ │ │ │ │ │ ├── unit_test_log_t.html │ │ │ │ │ │ └── unit_test_main.html │ │ │ │ │ ├── test_classes.html │ │ │ │ │ ├── test_suite/ │ │ │ │ │ │ ├── boost_auto_test_suite.html │ │ │ │ │ │ ├── boost_auto_test_suite_end.html │ │ │ │ │ │ ├── boost_fixture_test_suite.html │ │ │ │ │ │ ├── boost_test_module.html │ │ │ │ │ │ └── boost_test_suite.html │ │ │ │ │ └── test_suite.html │ │ │ │ ├── reference.html │ │ │ │ ├── tutorials/ │ │ │ │ │ ├── hello_test.html │ │ │ │ │ ├── running_selected_tests.html │ │ │ │ │ ├── testing_with_exceptions.html │ │ │ │ │ └── testing_with_fixtures.html │ │ │ │ └── tutorials.html │ │ │ └── test_HTML.manifest │ │ ├── src/ │ │ │ ├── Jamfile.v2 │ │ │ ├── UTF.log.xsd │ │ │ ├── UTF.report.xsd │ │ │ ├── examples/ │ │ │ │ ├── Jamfile.v2 │ │ │ │ ├── another_global_fixture.cpp │ │ │ │ ├── assertion_failures.cpp │ │ │ │ ├── assertions.cpp │ │ │ │ ├── auto_test_case_expected_failures.cpp │ │ │ │ ├── auto_test_case_template.cpp │ │ │ │ ├── compilation/ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── dynamic/ │ │ │ │ │ │ ├── main.cpp │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── dynamic_main/ │ │ │ │ │ │ ├── main.cpp │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── minimal/ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── static/ │ │ │ │ │ │ ├── main.cpp │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ └── static_main/ │ │ │ │ │ ├── main.cpp │ │ │ │ │ └── test_hello.cpp │ │ │ │ ├── file_system.cpp │ │ │ │ ├── global_fixture.cpp │ │ │ │ ├── manual_registration.cpp │ │ │ │ ├── param_class_test_case.cpp │ │ │ │ ├── param_test_case.cpp │ │ │ │ ├── test_case.cpp │ │ │ │ ├── test_case_template.cpp │ │ │ │ └── turtle_mock.cpp │ │ │ ├── ref-assertion.qbk │ │ │ ├── ref-assertion.qbk.bak │ │ │ ├── ref-compilation.qbk │ │ │ ├── ref-runner-argument.qbk │ │ │ ├── ref-runner-argument.qbk.bak │ │ │ ├── ref-runner-output.qbk │ │ │ ├── ref-runner.qbk │ │ │ ├── ref-test-case.qbk │ │ │ ├── ref-test-case.qbk.bak │ │ │ ├── ref-test-classes.qbk │ │ │ ├── ref-test-suite.qbk │ │ │ ├── reference.qbk │ │ │ ├── system_under_test/ │ │ │ │ ├── Jamfile.v2 │ │ │ │ ├── hello/ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── hello.cpp │ │ │ │ │ └── hello.hpp │ │ │ │ └── scanner/ │ │ │ │ ├── Jamfile.v2 │ │ │ │ ├── directory_scanner.hpp │ │ │ │ ├── filesystem_directory_scanner.hpp │ │ │ │ ├── scanner.cpp │ │ │ │ └── scanner.hpp │ │ │ ├── test.qbk │ │ │ ├── tutorials/ │ │ │ │ ├── Jamfile.v2 │ │ │ │ ├── hello_test/ │ │ │ │ │ ├── 1/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── hello_test~1.output │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── 2/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── hello_test~2.output │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── 3/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── hello_test~3.output │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ └── test/ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── hello_test.output │ │ │ │ │ ├── sut/ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ └── test/ │ │ │ │ │ └── test_hello.cpp │ │ │ │ ├── running_selected_tests/ │ │ │ │ │ ├── 1/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── report_level_detailed.output │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ │ └── test_hello~running_selected_tests~1.output │ │ │ │ │ ├── 2/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── report_level_detailed.output │ │ │ │ │ │ ├── run_test_hello_inserts_text.output │ │ │ │ │ │ ├── run_test_hello_star_inserts_text.output │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ │ └── test_hello~running_selected_tests~2.output │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── report_level_detailed.output │ │ │ │ │ ├── sut/ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ └── test/ │ │ │ │ │ └── test_hello.cpp │ │ │ │ ├── testing_with_exceptions/ │ │ │ │ │ ├── 1/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ │ └── test_hello~testing_with_exceptions~1.output │ │ │ │ │ ├── 2/ │ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ │ ├── sut/ │ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ │ ├── test/ │ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ │ └── test_hello~testing_with_exceptions~2.output │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── sut/ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ ├── test/ │ │ │ │ │ │ └── test_hello.cpp │ │ │ │ │ └── test_hello~testing_with_exceptions.output │ │ │ │ └── testing_with_fixtures/ │ │ │ │ ├── 1/ │ │ │ │ │ ├── Jamfile.v2 │ │ │ │ │ ├── sut/ │ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ │ └── hello.hpp │ │ │ │ │ └── test/ │ │ │ │ │ └── test_hello.cpp │ │ │ │ ├── Jamfile.v2 │ │ │ │ ├── sut/ │ │ │ │ │ ├── hello.cpp │ │ │ │ │ └── hello.hpp │ │ │ │ └── test/ │ │ │ │ └── test_hello.cpp │ │ │ ├── tutorials.qbk │ │ │ ├── user-compilation.qbk │ │ │ └── user-guide.qbk │ │ └── todo.txt │ ├── ReadMe.txt │ └── snapshots/ │ ├── 00/ │ │ ├── CMakeLists.txt │ │ ├── LocalPaths.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 01/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 02/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 03/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 04/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 05/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 06/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 07/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 08/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 09/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 10/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 11/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 12/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 13/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 14/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 15/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 16/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 17/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 18/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 19/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 20/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 21/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 22/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 23/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 24/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ └── test_factors.cpp │ ├── 25/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ └── factors.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 26/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 27/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 28/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 29/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 30/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 31/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 32/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 33/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 34/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 35/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 36/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 37/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ ├── 38/ │ │ ├── CMakeLists.txt │ │ ├── factors/ │ │ │ ├── factors.cpp │ │ │ ├── factors.h │ │ │ └── mediator.h │ │ └── test/ │ │ ├── test_factors.cpp │ │ └── test_mediator.cpp │ └── 39/ │ ├── CMakeLists.txt │ ├── factors/ │ │ ├── factors.cpp │ │ ├── factors.h │ │ └── mediator.h │ └── test/ │ ├── test_factors.cpp │ └── test_mediator.cpp └── unicode-cpp.pptx ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ unlinked/ *~ .DS_Store ================================================ FILE: README.md ================================================ # C++Now 2014 Presentations * [Library in a Week Repo](https://github.com/JeffGarland/liaw2014.git) Below are links to the pdfs / keynotes / OPDs in the files directory. Depending on your browser, you may need to right click on the link and select save. ## Tuesday, May 13 * [Library in a Week - C++ Templating Engine](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/liaw_template_engine_day1.pdf?raw=true) * Keynote: Axiomatic Programming: From Euclidean Deductions to C++ Templates and Beyond * C++14: Through the Looking Glass * [Coroutines, Fibers, and Threads, Oh My](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Coroutines-Fibers-Threads.pdf?raw=true) * The Canonical Class * [ConceptClang: Theoretical Advances with Full C++ Concepts](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/ConceptClang.pdf?raw=true) | [PPTX](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/ConceptClang.pptx?raw=true) * [Generic Programming of Generic Spaces: Compile-Time Geometric Algebra with C++11](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/generic_spaces.pdf?raw=true) * [Test-Driven Development With Boost.Test and Turtle Mock, Part I/II](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/test_driven/test_driven.pdf?raw=true) | [Code](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/test_driven/) * [Removing undefined behavior from integer operations: the bounded::integer library](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/bounded_integer.pdf?raw=true) | [LibreOffice File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/bounded_integer.opd?raw=true) * [Value Semantics and Range Algorithms - Composability and Efficiency](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/range_algos.pdf?raw=true) * Preparing the C++11 Library AFIO for Boost Peer Review ## Wednesday, May 14 * [MPL11: A New Metaprogramming Library for C++11](https://ldionne.github.io/mpl11-cppnow-2014) * [The Optimization of a Boost.Asio-Based Networking Server](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/optimization_boost_asio.pdf?raw=true) | [Keynote File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/optimization_boost_asio.key?raw=true) * [Undefined Behavior in C++; what is it, and why should I care](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Undefined-Behavior.pdf?raw=true) * [Mach7: The Design and Evolution of a Pattern Matching Library for C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/open-pattern-matching.pdf?raw=true) | [PowerPoint File](ttps://github.com/boostcon/cppnow_presentations_2014/blob/master/files/open-pattern-matching.pptx?raw=true) * [Practical Type Erasure: A boost::any Based Configuration Framework](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/PracticalTypeErasureSlides.pdf?raw=true) | [LibreOffice File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/PracticalTypeErasureSlides.odp?raw=true) * [A Tutorial Introduction to C++11/14 Part I/II](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/tutorial_intro_cpp_11_14.pdf?raw=true) * [C++11 in Space Plasma Model Development](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/esitys.tar?raw=true) (Requires Java) * [C++11 Library Design](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/cxx11-library-design.pdf?raw=true) | [PPTX File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/cxx11-library-design.pptx?raw=true) * [Goals for Better Code: Implement Complete Types](https://github.com/sean-parent/sean-parent.github.com/wiki/Papers-and-Presentations) * [Multiplatform C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/2014_05_14_multiplatform_cpp.pdf?raw=true) * Octopus: A Policy-Driven Framework for CFD Simulations ## Thursday, May 15 * [Keynote: Beware of C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Josuttis_C++Now_140515_handouts.pdf?raw=true) * [Interactive Metaprogramming Shell Based on Clang](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/2014_cppnow_metashell.pdf?raw=true) * [libcppa: Type-safe Messaging Systems in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/libcppa_part1.pdf?raw=true) | [Part II](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/libcppa_part2.pdf?raw=true) * [Unicode in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/unicode-cpp.pdf?raw=true) | [PPTX File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/unicode-cpp.pptx?raw=true) * [CppComponents: A Modern Portable C++11 Component System](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/cppnow2014_bandela_presentation.pdf?raw=true) * [UI. Aesthetics. C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/UI_Aesthetics_Cpp.pdf?raw=true) * Accelerator Programming with C++ AMP * [Designing XML API for Modern C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/designing-xml-api-for-modern-c++.pdf?raw=true) * [Modern C++ as Concurrent Assembly](https://github.com/diegoperini/cppnow2014-doppl) * [Understanding &&](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/UnderstandingRValueRef_rev7.pdf?raw=true) * [Boost Library Incubator](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/incubator.pdf?raw=true) | [Zip Archive](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/incubator.zip?raw=true) ## Friday, May 16 * [Iterators May Stay](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/CppNow2014Ranges.pdf?raw=true) | [LibreOffice File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/CppNow2014Ranges.opd?raw=true) * [Value Semantics: It ain't about the syntax!](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/accu2015.140518.pdf?raw=true) * [Create Your Own Refactoring Tool with Clang](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Create-Your-Own-Refactoring-Tool-with-Clang.pdf?raw=true) * [How to Design C++ Implementations of Complex Combinatorial Algorithms](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/How_to_Design_C++_Implementations_of_Complex_Combinatorial_Algorithms.pdf?raw=true) * [Intro to Functional Programming in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/intro-to-functional-programming-in-cpp.pdf?raw=true) * [Managing Object Lifetimes](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Managing-Object-Lifetimes.pdf?raw=true) * [0xBADC0DE](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/0xBADC0DE.pdf?raw=true) * [Expected — An Exception-friendly Error Monad](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/expected.pdf?raw=true) * [Lifetime and Usage of Global, Thread-local, and Static Data](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/LifetimeRev2.pdf?raw=true) * [Functional Data Structures in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/functional-data-structures.pdf?raw=true) | [Keynote File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/functional-data-structures.key?raw=true) * [Asynchronous Programming Using Boost.MetaStateMachine and the Upcoming Asynchronous Library](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/AsyncTalkCppNow14.pdf?raw=true) * [Ownership of Memory in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/ownership_of_memory.pdf?raw=true) | [LibreOffice File](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/ownership_of_memory.opd?raw=true) ## Saturday, May 17 * [The Future of Accelerator Programming in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/CppNow2014_Future_of_Accelerator_Programming.pdf?raw=true) * [Functional Reactive Programming - Cleanly Abstracted Interactivity](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/Functional-Reactive-Programming.pdf?raw=true) * [Disambiguation: The Black Technology](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/disambiguation.pdf?raw=true) * [My Thoughts on Large Code Base Change Ripple Management in C++](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/change_ripple.pdf?raw=true) | [Position Paper](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/large_code_base_change_ripple_in_cpp.pdf?raw=true) * [Future of Boost: Boostache](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/boostache.pdf?raw=true) * [Future of Boost: Community Management Team](https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/boost-cmt.pdf?raw=true) ================================================ FILE: files/optimization_boost_asio.key ================================================ [File too large to display: 45.4 MB] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/doc/src/boostbook.css ================================================ /*============================================================================= Copyright (c) 2004 Joel de Guzman http://spirit.sourceforge.net/ Distributed under the Boost Software License, Version 1.0. (See accompany- ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ /*============================================================================= Body defaults =============================================================================*/ body { margin: 1em; font-family: sans-serif; } /*============================================================================= Paragraphs =============================================================================*/ p { text-align: left; font-size: 10pt; line-height: 1.15; } /*============================================================================= Program listings =============================================================================*/ /* Code on paragraphs */ p tt.computeroutput { font-size: 9pt; } pre.synopsis { font-size: 9pt; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } .programlisting, .screen { font-size: 9pt; display: block; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } /* Program listings in tables don't get borders */ td .programlisting, td .screen { margin: 0pc 0pc 0pc 0pc; padding: 0pc 0pc 0pc 0pc; } /*============================================================================= Headings =============================================================================*/ h1, h2, h3, h4, h5, h6 { text-align: left; margin: 1em 0em 0.5em 0em; font-weight: bold; } h1 { font-size: 140%; } h2 { font-weight: bold; font-size: 140%; } h3 { font-weight: bold; font-size: 130%; } h4 { font-weight: bold; font-size: 120%; } h5 { font-weight: normal; font-style: italic; font-size: 110%; } h6 { font-weight: normal; font-style: italic; font-size: 100%; } /* Top page titles */ title, h1.title, h2.title h3.title, h4.title, h5.title, h6.title, .refentrytitle { font-weight: bold; margin-bottom: 1pc; } h1.title { font-size: 140% } h2.title { font-size: 140% } h3.title { font-size: 130% } h4.title { font-size: 120% } h5.title { font-size: 110% } h6.title { font-size: 100% } .section h1 { margin: 0em 0em 0.5em 0em; font-size: 140%; } .section h2 { font-size: 140% } .section h3 { font-size: 130% } .section h4 { font-size: 120% } .section h5 { font-size: 110% } .section h6 { font-size: 100% } /* Code on titles */ h1 tt.computeroutput { font-size: 140% } h2 tt.computeroutput { font-size: 140% } h3 tt.computeroutput { font-size: 130% } h4 tt.computeroutput { font-size: 130% } h5 tt.computeroutput { font-size: 130% } h6 tt.computeroutput { font-size: 130% } /*============================================================================= Author =============================================================================*/ h3.author { font-size: 100% } /*============================================================================= Lists =============================================================================*/ li { font-size: 10pt; line-height: 1.3; } /* Unordered lists */ ul { text-align: left; } /* Ordered lists */ ol { text-align: left; } /*============================================================================= Links =============================================================================*/ a { text-decoration: none; /* no underline */ } a:hover { text-decoration: underline; } /*============================================================================= Spirit style navigation =============================================================================*/ .spirit-nav { text-align: right; } .spirit-nav a { color: white; padding-left: 0.5em; } .spirit-nav img { border-width: 0px; } /*============================================================================= Copyright footer =============================================================================*/ .copyright-footer { text-align: right; font-size: 70%; } .copyright-footer p { text-align: right; font-size: 80%; } /*============================================================================= Table of contents =============================================================================*/ div.toc { margin: 1pc 4% 0pc 4%; padding: 0.1pc 1pc 0.1pc 1pc; font-size: 80%; line-height: 1.15; } .boost-toc { float: right; padding: 0.5pc; } /* Code on toc */ .toc .computeroutput { font-size: 120% } /* No margin on nested menus */ .toc dl dl { margin: 0; } /*============================================================================= Tables =============================================================================*/ .table-title, div.table p.title { margin-left: 4%; padding-right: 0.5em; padding-left: 0.5em; } .informaltable table, .table table { width: 92%; margin-left: 4%; margin-right: 4%; } div.informaltable table, div.table table { padding: 4px; } /* Table Cells */ div.informaltable table tr td, div.table table tr td { padding: 0.5em; text-align: left; font-size: 9pt; } div.informaltable table tr th, div.table table tr th { padding: 0.5em 0.5em 0.5em 0.5em; border: 1pt solid white; font-size: 80%; } table.simplelist { width: auto !important; margin: 0em !important; padding: 0em !important; border: none !important; } table.simplelist td { margin: 0em !important; padding: 0em !important; text-align: left !important; font-size: 9pt !important; border: none !important; } /*============================================================================= Blurbs =============================================================================*/ div.note, div.tip, div.important, div.caution, div.warning, p.blurb { font-size: 9pt; /* A little bit smaller than the main text */ line-height: 1.2; display: block; margin: 1pc 4% 0pc 4%; padding: 0.5pc 0.5pc 0.5pc 0.5pc; } p.blurb img { padding: 1pt; } /*============================================================================= Variable Lists =============================================================================*/ div.variablelist { margin: 1em 0; } /* Make the terms in definition lists bold */ div.variablelist dl dt, span.term { font-weight: bold; font-size: 10pt; } div.variablelist table tbody tr td { text-align: left; vertical-align: top; padding: 0em 2em 0em 0em; font-size: 10pt; margin: 0em 0em 0.5em 0em; line-height: 1; } div.variablelist dl dt { margin-bottom: 0.2em; } div.variablelist dl dd { margin: 0em 0em 0.5em 2em; font-size: 10pt; } div.variablelist table tbody tr td p, div.variablelist dl dd p { margin: 0em 0em 0.5em 0em; line-height: 1; } /*============================================================================= Misc =============================================================================*/ /* Title of books and articles in bibliographies */ span.title { font-style: italic; } span.underline { text-decoration: underline; } span.strikethrough { text-decoration: line-through; } /* Copyright, Legal Notice */ div div.legalnotice p { text-align: left } /*============================================================================= Colors =============================================================================*/ @media screen { body { background-color: #FFFFFF; color: #000000; } /* Syntax Highlighting */ .keyword { color: #0000AA; } .identifier { color: #000000; } .special { color: #707070; } .preprocessor { color: #402080; } .char { color: teal; } .comment { color: #800000; } .string { color: teal; } .number { color: teal; } .white_bkd { background-color: #FFFFFF; } .dk_grey_bkd { background-color: #999999; } /* Links */ a, a .keyword, a .identifier, a .special, a .preprocessor a .char, a .comment, a .string, a .number { color: #005a9c; } a:visited, a:visited .keyword, a:visited .identifier, a:visited .special, a:visited .preprocessor a:visited .char, a:visited .comment, a:visited .string, a:visited .number { color: #9c5a9c; } h1 a, h2 a, h3 a, h4 a, h5 a, h6 a, h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover, h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited { text-decoration: none; /* no underline */ color: #000000; } /* Copyright, Legal Notice */ .copyright { color: #666666; font-size: small; } div div.legalnotice p { color: #666666; } /* Program listing */ pre.synopsis { border: 1px solid #DCDCDC; } .programlisting, .screen { border: 1px solid #DCDCDC; } td .programlisting, td .screen { border: 0px solid #DCDCDC; } /* Blurbs */ div.note, div.tip, div.important, div.caution, div.warning, p.blurb { border: 1px solid #DCDCDC; } /* Table of contents */ div.toc { border: 1px solid #DCDCDC; } /* Tables */ div.informaltable table tr td, div.table table tr td { border: 1px solid #DCDCDC; } div.informaltable table tr th, div.table table tr th { background-color: #F0F0F0; border: 1px solid #DCDCDC; } .copyright-footer { color: #8F8F8F; } /* Misc */ span.highlight { color: #00A000; } } @media print { /* Links */ a { color: black; } a:visited { color: black; } .spirit-nav { display: none; } /* Program listing */ pre.synopsis { border: 1px solid gray; } .programlisting, .screen { border: 1px solid gray; } td .programlisting, td .screen { border: 0px solid #DCDCDC; } /* Table of contents */ div.toc { border: 1px solid gray; } .informaltable table, .table table { border: 1px solid gray; border-collapse: collapse; } /* Tables */ div.informaltable table tr td, div.table table tr td { border: 1px solid gray; } div.informaltable table tr th, div.table table tr th { border: 1px solid gray; } table.simplelist tr td { border: none !important; } /* Misc */ span.highlight { font-weight: bold; } } /*============================================================================= Images =============================================================================*/ span.inlinemediaobject img { vertical-align: middle; } /*============================================================================== Super and Subscript: style so that line spacing isn't effected, see http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=1&postId=5341 ==============================================================================*/ sup, sub { height: 0; line-height: 1; vertical-align: baseline; position: relative; } /* For internet explorer: */ * html sup, * html sub { vertical-align: bottom; } sup { bottom: 1ex; } sub { top: .5ex; } /*============================================================================== Indexes: pretty much the same as the TOC. ==============================================================================*/ .index { font-size: 80%; padding-top: 0px; padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; margin-left: 0px; } .index ul { padding-left: 3em; } .index p { padding: 2px; margin: 2px; } .index-entry-level-0 { font-weight: bold; } .index em { font-weight: bold; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/index.html ================================================ Boost.Test

Browse the documentation.

================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) use-project /boost/test : ../build ; import quickbook ; build-project src ; alias code : src ; boostbook test : src/test.qbk code : chunk.section.depth=4 chunk.first.sections=1 toc.section.depth=4 toc.max.depth=4 generate.section.toc.level=4 boost.root=../../../.. ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/index.html ================================================ Chapter 1. Boost.Test
Boost C++ Libraries Home Libraries People FAQ More

Next

Chapter 1. Boost.Test

Richard Thomson

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Table of Contents

Motivation
How To Read This Documentation
Tutorials
Hello, Test!
Testing with Exceptions
Testing with Fixtures
Running Selected Tests
User's Guide
Compilation and Usage Variants
Minimal Header
main
Header Only
Static Library
Shared Library
Test Case Design and Maintenance
Acceptance Tests and Unit Tests
Testing File I/O
Mocking Collaborators
Testing main
Testing Protected or Private Members
Manually Registering Test Cases and Suites
Reference
Configuration Macros
Test Cases
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES
BOOST_AUTO_TEST_CASE_TEMPLATE
BOOST_FIXTURE_TEST_CASE
BOOST_GLOBAL_FIXTURE
BOOST_PARAM_TEST_CASE
BOOST_PARAM_CLASS_TEST_CASE
BOOST_TEST_CASE
BOOST_TEST_CASE_TEMPLATE
BOOST_TEST_CASE_TEMPLATE_FUNCTION
Test Suites
BOOST_AUTO_TEST_SUITE
BOOST_AUTO_TEST_SUITE_END
BOOST_FIXTURE_TEST_SUITE
BOOST_TEST_MODULE
BOOST_TEST_SUITE
Test Classes
predicate_result
test_unit
test_case
test_suite
master_test_suite_t
test_observer
unit_test_log_t
unit_test_log_formatter
init_unit_test_func
unit_test_main
Test Assertions
Assertion Levels
BOOST_level_BITWISE_EQUAL
BOOST_level_CLOSE
BOOST_level_CLOSE_FRACTION
BOOST_level_EQUAL
BOOST_level_EQUAL_COLLECTIONS
BOOST_level_EXCEPTION
BOOST_FAIL
BOOST_level_GE
BOOST_level_GT
BOOST_level_LE
BOOST_level_LT
BOOST_level_MESSAGE
BOOST_level_NE
BOOST_level_NO_THROW
BOOST_level_PREDICATE
BOOST_level_SMALL
BOOST_level_THROW
BOOST_TEST_DONT_PRINT_LOG_VALUE
Test Runner
Command Line Arguments
--auto_start_dbg
--build_info
--catch_system_errors
--detect_fp_exceptions
--detect_memory_leaks
--log_format
--log_level
--log_sink
--output_format
--random
--report_format
--report_level
--report_sink
--result_code
--run_test
--show_progress
--use_alt_stack
Test Output
Test Log
Test Report
BOOST_TEST_CHECKPOINT
BOOST_TEST_MESSAGE
BOOST_TEST_PASSPOINT

This is the documentation for Boost.Test, a library designed to support automated testing of software generally and unit testing specifically.

Last revised: January 06, 2014 at 04:37:36 GMT


Next
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/acceptance_tests.html ================================================ Acceptance Tests and Unit Tests
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Unit testing helps us to find bugs "in the small"; little implementation details that we got wrong while we were building a function, a method or a class. When we test each class as an isolated unit, we can miss errors in the way two classes interact or in the way a whole ensemble of classes cooperate in an integrated system.

An acceptance test is an automated test that exercises our system as an integrated whole and not as a collection of isolated units. In a unit test, we decouple ourselves from the execution environment in order to test a piece of code in isolation. In an acceptance test, we run the whole system and provide controlled inputs to the system. This may consist of prepared input data files, prepared input databases and so-on.

Using these two forms of automated testing, we can use them as a vise to squeeze bugs between the two forms of automated tests. Unit tests push from below and acceptance tests push from above.

While the facilities in Boost.Test can be used to create an automated acceptance test, the tools are fairly low-level for the kinds of high-level criteria that an acceptance test would use. Acceptance tests are usually defined by the product owner or customer and will describe acceptance criteria in the language closest to the problem domain and farthest away from the details of the implementation.

A better approach for automated acceptance tests would be a tool such as FitNesse that is designed for automated acceptance testing.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation/_main_.html ================================================ main
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

To use the implementation of main provided by Boost.Test, exactly one source file must define BOOST_TEST_MAIN before including <boost/test/unit_test.hpp>. If multiple source files define BOOST_TEST_MAIN, then a multiply defined symbol error will occur during linking.

If BOOST_TEST_NO_MAIN is defined, then no implementation of main will be provided and the test executable must provide an initialization function. The exact initialization function that must be provided varies depending on how the library is compiled. The details are shown in the discussion of each compilation variation.

When Boost.Test is compiled as a library, BOOST_TEST_NO_MAIN must be defined when the library is compiled for it to work properly in those circumstances.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation/header_only.html ================================================ Header Only
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The entire unit test framework can be incorporated into an executable by including the file <boost/test/included/unit_test.hpp>. Because the entire implementation is incorporated into the source file including this header, only a single source file in the test executable can include this header.

Additional source files must define BOOST_TEST_NO_LIB before including <boost/test/unit_test.hpp> to prevent any automatic linking to a shared library. If additional source files attempt to include <boost/test/included/unit_test.hpp>, a multiply defined symbol error will occur during linking.

// In exactly one source file:
#include <boost/test/included/unit_test.hpp>

// test cases (optional)

// In additional source files
#define BOOST_TEST_NO_LIB
#include <boost/test/unit_test.hpp>

// test cases

If BOOST_TEST_NO_MAIN is defined, then an implementation of main must be provided that executes the test cases. This is most readily done by delegating to unit_test_main.

// In exactly one source file
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

boost::unit_test::test_suite *init_function(int argc, char *argv[])
{
    // create test cases and suites and return a pointer to any enclosing
    // suite, or 0.
    return 0;
}

int main(int argc, char* argv[])
{
    return ::boost::unit_test::unit_test_main(&init_function, argc, argv);
}

Example Source Code

The tutorials all use the header-only version of Boost.Test.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation/minimal_header.html ================================================ Minimal Header
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

A lightweight, minimal version of the testing framework can be obtained by including <boost/test/minimal.hpp>. This header provides only the following macros:

Macro

Meaning

BOOST_CHECK(expression)

If expression is false, the test fails and test execution continues.

BOOST_REQUIRE(expression)

If expression is false, the test fails and test execution terminates.

BOOST_ERROR(message)

Report message, fail the test and continue test execution.

BOOST_FAIL(message)

Report message, fail the test and terminate test execution.

The header supplies an implementation of main that executes a single test case by calling a free function named test_main with the following signature:

int test_main(int argc, char *argv[]);

The arguments argc and argv are passed to test_main from the implementation of main supplied by the test framework. No command-line argument processing is performed by main. A summary report of errors recorded by the test case is printed out after executing the test case. If any exception is thrown by the test case, it is caught by main and treated as an error from the test case.

#include <boost/test/minimal.hpp>

int test_main(int argc, char *argv[])
{
    // test case
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation/shared_library.html ================================================ Shared Library
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

To build Boost.Test as a shared library, first build the boost build tools, as described in the Getting Started documentation. After you have bootstrapped the build tools, build the test library with by invoking b2 with arguments similar to the following:

b2 --with-test link=shared

This will place the resulting libraries in stage/lib at the top level of the boost tree.

In a shared library configuration, Boost.Test is compiled into a single shared library named boost_unit_test_framework and the test executable is linked against that library to import symbols from the library. The Boost.Test shared library must be available to the runtime loader in order for the tests to execute. Every compilation unit that includes a header from Boost.Test must define BOOST_TEST_DYN_LINK first so that declarations are properly annotated as imported symbols. When BOOST_TEST_DYN_LINK is defined, Boost.Test also defines BOOST_TEST_ALTERNATIVE_INIT_API.

Exactly one compilation unit in the test executable should define BOOST_TEST_MAIN, in order run the tests.

// In exactly one compilation unit
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

// test cases (optional)

Additional source files define BOOST_TEST_DYN_LINK, include the main unit test header and define more test cases and/or suites.

// In additional source files
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>

// test cases

To compile the library with no implementation of main, add BOOST_TEST_NO_MAIN to the cxxflags property for b2:

b2 --with-test link=shared define=BOOST_TEST_NO_MAIN

When the library is compiled with BOOST_TEST_NO_MAIN defined, one source file must provide a definition for main. The simplest is to delegate to unit_test_main and provide an implementation of an initialization function that manually adds test cases and suites to the test tree. Any test cases or test suites added with BOOST_AUTO_TEST_CASE, BOOST_FIXTURE_TEST_CASE, BOOST_AUTO_TEST_SUITE or BOOST_FIXTURE_TEST_SUITE are automatically added.

// In exactly one source file
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

bool init_function()
{
    // create test cases and suites and return a boolean indicating
    // success (true) or failure (false).
    return true;
}

int main(int argc, char* argv[])
{
    return ::boost::unit_test::unit_test_main(&init_function, argc, argv);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation/static_library.html ================================================ Static Library
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

To build Boost.Test as a static library, first build the boost build tools, as described in the Getting Started documentation. After you have bootstrapped the build tools, build the test library with by invoking b2 with arguments similar to the following:

b2 --with-test link=static

This will place the resulting libraries in stage/lib at the top level of the boost tree.

In a static library configuration, Boost.Test is compiled into a single static library named boost_unit_test_framework and the test executable is linked against that library. Exactly one compilation unit in the test executable should define BOOST_TEST_MAIN, in order run the tests.

// In exactly one source file
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>

// test cases (optional)

Additional source files simply include the main unit test header and define more test cases and/or suites.

// In additional source files
#include <boost/test/unit_test.hpp>

// test cases

To compile the library with no implementation of main, add BOOST_TEST_NO_MAIN to the cxxflags property for b2:

b2 --with-test link=static define=BOOST_TEST_NO_MAIN

When the library is compiled with BOOST_TEST_NO_MAIN defined, one source file must provide a definition for main. The simplest is to delegate to unit_test_main and provide an implementation of an initialization function that manually adds test cases and suites to the test tree. Any test cases or test suites added with BOOST_AUTO_TEST_CASE, BOOST_FIXTURE_TEST_CASE, BOOST_AUTO_TEST_SUITE or BOOST_FIXTURE_TEST_SUITE are automatically added.

// In exactly one source file
#define BOOST_TEST_NO_MAIN
#include <boost/test/unit_test.hpp>

boost::unit_test::test_suite *init_function(int argc, char *argv[])
{
    // create test cases and suites and return a pointer to any enclosing
    // suite, or 0.
    return 0;
}

int main(int argc, char *argv[])
{
    return boost::unit_test::unit_test_main(init_function, argc, argv);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/compilation.html ================================================ Compilation and Usage Variants
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Boost.Test is available in several forms:

  • a single, minimal header
  • a header-only form
  • a static library
  • a shared library

The minimal header can be useful in situations where you don't already have the library built and want to quickly explore a test with a minimal amount of fuss. Once you need to create multiple unit tests, you will quickly outgrow the minimal header.

The header only form is useful when you don't want to be bothered with compiling the library. Once you have multiple compilation units with unit tests in each compilation unit, you will grow tired of the compilation cost involved with the header only form of the framework.

The static library form is the easiest to integrate into your build system as it doesn't require any installation of runtime files in order to execute your tests. This runtime simplicity comes at the cost of increased link times and executable sizes.

The dynamic library form requires the most effort for successful test execution, but provides faster link times than the static library, faster compile times than the header only form and provides all the features of the framework compared to the minimal header.

[Caution] Caution

Boost.Test is not a thread-safe library. Care should be taken when automated tests create multiple threads and interact with data structures passed to Boost.Test macros or functions.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/exception_safety_test.html ================================================ Exception Safety Tests
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Boost.Test provides support for a special kind of test called an exception safety test.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/manually_registering_test_cases_and_suites.html ================================================ Manually Registering Test Cases and Suites
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
Registering Test Cases

You may have an existing body of tests that you wish to register with Boost.Test manually. You can use BOOST_TEST_CASE to register a function taking no arguments and returning void as a test case:

static void inserts_text()
{
    std::ostringstream dest;

    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

static void register_function(test_suite& suite)
{
    suite.add(BOOST_TEST_CASE(inserts_text));
}

You can use a test case method on a fixture class by registering a function that creates an instance of the fixture and invokes the test method. This assures that a fresh fixture is created for each test case, ensuring that each test executes independently of other tests.

class hello_fixture
{
public:
    void stream_with_badbit_throws_runtime_error()
    {
        dest.clear(std::ios_base::badbit);

        BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
    }

    std::ostringstream dest;
};

static void stream_with_badbit_throws_runtime_error()
{
    hello_fixture().stream_with_badbit_throws_runtime_error();
};

static void register_method_function_instance(test_suite& suite)
{
    suite.add(BOOST_TEST_CASE(stream_with_badbit_throws_runtime_error));
}

You can register a method on a class as a test case by using Boost.Bind to bind the method to a static instance of the class. This can cause oen test case to influence the execution of another test case because they share the static fixture.

static hello_fixture hf;

static void register_method_static_instance(test_suite& suite)
{
    suite.add(BOOST_TEST_CASE(
        boost::bind(&hello_fixture::stream_with_badbit_throws_runtime_error,
            &hf)));
}

A static instance of the class is used so that the instance exists at the time the test case is invoked. Test case invocation happens after registration, so using a local instance in the registration function is insufficient.

Registering Test Suites

A new test suite is created with the BOOST_TEST_SUITE macro. The new suite must be added to the master test suite to execute its tests. Any number of test suites can be added in a hierarchy of suites and any test case can be added to any test suite.

static test_suite*
init_unit_test_suite(int argc, char* argv[])
{
    test_suite* hello_suite = BOOST_TEST_SUITE("hello");
    register_function(*hello_suite);
    register_method_static_instance(*hello_suite);
    register_method_function_instance(*hello_suite);
    framework::master_test_suite().add(hello_suite);
    return 0;
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/mocking_collaborators.html ================================================ Mocking Collaborators
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

In testing file I/O, we showed an example of creating a class fake_directory_scanner that acted as a simple test double for an interface. Such simple fake objects are fine at first, but they're full of boring boiler plate code and after a while it becomes tedious to write them by hand.

For collaborators defined by a pure virtual base class, also known as an interface, there are mock object frameworks that alleviate the need to write the repetitive boiler plate code. One such mock object framework that is designed to work with Boost.Test is the Turtle mock object framework.

Here is an example of the file system tests written using turtle:

#include "directory_scanner.hpp"
#include <turtle/mock.hpp>

MOCK_BASE_CLASS(mock_directory_scanner, directory_scanner)
{
    MOCK_METHOD(begin, 1);
    MOCK_METHOD(has_next, 0);
    MOCK_METHOD(next, 0);
};

Defining the mock object is considerably simpler than writing a fake object by hand. Turtle uses variadic argument macros and template based type deduction to infer the type signature of the methods simply from the number of arguments each method takes. This alleviates us from having to repeat all of this information from the interface into the implementation of the test double.

Now we can rewrite our tests to use a mock object configured for each test case:

static std::string const ARBITRARY_DIRECTORY_NAME("foo");
static std::string const ARBITRARY_NON_TEXT_FILE_NAME("foo.foo");
static std::string const ARBITRARY_TEXT_FILE_NAME("foo.txt");
static std::string const ARBITRARY_OTHER_TEXT_FILE_NAME("bar.txt");

struct text_files_fixture
{
    text_files_fixture()
    {
        MOCK_EXPECT(scanner.begin).once().with(ARBITRARY_DIRECTORY_NAME);
    }

    void expect_enumerate_non_text_file()
    {
        MOCK_EXPECT(scanner.has_next).once().returns(true);
        MOCK_EXPECT(scanner.next).once().returns(ARBITRARY_NON_TEXT_FILE_NAME);
    }

    void expect_enumerate_text_file(std::string const& file_name = ARBITRARY_TEXT_FILE_NAME)
    {
        MOCK_EXPECT(scanner.has_next).once().returns(true);
        MOCK_EXPECT(scanner.next).once().returns(file_name);
        expected.push_back(file_name);
    }

    void expect_enumerate_end()
    {
        MOCK_EXPECT(scanner.has_next).once().returns(false);
    }

    mock_directory_scanner scanner;
    std::vector<std::string> empty;
    std::vector<std::string> expected;
};

BOOST_FIXTURE_TEST_SUITE(test_text_files, text_files_fixture);

BOOST_AUTO_TEST_CASE(returns_empty_for_empty_directory)
{
    expect_enumerate_end();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_empty_for_no_text_files)
{
    expect_enumerate_non_text_file();
    expect_enumerate_end();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_file_for_text_file)
{
    expect_enumerate_text_file();
    expect_enumerate_end();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_only_text_file_for_mixed_files)
{
    expect_enumerate_text_file();
    expect_enumerate_non_text_file();
    expect_enumerate_end();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_all_text_files)
{
    expect_enumerate_text_file();
    expect_enumerate_non_text_file();
    expect_enumerate_text_file(ARBITRARY_OTHER_TEXT_FILE_NAME);
    expect_enumerate_end();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_SUITE_END();

The tests themselves are largely unchanged and what is different is the intention revealing methods we placed in the test fixture. Mock object frameworks generally provide a rich set of methods on the mock object for setting the expectations on the number of times a method is called, such as once(), the expected arguments to a method, such as with(), and the return value of a method, such as returns().

With a turtle mock, the expectations are verified when the mock object is destroyed. The mock is a member in our fixture and will be destroyed at the end of every test case.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/test_case_design.html ================================================ Test Case Design and Maintenance
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

xUnit Patterns[2], by Gerard Meszaros, presents several high level objectives for automated tests and individual goals for achieving those objectives:

In this section, we will discuss how the facilities in Boost.Test can support these goals; see xUnit Patterns for the description and rationale of these goals.

Goal: Tests as Specifications

Tests can serve as specifications for the system under test if we write the test for the system first, using test-driven development. We imagine the perfect system that does exactly what we need and write a test as if that system existed. In order to achieve a failing test, we write just enough of the implementation to make the test compile.

A good way to ensure that the implementation causes a test failure is for called methods and functions to throw an exception indicating that the method or function called is not implemented:

#include <stdexcept>

void free_function()
{
    throw std::runtime_error("free_function not implemented.");
}

We get a failing test right away, while still satisfying just enough syntax to satisfy the compiler.

Goal: Bug Repellant

It is well known that the longer a bug remains undetected in a software, the more expensive it is to fix.[3] If we are practicing test-driven development, then we find bugs in our implementation as soon as we code them. The time to find a bug in this manner can be as little as seconds and was demonstrated in the tutorial "Hello, Test!".

The easiest way to achieve this rapid feedback is to run the tests as part of the build. The details vary depending on your build system.

In Visual Studio 2012, this is most readily achieved by setting a post-build build event as shown below. Because $(TargetPath) may contain spaces, the variable is surrounded by double quotes to ensure that the entire path to the executable is found. The description is given generically using $(TargetName) so that this build event can be copied to any test project's properties and be used without modification. Take care that you define the build event for all configurations and all platforms used by your build system so that the unit tests always run.

user-vs2012-build-event

If you are using a Makefile to compile your code, create a phony target that depends on your unit test executable and specify the command to execute your unit test and create the phony target if the test passes. This will ensure that the unit tests continue to run as long as they fail because the phony target will only be updated when the tests pass.

If you are using Boost.Build and Jamfiles to compile your code, you can use the rules in the testing module to incorporate your unit tests into your build. The unit-test rule will build an executable and run it, failing the build when the executable returns a non-zero exit status. Other rules in the testing module may also be useful.

Goal: Defect Localization

If we keep our test cases focused on only a single behavior in our system under test, then there is only a single cause for any particular unit test to fail. We saw this in "Testing With Exceptions" when we added a new test case to hello_world for a bad stream. By choosing intention revealing names for our test cases, we can identify the source of the failure simply by reading the name of the failed test case.

Since each test case excercises only one scenario for the system under test, we must make at least one test case for each possible scenario. We can use the cyclomatic complexity as a rough proxy for the number of tests cases needed for any particular method or function to ensure that we have sufficient coverage of the system under test.

Goal: Tests as Documentation

When confronted with a new software component or a new code base, how do we understand its behavior? We can read the documentation, but ultimately the behavior is defined by the code executed. Comments and documentation can lag the actual implementation. Sometimes, the only answer to our questions about a software component come from the implementation. If the component is only available to us in binary form, we don't have the luxury of consulting the source code in order to answer our questions.

Unit tests can serve as a form of executable documentation for software components. They tell us how the system responds to the scenarios orchestrated by the test cases.

When faced with a confusing aspect of a software component, we can answer questions about the behavior of the component by writing a unit test that describes our hypothesis about the component's behavior. If the unit test passes, we have verified our hypothesis. If the unit test fails, our hypothesis was incorrect; either way, we have learned something about the component. We can use unit tests to document subtle and unexpected behaviors of components. Unit tests are also the perfect documentation for a bug report on a component maintained by others.

Goal: Tests as Safety Net

When we start building a software system, we are able to keep all the details of the system in our mind because the system is small. As the size of the system increases, it becomes harder and harder to keep all the details of the system in mind as we make modifications. A comprehensive suite of unit tests over the system give us an automated regression test that gives us the confidence of knowing that our changes are not introducing any problems elsewhere in the code.

Goal: Do No Harm

Automated tests should only reduce risk, not introduce risk into the system. To achieve this, we want to keep all test code separated from production code. The easiest way to do this is to put the system under test into a library (static or shared) and link the test executable against the library. We saw this in the tutorial "Hello, Test!", when we separated the system under test into the hello library and the test code into test_hello.cpp.

Goal: Fully Automated Test

Boost.Test supports fully automated tests by allowing us to supply the inputs to the system under test in each test case in order to drive the system into the scenario of interest. Test cases should never rely on user input, or they will not be fully automated tests that can run unattended.

Goal: Self-Checking Test

Boost.Test supports self-checking tests through its rich set of assertions. Each test case supplies the inputs to the system under test and validates the behavior of the system using assertions. Self-checking tests report only bad news and good news results in no notifications. The default output from the test runner only reports failing tests and a summary of all tests executed. The test runner also returns a non-zero status code when a test fails, allowing easy failure of continuous integration builds.

Goal: Repeatable Test

We should get the same results from automated tests every time we run them, provided the implementation of the system under test has not changed between runs. In the context of unit testing, this implies that a test case must control all the collaborators that can influence the system.

The most troublesome collaborators are among the following: * current date and time * device input * file system * system services (Windows registry, networking, etc.) * C style apis

In the book "Working Effectively with Legacy Code", Michael Feathers described a number of techniques for decoupling the system under test from such troublesome collaborators that can cause unit tests to spuriously fail. All the techniques are variations on a theme: introduce a level of indirection to decouple the system under test from a collaborator. C++ offers static polymorphism via templates as well as the usual dynamic polymorphism via interfaces to decouple a system under test from a collaborator.

Goal: Simple Tests

We keep tests simple by exercising only one scenario for each test case. Simple test cases read linearly through the phases of setup, exercise and verify. Trying to exercise too much functionality in a single test case can introduce unnecessary complexity into the test.

Duplication between test cases can make tests hard to read by distracting us from the steady rhythm of setup, exercise and verify of test cases. You may find it useful to apply the rule of three when writing test cases to decide when to extract duplication into a fixture.

Goal: Expressive Tests

Sometimes low-level setup details get in the way of a test reading clearly. This could be the result of a complicated data structure needed in order to exercise the system down a particular code path. Similarly, the verification of a result produced by the system under test may involve a series of assertions that make the test hard to follow. Boost.Test provides fixtures as a way to localize these distracting details by extracting setup and assertion methods into the fixture.

Over time we build up a series of methods in the fixture that allow us to express domain concepts succinctly and clearly in the tests, making them more expressive of the scenario in the domain. Fixtures can be combined through aggregation or inheritance in order to express combinations and hierarchies of domain concepts.

Goal: Separation of Concerns

We keep test code separated from production code with the packaging mechanisms provided by C++. Production code is supplied to the test executable as a library, either static or dynamic. The test code resides in separate source files from the production code. The production code consumed by the test code is compiled with the exact same preprocessor settings as the production code to ensure that tests do not influence the production code.

We keep concerns separated in our tests by testing each concern in its own test case. Each test case exercises a single scenario and our tests exercise the responsibilities or classes individually. If we are practicing test-driven development, we keep the single responsibility principle in mind as we are creating the system to satisfy the evolving tests. When our tests start involving more than one concern, it can be a sign that our system under test is covering more than one responsibility.

Goal: Robust Test

Test cases are robust when small changes to the system under test result in a small number of test cases failing. If a small change to the system results in many test cases failing, then our tests are not robust. If our tests cases do not sufficiently isolate the system under test from its collaborators, then a change to one part of the system can cause tests on seemingly unrelated parts of the system to fail. If we have repeated assertions in many test cases for the same system under test, then many test cases can fail if that single assertion fails. Each of these situations is a case of overlap between test cases; in the first case, the overlap is between the parts of the production code unrelated to the system under test that we exercise and in the second case, the overlap is between test cases on the system under test.



[2] The term xUnit is a generic term for unit testing frameworks, such as jUnit. The advice in xUnit Patterns applies equally well to Boost.Test.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/testing__main_.html ================================================ Testing main
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

If there is considerable logic in an appliation's main function, this can be difficult to unit test. The One Definition Rule prevents us from having the application's main and the unit test executable's main in the same executable. Furthermore, even if we could perform some trick to resolve the multiply defined symbol[4], we would still need to figure out how to link the test executable with the application's main function to test the code.

When it becomes difficult to test code where it is currently, such as in the body of main, the simplest thing to do is to move the code somewhere else that makes it easy to test. Here is one way to accomplish this:

  1. rename main to app_main.
  2. move app_main to a library.
  3. create a simple delegating main that calls app_main.
  4. write tests for app_main by linking against the library.

The delegating main looks like this:

extern int app_main(int argc, char* argv[]);

int main(int argc, char* argv[])
{
    return app_main(argc, argv);
}

If you don't already have a library for app_main, then create one and add all the other application code to the library as well. The build logic for making the executable will consist of compiling a single source file containing your delegating implementation of main and linking against a library containing the rest of the application. This will give you a starting point for writing unit tests for anything in your application.



[4] We could abuse the C++ preprocessor or use object file symbol modification.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/testing_file_i_o.html ================================================ Testing File I/O
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

A common problem encountered in unit testing is interaction with the file system: scanning directories, creating files, opening files, reading files, writing files, creating symbolic links and so-on. Interacting directly with the file system when executing unit tests can lead to a failure of tests to be robust or repeatable. We also want our unit tests to be fast; an execution time of 100 milliseconds is considered a slow unit test. Interacting directly with the file system can make our unit tests take too long to execute.

The simplest approach is to wrap file system operations in an interface and perform all operations through the interface. Consider the following example of a function that returns a vector of filenames ending in ".txt" in a given directory:

extern std::vector<std::string> text_files(std::string const& directory);

How can we unit test text_files without relying on the actual contents of the file system? We can decouple text_files from the file system by introducing an interface:

class directory_scanner;

extern std::vector<std::string> text_files(
    std::string const& directory,
    directory_scanner& scanner);

We've used a forward declaration of directory_scanner where text_files is declared. The interface looks like this:

class directory_scanner
{
public:
    virtual ~directory_scanner() {}

    virtual void begin(std::string const &directory) = 0;

    virtual bool has_next() const = 0;

    virtual std::string next() const = 0;
};

The interface directory_scanner is used to isolate the free function text_files from directly interacting with the file system. In the unit tests, we use an implementation of directory_scanner that senses how text_files uses the interface and allows us to control the data made available to text_files. The tests can use a hand-crafted fake implementation or an implementation from a mock library. The fake might look something like this:

class fake_directory_scanner : public directory_scanner
{
public:
    fake_directory_scanner()
        : begin_called(false),
        has_next_called(false),
        next_called(false),
        next_call_count(0U)
    {}

    virtual ~fake_directory_scanner() {}

    virtual void begin(std::string const &directory)
    {
        begin_called = true;
        begin_last_directory = directory;
    }
    bool begin_called;
    std::string begin_last_directory;

    virtual bool has_next() const
    {
        has_next_called = true;
        return next_call_count <= next_fake_results.size();
    }
    mutable bool has_next_called;
    bool has_next_fake_result;

    virtual std::string next() const
    {
        next_called = true;
        ++next_call_count;
        return has_next() ? next_fake_results[next_call_count - 1U] : "";
    }
    mutable bool next_called;
    mutable std::size_t next_call_count;
    std::vector<std::string> next_fake_results;
};

The tests for text_files use the fake_directory_scanner to specify the configuration of the file system for the different test cases:

struct text_files_fixture
{
    fake_directory_scanner scanner;
};

BOOST_FIXTURE_TEST_SUITE(test_text_files, text_files_fixture);

BOOST_AUTO_TEST_CASE(returns_empty_for_empty_directory)
{
    std::vector<std::string> empty;

    std::vector<std::string> files = text_files("foo", scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_empty_for_no_text_files)
{
    scanner.next_fake_results.push_back("foo.foo");
    std::vector<std::string> empty;

    std::vector<std::string> files = text_files("foo", scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_file_for_text_file)
{
    scanner.next_fake_results.push_back("foo.txt");
    std::vector<std::string> expected;
    expected.push_back("foo.txt");

    std::vector<std::string> files = text_files("foo", scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_only_text_file_for_mixed_files)
{
    scanner.next_fake_results.push_back("foo.txt");
    scanner.next_fake_results.push_back("foo.foo");
    std::vector<std::string> expected;
    expected.push_back("foo.txt");

    std::vector<std::string> files = text_files("foo", scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_SUITE_END();

In production code, we use an implementation of directory_scanner that interacts directly with the file system using Boost.FileSystem.

class filesystem_directory_scanner : public directory_scanner
{
public:
    filesystem_directory_scanner() {}
    virtual ~filesystem_directory_scanner() {}

    virtual void begin(std::string const &directory)
    {
        current = boost::filesystem::directory_iterator(directory);
    }

    virtual bool has_next() const
    {
        return current != end;
    }

    virtual std::string next() const
    {
        if (has_next())
        {
            std::string const result = (*current).path().filename().string();
            do
            {
                ++current;
            }
            while (has_next() && !boost::filesystem::is_regular_file((*current).path()));
            return result;
        }
        throw std::runtime_error("no next path");
    }

private:
    mutable boost::filesystem::directory_iterator current;
    boost::filesystem::directory_iterator end;
};

We've wrapped just enough of Boost.FileSystem for our needs; Boost.FileSystem has a very large surface area and we don't need to put an interface around the entire thing, just enough to satisfy the needs of text_files.

If we don't want production code to have to worry about supplying an instance of filesystem_directory_scanner to text_files, we can use overloading on text_files and use simple delegation to supply the dependency:

extern std::vector<std::string>
text_files(std::string const& directory)
{
    filesystem_directory_scanner scanner;
    return text_files(directory, scanner);
}

Seeing this, you might wonder if we need to unit test the overload we just created? Because we are using simple delegation here, there isn't sufficient complexity to warrant unit testing. However, we have no unit tests for filesystem_directory_scanner, which does have control structures. We will want some sort of automated tests around this code to verify that it functions properly. We can use acceptance tests to verify the system as a whole, exercising all the components end-to-end and not just in isolation.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/testing_file_io.html ================================================ Testing File I/O
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

A common problem encountered in unit testing is interaction with the file system: scanning directories, creating files, opening files, reading files, writing files, creating symbolic links and so-on. Interacting directly with the file system when executing unit tests can lead to a failure of tests to be robust or repeatable. We also want our unit tests to be fast; an execution time of 100 milliseconds is considered a slow unit test. Interacting directly with the file system can make our unit tests take too long to execute.

The simplest approach is to wrap file system operations in an interface and perform all operations through the interface. Consider the following example of a function that returns a vector of filenames ending in ".txt" in a given directory:

extern std::vector<std::string> text_files(std::string const& directory);

How can we unit test text_files without relying on the actual contents of the file system? We can decouple text_files from the file system by introducing an interface:

class directory_scanner;

extern std::vector<std::string> text_files(
    std::string const& directory,
    directory_scanner& scanner);

We've used a forward declaration of directory_scanner where text_files is declared. The interface looks like this:

class directory_scanner
{
public:
    virtual ~directory_scanner() {}

    virtual void begin(std::string const &directory) = 0;

    virtual bool has_next() const = 0;

    virtual std::string next() const = 0;
};

The interface directory_scanner is used to isolate the free function text_files from directly interacting with the file system. In the unit tests, we use an implementation of directory_scanner that senses how text_files uses the interface and allows us to control the data made available to text_files. The tests can use a hand-crafted fake implementation or an implementation from a mock library. The fake might look something like this:

class fake_directory_scanner : public directory_scanner
{
public:
    fake_directory_scanner()
        : begin_called(false),
        has_next_called(false),
        next_called(false),
        next_call_count(0U)
    {}

    virtual ~fake_directory_scanner() {}

    virtual void begin(std::string const &directory)
    {
        begin_called = true;
        begin_last_directory = directory;
    }
    bool begin_called;
    std::string begin_last_directory;

    virtual bool has_next() const
    {
        has_next_called = true;
        return next_call_count <= next_fake_results.size();
    }
    mutable bool has_next_called;
    bool has_next_fake_result;

    virtual std::string next() const
    {
        next_called = true;
        ++next_call_count;
        return has_next() ? next_fake_results[next_call_count - 1U] : "";
    }
    mutable bool next_called;
    mutable std::size_t next_call_count;
    std::vector<std::string> next_fake_results;
};

The tests for text_files use the fake_directory_scanner to specify the configuration of the file system for the different test cases:

static std::string const ARBITRARY_DIRECTORY_NAME("foo");
static std::string const ARBITRARY_NON_TEXT_FILE_NAME("foo.foo");
static std::string const ARBITRARY_TEXT_FILE_NAME("foo.txt");
static std::string const ARBITRARY_OTHER_TEXT_FILE_NAME("bar.txt");

struct text_files_fixture
{
    void expect_enumerate_non_text_file()
    {
        scanner.next_fake_results.push_back(ARBITRARY_NON_TEXT_FILE_NAME);
    }

    void expect_enumerate_text_file(std::string const& file_name = ARBITRARY_TEXT_FILE_NAME)
    {
        scanner.next_fake_results.push_back(file_name);
        expected.push_back(file_name);
    }

    fake_directory_scanner scanner;
    std::vector<std::string> empty;
    std::vector<std::string> expected;
};

BOOST_FIXTURE_TEST_SUITE(test_text_files, text_files_fixture);

BOOST_AUTO_TEST_CASE(returns_empty_for_empty_directory)
{
    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_empty_for_no_text_files)
{
    expect_enumerate_non_text_file();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_file_for_text_file)
{
    expect_enumerate_text_file();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_only_text_file_for_mixed_files)
{
    expect_enumerate_text_file();
    expect_enumerate_non_text_file();

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_CASE(returns_all_text_files)
{
    expect_enumerate_text_file();
    expect_enumerate_non_text_file();
    expect_enumerate_text_file(ARBITRARY_OTHER_TEXT_FILE_NAME);

    std::vector<std::string> files = text_files(ARBITRARY_DIRECTORY_NAME, scanner);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end());
}

BOOST_AUTO_TEST_SUITE_END();

In production code, we use an implementation of directory_scanner that interacts directly with the file system using Boost.FileSystem.

class filesystem_directory_scanner : public directory_scanner
{
public:
    filesystem_directory_scanner() {}
    virtual ~filesystem_directory_scanner() {}

    virtual void begin(std::string const &directory)
    {
        current = boost::filesystem::directory_iterator(directory);
    }

    virtual bool has_next() const
    {
        return current != end;
    }

    virtual std::string next() const
    {
        if (has_next())
        {
            std::string const result = (*current).path().filename().string();
            do
            {
                ++current;
            }
            while (has_next() && !boost::filesystem::is_regular_file((*current).path()));
            return result;
        }
        throw std::runtime_error("no next path");
    }

private:
    mutable boost::filesystem::directory_iterator current;
    boost::filesystem::directory_iterator end;
};

We've wrapped just enough of Boost.FileSystem for our needs; Boost.FileSystem has a very large surface area and we don't need to put an interface around the entire thing, just enough to satisfy the needs of text_files.

If we don't want production code to have to worry about supplying an instance of filesystem_directory_scanner to text_files, we can use overloading on text_files and use simple delegation to supply the dependency:

extern std::vector<std::string>
text_files(std::string const& directory)
{
    filesystem_directory_scanner scanner;
    return text_files(directory, scanner);
}

Seeing this, you might wonder if we need to unit test the overload we just created? Because we are using simple delegation here, there isn't sufficient complexity to warrant unit testing. However, we have no unit tests for filesystem_directory_scanner, which does have control structures. We will want some sort of automated tests around this code to verify that it functions properly. We can use acceptance tests to verify the system as a whole, exercising all the components end-to-end and not just in isolation.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide/testing_protected_or_private_members.html ================================================ Testing Protected or Private Members
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When testing a large class, you may find yourself wanting to test protected or private members of the class. The best approach is to test those members by testing the public members of the class. If using the public members of a class requires considerable setup in order to force execution down a particular path that exercises the protected or private member in question, then you may wish to refactor the code to enhance testability.

The most expedient technique for protected members is to raise their visibility through derivation. Suppose we have a base class B with a protected member p that we wish to test:

class B
{
// ... other stuff in B
protected:
    bool p();
};

We can derive a class D in the test code from the class B in the production code that raises the visibility of p:

class D : public B
{
// ... other stuff needed to build a D from a B
public:
    using B::p;
};

Now we can write a test for D::p.

While this certainly seems expedient, it's annoying to write these derived classes simply for the purposes of hoisting members into public visibility. It also just feels dirty. We're taking implementation details that are supposed to be hidden from consumers of the class and we're exposing them. If we are not diligent and watchful, this class D in the test project that was only intended for testing may find itself showing up in the production code.

Maybe the problem isn't one of visibility but that we simply aren't listening closely enough to the code in the first place. As Herb Sutter shows us in Uses and Abuses of Access Rights, the "Liar", the "Pickpocket", the "Cheat" and the "Language Lawyer" can all find ways to subvert the access protections afforded to a class.

When we are tempted to test non-public methods of a class, it's because we feel that there is sufficient complexity in these non-public methods to warrant testing them. What if that complexity is trying to tell us something? If our class is so complex, isn't it possible that it's violating the Single Responsibility Principle? Maybe the class is trying to encompass several responsibilities and should be decomposed into two or more classes, each with a single responsibility. We could perform the Extract Class refactoring to create two classes with appropriate public interfaces and then write tests against those new public interfaces.

Another choice is to refactor the original class using the "pimpl idiom", elevate the visibility to public of all the methods on the implementation class and write tests against the implementation class. This has the same downsides as the derive-and-elevate approach and we're still ignoring the whispers of the code.

When your code is hard to test, your code is telling you something. Listen to the code!


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/guide.html ================================================ User's Guide
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/how_to_read_this_documentation.html ================================================ How To Read This Documentation
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This documentation provides material for both new users and advanced users. If you are completely new to automated testing, you may wish to read Wikipedia's article on test-driven development and consult the online book xUnit Test Patterns. The amount of information available on automated testing has exploded in the past decade and these are only some suggested starting points and not intended to be an exhaustive list.

To get started quickly writing your first test, read the tutorial sections. For advice on designing and maintaining your tests, read the section on test case design. For advanced uses of the library, consult the reference.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/motivation.html ================================================ Motivation
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Automated tests are an important part of verifying software. At the developer level, automated tests provide confidence that changes made to the software do not result in new defects. At the customer level, automated tests provide confidence that new features meet expectations and existing features continue to function unchanged.

Boost.Test is a library that supports the automated testing of software, primarily aimed at satisfying the needs of the developer.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___bitwise_equal_.html ================================================ BOOST_level_BITWISE_EQUAL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BITWISE_level_EQUAL(lhs, rhs) compares the two arguments for bitwise equality and fails if they are not equal. This can be useful when testing integral values that represent a logical or combination of bit flags.

Example

enum bit_flags
{
    source_file = 1u,
    header_file = 2u,
    build_file = 4u
};

BOOST_AUTO_TEST_CASE(example_bitwise_equal)
{
    BOOST_REQUIRE_BITWISE_EQUAL(
        source_file | build_file,
        build_file | source_file);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___close_.html ================================================ BOOST_level_CLOSE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_CLOSE(lhs, rhs, tolerance) compares the two floating-point arguments and considers them equal if they agree within the given tolerance. The tolerance is given as a percentage.

Example

BOOST_AUTO_TEST_CASE(example_close)
{
    BOOST_REQUIRE_CLOSE(100.f, 100.9f, 1.f);
    BOOST_REQUIRE_CLOSE(100.f, 99.1f, 1.f);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___close_fraction_.html ================================================ BOOST_level_CLOSE_FRACTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_CLOSE_FRACTION(lhs, rhs, tolerance) compares the two floating-point arguments and considers them equal if they agree within the given tolerance. The tolerance is given as a percentage.

Example

BOOST_AUTO_TEST_CASE(example_close_fraction)
{
    BOOST_REQUIRE_CLOSE_FRACTION(100.f, 100.9f, 1.f);
    BOOST_REQUIRE_CLOSE_FRACTION(100.f, 99.1f, 1.f);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___equal_collections_.html ================================================ BOOST_level_EQUAL_COLLECTIONS
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_EQUAL_COLLECTIONS(lhs_begin, lhs_end, rhs_begin, rhs_end) compares two collections for equality. Two collections are considered equal if they have the same number of elements and the elements compare equal by operator==. The elements are obtained through the supplied iterators on the collections. The diagnostic message is constructed from applying operator<< to each of the elements in the collections.

[Important] Important

If you get a strange compile error when using BOOST_EQUAL_COLLECTIONS, check that the appropriate operator== and operator<< are defined for the element type in the collection. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

static std::list<int> generate_list()
{
    std::list<int> l;
    l.push_front(3);
    l.push_front(2);
    l.push_front(1);

    return l;
}

BOOST_AUTO_TEST_CASE(example_equal_collections)
{
    std::vector<int> expected;
    expected.push_back(1);
    expected.push_back(2);
    expected.push_back(3);

    std::list<int> actual = generate_list();

    BOOST_REQUIRE_EQUAL_COLLECTIONS(
        expected.begin(), expected.end(),
        actual.begin(), actual.end());
}

BOOST_AUTO_TEST_CASE(example_equal_collections_pod)
{
    int const expected[] = { 1, 2, 3 };

    std::list<int> actual = generate_list();

    BOOST_REQUIRE_EQUAL_COLLECTIONS(
        &expected[0], &expected[sizeof(expected)/sizeof(expected[0])],
        actual.begin(), actual.end());
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___exception_.html ================================================ BOOST_level_EXCEPTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_EXCEPTION(statement, exception, predicate) asserts that when statement throws an exception of type exception, the predicate applied to the instance of the exception returns true. This is used to verify not only that an exception of the correct type was thrown, but that the contents of the thrown exception meet the expectations of the predicate.

class error_number_exception
{
public:
    error_number_exception(int num)
        : num_(num)
    { }

    int error_number() const { return num_; }

private:
    int num_;
};

static bool has_error_number_1(error_number_exception const& ex)
{
    return ex.error_number() == 1;
}

BOOST_AUTO_TEST_CASE(example_exception)
{
    BOOST_REQUIRE_EXCEPTION(throw error_number_exception(1), error_number_exception, has_error_number_1);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___ge_.html ================================================ BOOST_level_GE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_GE(lhs, rhs) asserts that lhs is greater than or equal to rhs. The comparison is made by applying operator>= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_GE, check that the appropriate operator>= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

BOOST_AUTO_TEST_CASE(example_ge)
{
    // integral types
    unsigned const u = 1u;
    int const i = -10;
    char const A = 'A';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_GE(2u, u);
    BOOST_REQUIRE_GE(1u, u);
    BOOST_REQUIRE_GE(-9, i);
    BOOST_REQUIRE_GE(-10, i);
    BOOST_REQUIRE_GE('B', A);
    BOOST_REQUIRE_GE('A', A);
    BOOST_REQUIRE_GE("scoobz", s);
    BOOST_REQUIRE_GE("scooby", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___gt_.html ================================================ BOOST_level_GT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_GT(lhs, rhs) asserts that lhs is greater than rhs. The comparison is made by applying operator> to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_GT, check that the appropriate operator> and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

BOOST_AUTO_TEST_CASE(example_gt)
{
    // integral types
    unsigned const u = 1u;
    int const i = -10;
    char const A = 'A';
    // standard library types providing operator> and operator==
    std::string const s = "scooby";

    BOOST_REQUIRE_GT(2u, u);
    BOOST_REQUIRE_GT(-9, i);
    BOOST_REQUIRE_GT('B', A);
    BOOST_REQUIRE_GT("scoobz", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___le_.html ================================================ BOOST_level_LE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_LE(lhs, rhs) asserts that lhs is less than or equal to rhs. The comparison is made by applying operator<= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_LE, check that the appropriate operator<= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

BOOST_AUTO_TEST_CASE(example_le)
{
    // integral types
    unsigned const u = 10u;
    int const i = -10;
    char const M = 'M';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_LE(9u, u);
    BOOST_REQUIRE_LE(10u, u);
    BOOST_REQUIRE_LE(-11, i);
    BOOST_REQUIRE_LE(-10, i);
    BOOST_REQUIRE_LE('L', M);
    BOOST_REQUIRE_LE('M', M);
    BOOST_REQUIRE_LE("scoobx", s);
    BOOST_REQUIRE_LE("scooby", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___lt_.html ================================================ BOOST_level_LT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_LT(lhs, rhs) asserts that lhs is less than rhs. The comparison is made by applying operator< to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_LT, check that the appropriate operator< and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

BOOST_AUTO_TEST_CASE(example_lt)
{
    // integral types
    unsigned const u = 10u;
    int const i = -10;
    char const M = 'M';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_LT(9u, u);
    BOOST_REQUIRE_LT(-11, i);
    BOOST_REQUIRE_LT('L', M);
    BOOST_REQUIRE_LT("scoobx", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___message_.html ================================================ BOOST_level_MESSAGE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_MESSAGE(predicate, message) emits message if the supplied predicate evaluates to false. The message is applied to an output stream with operator<< and the argument can contain additional applications of operator<< for building up complex messages. The predicate can return bool or predicate_result.

static int g_i;

// simple predicate
static bool global_int_is_positive()
{
    return g_i > 0;
}

// predicate that builds up detail message
static boost::test_tools::predicate_result global_int_equal(int expected)
{
    if (g_i == expected)
    {
        return true;
    }

    boost::test_tools::predicate_result failed = false;
    failed.message() << "g_i != " << expected << "; actual: " << g_i;
    return failed;
}

BOOST_AUTO_TEST_CASE(example_message)
{
    g_i = 1;

    BOOST_REQUIRE_MESSAGE(global_int_is_positive(),
        "g_i is not positive; actual: " << g_i);
    BOOST_REQUIRE_MESSAGE(global_int_equal(1), "");
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___ne_.html ================================================ BOOST_level_NE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_NE(lhs, rhs) asserts that lhs is not equal to rhs. The comparison is made by applying operator!= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_NE, check that the appropriate operator!= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Example

BOOST_AUTO_TEST_CASE(example_ne)
{
    // integral types
    unsigned const u = 1u;
    int const i = -1;
    char const A = 'A';
    // standard library types providing operator!= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_NE(2u, u);
    BOOST_REQUIRE_NE(-2, i);
    BOOST_REQUIRE_NE('B', A);
    BOOST_REQUIRE_NE("scoobz", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___no_throw_.html ================================================ BOOST_level_NO_THROW
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_NO_THROW(statement) asserts that statement does not throw an exception.

BOOST_AUTO_TEST_CASE(example_no_throw)
{
    BOOST_REQUIRE_NO_THROW(1 + 1);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___predicate_.html ================================================ BOOST_level_PREDICATE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_PREDICATE(predicate, args) asserts that the supplied predicate applied to args evaluates to true. The supplied predicate must have a return type of bool and argument types that are compatible with the argument list args. Because BOOST_level_PREDICATE is a macro, the args must be supplied as a sequence of parenthesized values, with no comma separating the values.

Example

static bool custom_string_compare(char const* const expected, char const* const actual)
{
    return std::strcmp(expected, actual) == 0;
}

BOOST_AUTO_TEST_CASE(example_predicate)
{
    char const* const s = "scooby";

    BOOST_REQUIRE_PREDICATE(custom_string_compare, ("scooby")(s));
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost____level___small_.html ================================================ BOOST_level_SMALL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_SMALL(value, tolerance) checks that the value is within tolerance of zero.

Example

BOOST_AUTO_TEST_CASE(example_small)
{
    float const f = 0.1f;

    BOOST_REQUIRE_SMALL(f, 0.25f);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost_test_dont_print_log_value_.html ================================================ BOOST_TEST_DONT_PRINT_LOG_VALUE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_DONT_PRINT_LOG_VALUE(type) instructs the test framework to ignore values of type type when constructing diagnostic messages. It does this by defining an empty implementation of a print function specialized for type. Because the specialization is inside an implementation namespace for Boost.Test, the macro must be invoked at the global namespace scope. Therefore, it cannot be used inside a test suite or any other namespace.

Example

struct custom
{
    int value;
};

BOOST_TEST_DONT_PRINT_LOG_VALUE(custom);

static bool operator==(custom const& expected, custom const& actual)
{
    return expected.value == actual.value;
}

BOOST_AUTO_TEST_CASE(example_test_dont_print_log_value)
{
    custom const v1 = { 1 };
    custom const v2 = { 1 };
    BOOST_REQUIRE_EQUAL(v1, v2);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost_test_error_.html ================================================ BOOST_TEST_ERROR
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_ERROR(message) always fails and emits the given message at the CHECK assertion level.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/_boost_test_is_defined_.html ================================================ BOOST_TEST_IS_DEFINED
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_IS_DEFINED(symbol) asserts that symbol is a defined value.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_fail.html ================================================ BOOST_FAIL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_FAIL(message) always fails and emits the given message at the REQUIRE assertion level. Other assertion macros are generally preferred over BOOST_FAIL because they emit better diagnostics in the case of failure.

There are two situations where you might be tempted to use BOOST_FAIL: testing the situations where the system under test will throw exceptions or comparing against the values computed by the system under test. For testing exception generation, use BOOST_REQUIRE_THROW, BOOST_REQUIRE_NO_THROW or BOOST_REQUIRE_EXCEPTION. For testing against values computed by the system under test, use the comparing assertions.

Example

BOOST_AUTO_TEST_CASE(example_fail)
{
    BOOST_FAIL("This should never happen.");
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_level_equal.html ================================================ BOOST_level_EQUAL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_EQUAL(lhs, rhs) compares the two arguments with operator==. The diagnostic message is constructed with operator<< on the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_EQUAL, check that the appropriate operator== and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

Examples

BOOST_AUTO_TEST_CASE(example_equal)
{
    // integral types
    unsigned const u = 1u;
    int const i = -1;
    char const A = 'A';
    // standard library types providing operator== and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_EQUAL(1u, u);
    BOOST_REQUIRE_EQUAL(-1, i);
    BOOST_REQUIRE_EQUAL('A', A);
    BOOST_REQUIRE_EQUAL("scooby", s);
}

// custom data structure
struct symbol
{
    char const* const name;
    int value;
};

// custom comparison operator
static bool operator==(symbol const& lhs, symbol const& rhs)
{
    return lhs.value == rhs.value
        && std::string(lhs.name) == std::string(rhs.name);
}

// custom stream insertion operator
static std::ostream& operator<<(std::ostream& stream, symbol const& value)
{
    return stream << value.name << ": " << value.value;
}

BOOST_AUTO_TEST_CASE(example_equal_custom_compare)
{
    symbol const s1 = { "var" , 1 };
    symbol const s2 = { "var", 1 };
    // If the compiler doesn't collapse multiple constants, then:
    // s1.name != s2.name;

    BOOST_REQUIRE_EQUAL(s1, s2);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_level_exception.html ================================================ BOOST_level_EXCEPTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_EXCEPTION(expression, exception, predicate) asserts that when expression throws an exception of type exception, the predicate applied to the instance of the exception returns true. This is used to verify not only that an exception of the correct type was thrown, but that the contents of the thrown exception meet the expectations of the predicate.

The predicate can return bool, or predicate_result which allows the predicate to build up a detailed failure message.

Example

class error_number_exception
{
public:
    error_number_exception(int num)
        : num_(num)
    { }

    int error_number() const { return num_; }

private:
    int num_;
};

static bool has_error_number_1(error_number_exception const& ex)
{
    return ex.error_number() == 1;
}

BOOST_AUTO_TEST_CASE(example_exception)
{
    BOOST_REQUIRE_EXCEPTION(throw error_number_exception(1),
        error_number_exception, has_error_number_1);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_level_message.html ================================================ BOOST_level_MESSAGE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_MESSAGE(predicate, message) emits message if the supplied predicate evaluates to false. The message is applied to an output stream with operator<< and the argument can contain additional applications of operator<< for building up complex messages. The predicate can return bool or predicate_result.

Example

static int g_i;

// simple predicate
static bool global_int_is_positive()
{
    return g_i > 0;
}

// predicate that builds up detail message
static boost::test_tools::predicate_result global_int_equal(int expected)
{
    if (g_i == expected)
    {
        return true;
    }

    boost::test_tools::predicate_result failed = false;
    failed.message() << "g_i != " << expected << "; actual: " << g_i;
    return failed;
}

BOOST_AUTO_TEST_CASE(example_message)
{
    g_i = 1;

    BOOST_REQUIRE_MESSAGE(global_int_is_positive(),
        "g_i is not positive; actual: " << g_i);
    BOOST_REQUIRE_MESSAGE(global_int_equal(1), "g_i equals 1");
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_level_no_throw.html ================================================ BOOST_level_NO_THROW
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_NO_THROW(expression) asserts that expression does not throw an exception.

Example

BOOST_AUTO_TEST_CASE(example_no_throw)
{
    BOOST_REQUIRE_NO_THROW(1 + 1);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_level_throw.html ================================================ BOOST_level_THROW
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_THROW(expression, exception) asserts that expression throws an exception of type exception or a type derived from exception.

Example

static void always_throws()
{
    throw std::runtime_error("whoops");
}

BOOST_AUTO_TEST_CASE(example_throw)
{
    BOOST_REQUIRE_THROW(always_throws(), std::runtime_error);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/boost_test_dont_print_log_value.html ================================================ BOOST_TEST_DONT_PRINT_LOG_VALUE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_DONT_PRINT_LOG_VALUE(type) instructs the test framework to ignore values of type type when constructing diagnostic messages. It does this by defining an empty implementation of a print function specialized for type. Because the specialization is inside an implementation namespace for Boost.Test, the macro must be invoked at the global namespace scope. Therefore, it cannot be used inside a test suite or any other namespace.

Example

struct custom
{
    int value;
};

BOOST_TEST_DONT_PRINT_LOG_VALUE(custom);

static bool operator==(custom const& expected, custom const& actual)
{
    return expected.value == actual.value;
}

BOOST_AUTO_TEST_CASE(example_test_dont_print_log_value)
{
    custom const v1 = { 1 };
    custom const v2 = { 1 };
    BOOST_REQUIRE_EQUAL(v1, v2);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion/levels.html ================================================ Assertion Levels
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When using the library or header-only version of Boost.Test, many assertion macros are provided in three levels that determine the behavior when the assertion fails and how a failed assertion interacts with the test runner.

Table 1.2. Assertion Levels

Level

Test Case Fails?

Aborts Execution?

WARN

No

No

CHECK

Yes

no

REQUIRE

Yes

Yes


The WARN level issues a diagnostic message, but the test case is not considered to have failed and continues executing. The CHECK level issues a message to the test log on failure, marks the test case as failed and continues executing. The REQUIRE level issues a message to the test log on failure, marks the test case as failed and halts execution of the test case.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/assertion.html ================================================ Test Assertions
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Assertions are used to validate the result of exercising the system under test. When an assertion fails, a diagnostic message is created and the failed assertion is recorded. Different assertion levels allow you to control how a failed assertion is interpreted by the test runner.

[Important] Important

When an assertion involves a user-defined datatype, a stream insertion operator (operator<<) must be defined for the user-defined datatype, or the assertion will fail to compile. Asserting a comparison operation on a value of a user-defined type will require the appropriate comparison operator (operator<, operator==, etc.) be defiend for the type or the assertion will fail to compile. The need to define operator<< can be eliminated by using BOOST_TEST_DONT_PRINT_LOG_VALUE.

The minimal header test framework does not provide the facilities described here.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/configuration_macros.html ================================================ Configuration Macros
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Macro

Meaning

BOOST_TEST_ALTERNATIVE_INIT_API

When defined, the alternative init_unit_test_func test module initialization API is used.

BOOST_TEST_DYN_LINK

When defined, the implementation is compiled as a shared library. Defining BOOST_TEST_DYN_LINK also defines BOOST_TEST_ALTERNATIVE_INIT_API.

BOOST_TEST_MAIN

When defined, an implementation of main is included in the source file.

BOOST_TEST_MODULE

When defined, it provides the name of the master test suite, otherwise a default name is used.

BOOST_TEST_NO_LIB

When defined, no automatic linking is performed.

BOOST_TEST_NO_MAIN

When defined, no implementation of main is provided in any configuration. Static and shared libraries must have been built with this symbol defined for it to take effect when using the library. The test executable must provide its own implementation of main; unit_test_main may be used for this purpose.

When using any of these macros, they must be defined before including any header from Boost.Test.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/headers.html ================================================ Header Files
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHome

#include <boost/test/debug.hpp>

namespace boost { namespace test {

bool under_debugger();

void debugger_break();

struct dbg_startup_info {
    long                    pid;
    bool                    break_or_continue;
    unit_test::const_string binary_path;
    unit_test::const_string display;
    unit_test::const_string init_done_lock;
};

typedef boost::function<void (dbg_startup_info const&)> dbg_starter;

std::string set_debugger( unit_test::const_string dbg_id, dbg_starter s = dbg_starter() );

bool attach_debugger( bool break_or_continue = true );

void detect_memory_leaks( bool on_off, unit_test::const_string report_file = unit_test::const_string() );

void break_memory_alloc( long mem_alloc_order_num );

}} // boost::test

#include <boost/test/debug_config.hpp

BOOST_TEST_DBG_LIST

BOOST_TEST_STAT_LINE_MAX

#include <boost/test/execution_monitor.hpp>

namespace boost {

class execution_exception {
    typedef boost::unit_test::const_string const_string;
public:
    enum error_code {
        no_error               = 0,
        user_error             = 200,
        cpp_exception_error    = 205,
        system_error           = 210,
        timeout_error          = 215,
        user_fatal_error       = 220,
        system_fatal_error     = 225
    };

    struct BOOST_TEST_DECL location {
        explicit    location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );

        const_string    m_file_name;
        size_t          m_line_num;
        const_string    m_function;
    };

    // Constructor
    execution_exception( error_code ec_, const_string what_msg_, location const& location_ ); // max length 256 inc '\0'

    // Access methods
    error_code      code() const    { return m_error_code; }
    const_string    what() const    { return m_what; }
    location const& where() const   { return m_location; }
}; // execution_exception

class execution_monitor {
    typedef boost::unit_test::const_string const_string;
public:
    execution_monitor();

    // Public properties

    //  The p_catch_system_errors parameter specifies whether the monitor should 
    //  try to catch system errors/exceptions that would cause program to crash 
    //  in regular case
    unit_test::readwrite_property<bool> p_catch_system_errors;

    //  The p_auto_start_dbg parameter specifies whether the monitor should 
    //  try to attach debugger in case of caught system error
    unit_test::readwrite_property<bool> p_auto_start_dbg;

    //  The p_timeout parameter specifies the seconds that elapse before
    //  a timer_error occurs.  May be ignored on some platforms.
    unit_test::readwrite_property<int>  p_timeout;

    //  The p_use_alt_stack parameter specifies whether the monitor should
    //  use alternative stack for the signal catching
    unit_test::readwrite_property<bool> p_use_alt_stack;

    //  The p_detect_fp_exceptions parameter specifies whether the monitor should
    //  try to detect hardware floating point exceptions (!= 0), and which specific exception to catch
    unit_test::readwrite_property<unsigned> p_detect_fp_exceptions;

    int         execute( boost::function<int ()> const& F );
    //  Returns:  Value returned by function call F().
    //
    //  Effects:  Calls executes supplied function F inside a try/catch block which also may
    //  include other unspecified platform dependent error detection code.
    //
    //  Throws: execution_exception on an uncaught C++ exception,
    //  a hardware or software signal, trap, or other exception.
    //
    //  Note: execute() doesn't consider it an error for F to return a non-zero value.

    void         vexecute( boost::function<void ()> const& F );
    //  Effects:  Same as above, but returns nothing

    // register custom (user supplied) exception translator
    template<typename ExceptionType, typename ExceptionTranslator>
    void        register_exception_translator( ExceptionTranslator const& tr, const_string tag = const_string(), boost::type<ExceptionType>* = 0 );

    // erase custom exception translator
    void        erase_exception_translator( const_string tag )
    {
        m_custom_translators = m_custom_translators->erase( m_custom_translators, tag );
    }
    template<typename ExceptionType>
    void        erase_exception_translator( boost::type<ExceptionType>* = 0 )
    {
        m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
    }

}; // execution_monitor

template<typename ExceptionType, typename ExceptionTranslator>
void
execution_monitor::register_exception_translator( ExceptionTranslator const& tr, const_string tag, boost::type<ExceptionType>* )
{
    m_custom_translators.reset(
        new detail::translator_holder<ExceptionType,ExceptionTranslator>( tr, m_custom_translators, tag ) );
}

struct execution_aborted {};

class system_error {
public:
    // Constructor
    explicit    system_error( char const* exp );

    unit_test::readonly_property<long>          p_errno;
    unit_test::readonly_property<char const*>   p_failed_exp;
};

#define BOOST_TEST_SYS_ASSERT( exp ) if( (exp) ) ; else throw ::boost::system_error( BOOST_STRINGIZE( exp ) )

namespace fpe {

enum masks {
    BOOST_FPE_OFF       = 0,

#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
    BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE,
    BOOST_FPE_INEXACT   = EM_INEXACT,
    BOOST_FPE_INVALID   = EM_INVALID,
    BOOST_FPE_OVERFLOW  = EM_OVERFLOW,
    BOOST_FPE_UNDERFLOW = EM_UNDERFLOW|EM_DENORMAL,

    BOOST_FPE_ALL       = MCW_EM,
#elif defined(BOOST_NO_FENV_H) || defined(BOOST_CLANG)
    BOOST_FPE_ALL       = 1,
#else
    BOOST_FPE_DIVBYZERO = FE_DIVBYZERO,
    BOOST_FPE_INEXACT   = FE_INEXACT,
    BOOST_FPE_INVALID   = FE_INVALID,
    BOOST_FPE_OVERFLOW  = FE_OVERFLOW,
    BOOST_FPE_UNDERFLOW = FE_UNDERFLOW,

    BOOST_FPE_ALL       = FE_ALL_EXCEPT,
#endif
    BOOST_FPE_INV       = BOOST_FPE_ALL+1
};

// return the previous set of enabled exceptions when successful, and BOOST_FPE_INV otherwise
unsigned BOOST_TEST_DECL enable( unsigned mask );
unsigned BOOST_TEST_DECL disable( unsigned mask );

} // namespace fpe
} // namespace boost

PrevUpHome
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___break_exec_path_.html ================================================ --break_exec_path
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When performing an exception safety test, this argument forces a break into the debugger at the named exection path point within the test name. The test must be named exactly, no wildcards are supported.

Value

Meaning

name:path

For test case name, break on execution path number path.

Environment variable: BOOST_TEST_BREAK_EXEC_PATH


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___build_info_.html ================================================ --build_info
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument causes the test runner to report information about the build environment before running the tests. If the argument is specified but no value is given, then a value of yes is assumed.

Value

Meaning

no (default)

Do not report build information.

yes

Report build information.

Environment variable: BOOST_TEST_BUILD_INFO


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___catch_system_errors_.html ================================================ --catch_system_errors
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls whether or not the test runner catches fatal system errors.

Value

Meaning

no

Do not handle fatal system errors.

yes (default)

Handle fatal system errors.

Environment variable: BOOST_TEST_CATCH_SYSTEM_ERRORS


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___color_output_.html ================================================ --color_output
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

On systems that support colored text output, this argument controls whether or not the test runner will color the output. This argument does nothing on systems that do not support colored text output.

Value

Meaning

no (default)

Do not color test runner output.

yes

Color test runner output, if supported.

Environment variable: BOOST_TEST_COLOR_OUTPUT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___detect_fp_exceptions_.html ================================================ --detect_fp_exceptions
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

If the execution environment supoprts floating-point exceptions, this argument controls whether or not the test runner will detect floating-point exceptions.

Value

Meaning

no (default)

Do not detect floating-point exceptions.

yes

Detect floating-point exceptions, if supported.

Environment variable: BOOST_TEST_DETECT_FP_EXCEPTIONS


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___detect_memory_leaks_.html ================================================ --detect_memory_leaks
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

If the execution environment supports the detection of memory leaks, this argument controls whether or not the test runner reports memory leaks. After running the tests, a memory leak report is issued showing the allocation number and the amount of memory leaked.

Values greater than 1 for this argument cause a trap to the debugger for a particular memory allocation number. Currently, this option is only implemented for Microsoft compilers.

Value

Meaning

0

Do not detect memory leaks.

1 (default)

Detect memory leaks and issue a memory leak report.

number

Break on allocation number.

Environment variable: BOOST_TEST_DETECT_MEMORY_LEAKS


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___log_level_.html ================================================ --log_level
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the level of test runner output. The values are cumulative, with each increase in log level including all messages at lower levels. By default, only errors are reported. See test runner log for more information on the log.

Value

Meaning

nothing

Do not report any information.

fatal_error

Report all user or system fatal errors, such as memory access violation.

system_error

Report system non-fatal errors, such as timeout or floating-point exception.

cpp_exception

Report uncaught C++ exceptions.

error (default)

Report test failures.

warning

Report test warnings.

message

Report test messages; see BOOST_TEST_MESSAGE.

test_suite

Report entering and leaving every test case and test suite.

success

Report all successful assertions.

all

Report everything.

Environment variable: BOOST_TEST_LOG_LEVEL


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___log_sink_.html ================================================ --log_sink
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the destination, or sink, of the test runner log. See test runner log for more information on the log.

Value

Meaning

stdout (default)

The test runner log is sent to the standard output stream.

stderr

The test runner log is sent to the standard error stream.

file

The test runner log is sent to the file file.

Environment variable: BOOST_TEST_LOG_SINK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___output_format_.html ================================================ --output_format
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument combines --log_format and --report_format. See test runner log for more information on the log. See test runner report for more information on the report.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_OUTPUT_FORMAT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___random_.html ================================================ --random
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls whether or not the test runner will execute tests in a random order. This argument can also provide a seed for the random number generator used to run tests in a random order.

Value

Meaning

0 (default)

Run tests in registration order.

1

Run tests in a random order, using the current time as the seed.

n

Run tests in a random order, using n as the seed.

Environment variable: BOOST_TEST_RANDOM


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___report_level_.html ================================================ --report_level
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the level of the test report. The levels are cumulative, with each successive level incorporating the output of all the previous levels.

Value

Meaning

no

No test report.

confirm (default)

Confirmation test report.

short

Short test report.

detailed

Detailed test report.

Environment variable: BOOST_TEST_REPORT_LEVEL


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___report_sink_.html ================================================ --report_sink
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the destination, or sink, of the test runner report. See test runner report for more information on the report.

Value

Meaning

stdout

The test report is sent to the standard output stream.

stderr (default)

The test report is sent to the standard error stream.

file

The test report is sent to the file file.

Environment variable: BOOST_TEST_REPORT_SINK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___result_code_.html ================================================ --result_code
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls whether or not the test runner returns an exit code corresponding to a summary of the test execution or zero. The summary result code is determined as follows:

Result Code

Description

0 (boost::exit_success)

All executed tests passed.

200 (boost::exit_exception_failure)

Failure due to uncaught exception.

201 (boost::exit_test_failure)

One or more executed tests failed.

Value

Meaning

no

Always return zero.

yes (default)

Return a status code indicating the summary of the tests executed.

Environment variable: BOOST_TEST_RESULT_CODE


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___save_pattern_.html ================================================ --save_pattern
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument informs the test runner of a boolean value used to create or save a test pattern for file-based testing. The test case uses the boolean value to determine whether or not it writes the test pattern by exercising the system under test or reads the test pattern for comparison against the values produced by the system under test. The output_test_stream class provides a facility for recording and matching against save patterns.

Value

Meaning

no (default)

Match against a saved pattern.

yes

Save a pattern for matching.

Environment variable: BOOST_TEST_SAVE_PATTERN


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___show_progress_.html ================================================ --show_progress
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This parameter instructs the test runner to print progress through the test cases. The test runner has no way of determining the length of time each test case will consume; the progress percentage is determined by counting test cases.

Value

Meaning

no (default)

Do not show test execution progress.

yes

Show test execution progress.

Environment variable: BOOST_TEST_SHOW_PROGRESS


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/___use_alt_stack_.html ================================================ --use_alt_stack
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This parameter instructs the test runner to use an alternate stack for signals processing on platforms where this is supported.

Value

Meaning

no (default)

Do not use an alternate stack.

yes

Use an alternate stack, where supported.

Environment variable: BOOST_TEST_USE_ALT_STACK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/auto_start_dbg.html ================================================ --auto_start_dbg
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls whether or not a debugger is attached to the test runner when a fatal system error occurs. A fatal system error includes Unix/POSIX signals, C++ exceptions and Win32 structured exceptions.

Value

Meaning

no (default)

Do not attach a debugger to when a fatal system error occurs.

yes

Attach the default debugger when a fatal system error occurs.

Environment variable: BOOST_TEST_AUTO_START_DBG


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/list_content.html ================================================ --list_content
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument instructs the test runner to print out an indented listing of all test suites and test cases registered with the test runner without running the tests.

Value

Meaning

no (default)

Do not list test suites and cases.

yes

List test suites and cases and exit without running tests.

Environment variable: BOOST_TEST_LIST_CONTENT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/log_format.html ================================================ --log_format
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the format of the test runner output. The value is case insensitive. See test runner log for more information on the log.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_LOG_FORMAT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/log_level.html ================================================ --log_level
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the level of test runner output. The values are cumulative, with each increase in log level including all messages at lower levels. By default, only errors are reported. See test runner log for more information on the log.

Value

Meaning

nothing

Do not report any information.

fatal_error

Report all user or system fatal errors, such as memory access violation.

system_error

Report system non-fatal errors, such as timeout or floating-point exception.

cpp_exception

Report uncaught C++ exceptions.

error (default)

Report test failures.

warning

Report test warnings.

message

Report test messages; see BOOST_TEST_MESSAGE.

test_suite

Report entering and leaving every test case and test suite.

success

Report all successful assertions.

all

Report everything.

Environment variable: BOOST_TEST_LOG_LEVEL


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/log_sink.html ================================================ --log_sink
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the destination, or sink, of the test runner log. See test runner log for more information on the log.

Value

Meaning

stdout (default)

The test runner log is sent to the standard output stream.

stderr

The test runner log is sent to the standard error stream.

file

The test runner log is sent to the file file.

Environment variable: BOOST_TEST_LOG_SINK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/output_format.html ================================================ --output_format
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument combines --log_format and --report_format. See test runner log for more information on the log. See test runner report for more information on the report.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_OUTPUT_FORMAT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/report_format.html ================================================ --report_format
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the format of the test report. See test runner report for more information on the report.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_REPORT_FORMAT


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/report_level.html ================================================ --report_level
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the level of the test report. The levels are cumulative, with each successive level incorporating the output of all the previous levels. See test runner report for more information on the report.

Value

Meaning

no

No test report.

confirm (default)

Confirmation test report.

short

Short test report.

detailed

Detailed test report.

Environment variable: BOOST_TEST_REPORT_LEVEL


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/report_sink.html ================================================ --report_sink
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls the destination, or sink, of the test runner report. See test runner report for more information on the report.

Value

Meaning

stdout

The test report is sent to the standard output stream.

stderr (default)

The test report is sent to the standard error stream.

file

The test report is sent to the file file.

Environment variable: BOOST_TEST_REPORT_SINK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument/run_test.html ================================================ --run_test
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

This argument controls which test cases will be executed. The value is a comma separated list of test specifiers. Test cases are arranged as leaves on a tree structure, with every test case belonging to a test suite. The test runner always creates a master test suite. Named test suites are children of the master test suite or another named test suite. Any test case that is not the child of a named test suite is a child of the unnamed master test suite.

Test specifiers select test cases or suites by naming the path from the unnamed master test suite to the case or suite, similar to a full path to a file in a hierarchical directory structure. A test specifier is one or more path specifiers, separated by a slash (/). A test specifier begins at the master test suite and proceeds down the test tree, naming suites or test cases.

The argument --report_level set to detailed can be used to output the names of all the test suites and test cases within those test suites.

Path Specifier

Tests Selected

name

The test case or suite named name.

*name

All test cases or suites whose name ends in name.

name*

All test cases or suites whose name begins with name.

*name*

All test cases or suites whose name contains name.

*

All test cases or suites.

spec1,spec2,...

The test cases or suites with the given specifier.

spec1/spec2

The test cases or suites matched by spec2 in the test suite matched by spec1.

Environment variable: BOOST_TESTS_TO_RUN


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/argument.html ================================================ Command Line Arguments
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Table 1.3. Command Line Argument Summary

Argument

Description

--auto_start_dbg

Automatically attach debugger in case of system failure

--build_info

Print build information

--catch_system_errors

Catch system errors

--detect_fp_exceptions

Detect floating-point exceptions

--detect_memory_leaks

Detect memory leaks

--help

Print out a summary of test runner options

--log_format

The format of the test log

--log_level

The level of logging reported

--log_sink

The log sink name

--output_format

The output format

--random

Random number seed

--report_format

The test results report format

--report_level

The test results report level

--report_sink

The report sink name

--result_code

Return result code

--run_test

Tests to run

--show_progress

Show execution progress

--use_alt_stack

Use alternative stack

--wait_for_debugger

Wait for the debugger to attach to the test runner.


The functionality of each command-line option can also be invoked with an environment variable. The description for each option gives the environment variable associated with that option.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/_boost_test_checkpoint_.html ================================================ BOOST_TEST_CHECKPOINT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CHECKPOINT(message) registers a test case checkpoint and associated message with the test runner. A checkpoint includes the source file and line number where the macro was invoked. If the test case is aborted unexpectedly, the source location and message associated with the last registered checkpoint is emitted into the log. Checkpoints can be used to identify the location of an unexpected failure within a block of test case code. The message is applied to an output stream with operator<< and can include other invocations of operator<<.

BOOST_AUTO_TEST_CASE(example_checkpoint)
{
    int const i = 0;
    BOOST_TEST_CHECKPOINT("i = " << i);

    BOOST_REQUIRE(i == 0);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/_boost_test_passpoint_.html ================================================ BOOST_TEST_PASSPOINT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHome

BOOST_TEST_PASSPOINT() is similar to BOOST_TEST_CHECKPOINT, but only registers a source file location with the test runner.

BOOST_AUTO_TEST_CASE(example_passpoint)
{
    BOOST_TEST_PASSPOINT();

    throw std::runtime_error("Oops");
}


PrevUpHome
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/boost_test_checkpoint.html ================================================ BOOST_TEST_CHECKPOINT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CHECKPOINT(message) registers a test case checkpoint and associated message with the test runner. A checkpoint includes the source file and line number where the macro was invoked. If the test case is aborted unexpectedly, the source location and message associated with the last registered checkpoint is emitted into the log. Checkpoints can be used to identify the location of an unexpected failure within a block of test case code. The message is applied to an output stream with operator<< and can include other invocations of operator<<.

BOOST_AUTO_TEST_CASE(example_checkpoint)
{
    int const i = 0;
    BOOST_TEST_CHECKPOINT("i = " << i);

    BOOST_REQUIRE(i == 0);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/boost_test_message.html ================================================ BOOST_TEST_MESSAGE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_MESSAGE(message) unconditionally writes the message into the test runner log file. Unlike BOOST_TEST_CHECKPOINT no file and line number information is written into the log file. The message is applied to an output stream with operator<< and can include other invocations of operator<<.

BOOST_AUTO_TEST_CASE(example_test_message)
{
    int const i = 0;
    BOOST_TEST_MESSAGE("i = " << i);

    BOOST_REQUIRE(i == 0);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/log.html ================================================ Test Log
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test log contains detailed information on every assertion in every test case. The log can be formatted as plain human readable text or as XML and can be sent to the standard output stream, the standard error stream or a file.

The amount of detail in the log is set with the --log_level option. The format of the log is set with the --log_format option. The destination of the log is set with the --log_sink option. The --output_format option sets both the log format and the report format.

The XML format for the test log conforms to the schema UTF.log.xsd.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/report.html ================================================ Test Report
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The report contains summary information about the test cases executed and the count of failures. The report can be formatted as plain human readable text or as XML and can be sent to the standard output stream, standard error stream or a file.

The amount of detail in the report is controlled by the --report_level option. The format of the report can be changed with the --report_format option. The destination of the report can be set with the --report_sink option. The --output_format option sets both the report format and the log format.

The XML format for the test report conforms to the schema UTF.report.xsd.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/test_log.html ================================================ Test Log
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output/test_report.html ================================================ Test Report
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner/output.html ================================================ Test Output
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/runner.html ================================================ Test Runner
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_auto_test_case.html ================================================ BOOST_AUTO_TEST_CASE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_AUTO_TEST_CASE(name) creates a test case class, a test case invocation function, a test case unique identifier, registers the invocation function as a test case and begins the definition of the test method on the test class. The test case class name is derived from BOOST_AUTO_TEST_CASE_FIXTURE and contains a single method named test_method. The test invocation function instantiates the test case class and invokes the test case method. Test log checkpoints are made before the test case class is instantiated and bracketing the test method invocation. This provides diagnostic checkpoints should a runtime error cause a test case to be aborted before any assertions are made.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_auto_test_case_expected_failures.html ================================================ BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(name, n) is used to decorate a test case with an expected failure count of n. It should appear immediately preceding the macro that defines the test case, such as BOOST_AUTO_TEST_CASE or BOOST_FIXTURE_TEST_CASE. It can be used for test cases declared at file scope or within a test suite. This macro should only be used in the most exceptional of circumstances. Unit tests are designed to provide a safety net of regression tests against our code. If we allow tests to stay failing, we are less motivated to correct them.

As a temporary measure, we may wish to annotate certain tests as known failures. The count n is the number of expected failed assertions during the execution of the test case. When using the CHECK level assertions, the total failure count can be larger than one since the test case continues executing past a failed assertion. When using REQUIRE level assertions, the total failure count will only be one as execution of the test case terminates on the first failed assertion.

If CHECK level assertions are used and the number of failures is less than or equal to n, the test runner will return a status code of 0. If the number of failures is greather than n, the test runner will return a status code of 201. If REQUIRE level assertions are used, the number of expected failures can be at most one and the test runner will return a status code of 200 when one failed assertion is found.

BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(inserts_text_require_expected, 1)
BOOST_AUTO_TEST_CASE(inserts_text_require_expected)
{
    std::ostringstream dest;

    hello_world(dest);

    BOOST_REQUIRE_EQUAL("scooby-doo", dest.str());
}

[Note] Note

When using the compiler formatted test output, Visual Studio interprets the failed assertion output as a detected error, it will fail the Post-Build event mechanism recommended in Test Case Design and Maintenance.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_auto_test_case_template.html ================================================ BOOST_AUTO_TEST_CASE_TEMPLATE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_AUTO_TEST_CASE_TEMPLATE(name, var, types) declares a test case name parameterized by a single template argument var that is evaluated for each type in types. This allows you to write a test case that exercises an invariant across a collection of types. The macro expands into one test case for each type in types, with the template argument var assigned to each type. The types argument must be a Boost.MPL type list and must be defined as a typedef.

#include <boost/mpl/list.hpp>
#include <limits>

typedef boost::mpl::list<
    unsigned char, unsigned short,
    unsigned int,
    unsigned long, unsigned long long> unsigned_types;

BOOST_AUTO_TEST_CASE_TEMPLATE(not_is_signed_for_unsigned_types, T, unsigned_types)
{
    BOOST_REQUIRE(!std::numeric_limits<T>::is_signed);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_fixture_test_case.html ================================================ BOOST_FIXTURE_TEST_CASE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_FIXTURE_TEST_CASE(name, fixture) defines a test case class name that derives from fixture. If the test case is declared within a test suite that also has a test fixture, then to get the cumulative effect of both fixtures the test case fixture should derive from the test suite's fixture. Otherwise, the test case fixture will replace the test suite fixture for a test case defined with BOOST_FIXTURE_TEST_CASE.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_global_fixture.html ================================================ BOOST_GLOBAL_FIXTURE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_GLOBAL_FIXTURE(name) declares a global fixture that is constructed before executing any test cases and is destroyed after executing all test cases. If more than one global fixture is defined in a single source file, the fixtures are constructed in the order they appear in the source file and destroyed in the reverse order. If global fixtures are defined in multiple source files, the order in which global fixtures are initialized between source files is implementation dependent.

Because global fixtures are not created and destroyed for each test case, they represent shared state that prevents test cases from executing independently from each other. For this reason, test case fixtures created with BOOST_FIXTURE_TEST_CASE and test suite fixtures created with BOOST_FIXTURE_TEST_SUITE are preferred over global fixtures.

struct global_fixture
{
    global_fixture()
    {
        std::cout << "global setup\n";
    }
    ~global_fixture()
    {
        std::cout << "global teardown\n";
    }
};

BOOST_GLOBAL_FIXTURE(global_fixture);

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_param_class_test_case.html ================================================ BOOST_PARAM_CLASS_TEST_CASE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_PARAM_CLASS_TEST_CASE(memfn, instance, begin, end) works similarly to BOOST_PARAM_TEST_CASE. It creates a collection of test cases that invoke the member function memfn on the instance pointer instance. The member function is passed an item obtained by iterating the collection defined by the begin and end iterators. The instance pointer must be passed as a boost::shared_ptr to ensure the lifetime of the instance exceeds that of any test case using the instance. The test case returned by BOOST_PARAM_CLASS_TEST_CASE must be added to a test suite in an initialization function for the tests to be executed.

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>

using namespace boost::unit_test;

class hello_world_tester
{
public:
    hello_world_tester()
    {
        eq_items.push_back("Hello, world!\n");
        eq_items.push_back("Hello, world!\n");
        ne_items.push_back("shaggy");
        ne_items.push_back("scooby");
    }

    void inserts_text(std::string const& text)
    {
        std::ostringstream dest;

        hello_world(dest);

        BOOST_REQUIRE_EQUAL(text, dest.str());
    };

    void does_not_insert_text(std::string const& text)
    {
        std::ostringstream dest;

        hello_world(dest);

        BOOST_REQUIRE_NE(text, dest.str());
    }

    std::vector<std::string> eq_items;
    std::vector<std::string> ne_items;
};

boost::shared_ptr<hello_world_tester> tester(boost::make_shared<hello_world_tester>());

static test_suite*
init(int argc, char* argv[])
{
    test_suite& suite = framework::master_test_suite();
    suite.add(BOOST_PARAM_CLASS_TEST_CASE(
        &hello_world_tester::inserts_text, tester,
        tester->eq_items.begin(), tester->eq_items.end()));
    suite.add(BOOST_PARAM_CLASS_TEST_CASE(
        &hello_world_tester::does_not_insert_text, tester,
        tester->ne_items.begin(), tester->ne_items.end()));
    return 0;
}

int main(int argc, char* argv[])
{
    return unit_test_main(init, argc, argv);
}

[Note] Note

The single instance is shared among all test cases and therefore should not keep any shared state that may couple independent test cases. In this example, the output string stream is created fresh inside each test method and not shared between calls to the method.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_param_test_case.html ================================================ BOOST_PARAM_TEST_CASE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_PARAM_TEST_CASE(fn, begin, end) creates a series of test cases that invoking the callable object fn on the items in the collection defined by begin and end. The test case returned by BOOST_PARAM_TEST_CASE must be added to a test suite in an initialization function for the tests to be executed. The iterators begin and end must be valid at the time the test case executes and not just at the time the test case is created.

using namespace boost::unit_test;

static void does_not_insert_text(std::string const& text)
{
    std::ostringstream dest;

    hello_world(dest);

    BOOST_REQUIRE_NE(text, dest.str());
}

static std::vector<std::string> text;

static test_suite*
init(int argc, char* argv[])
{
    text.push_back("scooby");
    text.push_back("shaggy");
    text.push_back("foo");
    text.push_back("arg");
    framework::master_test_suite()
        .add(BOOST_PARAM_TEST_CASE(does_not_insert_text, text.begin(), text.end()));
    return 0;
}

int main(int argc, char* argv[])
{
    return unit_test_main(init, argc, argv);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_test_case.html ================================================ BOOST_TEST_CASE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CASE(fn) creates a new test case named "fn" that executes the callable function fn. The test case returned by BOOST_TEST_CASE must be added to a test suite in an initialization function for the tests to be executed.

#define BOOST_TEST_NO_MAIN
#include <boost/test/included/unit_test.hpp>
#include "hello.hpp"
#include <sstream>

using namespace boost::unit_test;

static void inserts_text()
{
    std::ostringstream dest;

    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

static test_suite*
init(int argc, char* argv[])
{
    framework::master_test_suite().add(BOOST_TEST_CASE(inserts_text));
    return 0;
}

int main(int argc, char* argv[])
{
    return unit_test_main(init, argc, argv);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_test_case_template.html ================================================ BOOST_TEST_CASE_TEMPLATE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CASE_TEMPLATE(name, types) manually creates a set of test cases from the template test case name for each type in types. The test case returned by BOOST_TEST_CASE_TEMPLATE must be added to a test suite in an initialization function for the tests to be executed. The test case function is defined with the BOOST_TEST_CASE_TEMPLATE_FUNCTION macro.

static test_suite*
init(int argc, char* argv[])
{
    test_suite& suite(framework::master_test_suite());
    suite.add(BOOST_TEST_CASE_TEMPLATE(not_is_signed_for_unsigned_types, unsigned_types));
    suite.add(BOOST_TEST_CASE_TEMPLATE(is_signed_for_signed_types, signed_types));
    return 0;
}

int main(int argc, char* argv[])
{
    return unit_test_main(init, argc, argv);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case/boost_test_case_template_function.html ================================================ BOOST_TEST_CASE_TEMPLATE_FUNCTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CASE_TEMPLATE_FUNCTION(name, T) defines a test case function named name that is parameterized by a type parameter T. The defined functions are then available for registration as parameterized test cases with BOOST_TEST_CASE_TEMPLATE.

typedef boost::mpl::list<
    char, short,
    int,
    long, long long> signed_types;

BOOST_TEST_CASE_TEMPLATE_FUNCTION(is_signed_for_signed_types, T)
{
    BOOST_REQUIRE(std::numeric_limits<T>::is_signed);
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_case.html ================================================ Test Cases
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

A test case is a named body of code providing the three phases of a test: setup, exercise and verify. A test case is most conveniently created using one of the provided test case macros listed in the following table.

Table 1.1. Test Case Macros

Macro

Description

BOOST_AUTO_TEST_CASE(name)

Creates test case name and automatically registers it with the test runner.

BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(name, count)

Informs the test runner that test case name should result in count failures.

BOOST_AUTO_TEST_CASE_TEMPLATE(name, T, types)

Automatically registers a test case name parameterized by the template argument T over the collection of types.

BOOST_FIXTURE_TEST_CASE(name, fixture)

Creates test case name derived from the fixture fixture and automatically registers it with the test runner.

BOOST_PARAM_TEST_CASE(fn, begin, end)

Manually creates a parameterized test case using the supplied callable object fn and parameter iterators begin and end.

BOOST_PARAM_CLASS_TEST_CASE(fn, instance, begin, end)

Manually creates a parameterized test case using the supplied callable object fn, class instance instance and parameter iterators begin and end.

BOOST_TEST_CASE(fn)

Manually creates a test case using the supplied callable object fn.

BOOST_TEST_CASE_TEMPLATE(name, types)

Manually creates a set of test cases from the template test case name for each type in types.

BOOST_TEST_CASE_TEMPLATE_FUNCTION(name, T)

Manually creates a template test case name parameterized by the template argument T.



PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___bitwise_equal_.html ================================================ BOOST_level_BITWISE_EQUAL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BITWISE_level_EQUAL(lhs, rhs) compares the two arguments for bitwise equality and fails if they are not equal. This can be useful when testing integral values that represent a logical or combination of bit flags.

enum bit_flags
{
    source_file = 1u,
    header_file = 2u,
    build_file = 4u
};

BOOST_AUTO_TEST_CASE(example_bitwise_equal)
{
    BOOST_REQUIRE_BITWISE_EQUAL(
        source_file | build_file,
        build_file | source_file);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___close_.html ================================================ BOOST_level_CLOSE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_CLOSE(lhs, rhs, tolerance) compares the two floating-point arguments and considers them equal if they agree within the given tolerance. The tolerance is given as a percentage.

BOOST_AUTO_TEST_CASE(example_close)
{
    BOOST_REQUIRE_CLOSE(100.f, 100.9f, 1.f);
    BOOST_REQUIRE_CLOSE(100.f, 99.1f, 1.f);
}

TODO: link to floating-point algorithm explanation


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___close_fraction_.html ================================================ BOOST_level_CLOSE_FRACTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_CLOSE_FRACTION(lhs, rhs, tolerance) compares the two floating-point arguments and considers them equal if they agree within the given tolerance. The tolerance is given as a percentage.

BOOST_AUTO_TEST_CASE(example_close_fraction)
{
    BOOST_REQUIRE_CLOSE_FRACTION(100.f, 100.9f, 1.f);
    BOOST_REQUIRE_CLOSE_FRACTION(100.f, 99.1f, 1.f);
}

TODO: link to floating-point algorithm explanation


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___equal_collections_.html ================================================ BOOST_level_EQUAL_COLLECTIONS
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level=_EQUAL_COLLECTIONS(lhs_begin, lhs_end, rhs_begin, rhs_end) compares two collections for equality. Two collections are considered equal if they have the same number of elements and the elements compare equal by operator==. The elements are obtained through the supplied iterators on the collections. The diagnostic message is constructed from applying operator<< to each of the elements in the collections.

[Important] Important

If you get a strange compile error when using BOOST_EQUAL_COLLECTIONS, check that the appropriate operator== and operator<< are defined for the element type in the collection. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_equal_collections)
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    std::list<int> l;
    l.push_front(3);
    l.push_front(2);
    l.push_front(1);

    BOOST_REQUIRE_EQUAL_COLLECTIONS(v.begin(), v.end(), l.begin(), l.end());
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___exception_.html ================================================ BOOST_level_EXCEPTION
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_EXCEPTION(statement, exception, predicate) asserts that when statement throws an exception of type exception, the predicate applied to the instance of the exception returns true. This is used to verify not only that an exception of the correct type was thrown, but that the contents of the thrown exception meet the expectations of the predicate.

class error_number_exception
{
public:
    error_number_exception(int num)
        : num_(num)
    { }

    int error_number() const { return num_; }

private:
    int num_;
};

bool has_error_number_1(error_number_exception const& ex)
{
    return ex.error_number() == 1;
}

BOOST_AUTO_TEST_CASE(example_exception)
{
    BOOST_REQUIRE_EXCEPTION(throw error_number_exception(1), error_number_exception, has_error_number_1);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___ge_.html ================================================ BOOST_level_GE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_GE(lhs, rhs) asserts that lhs is greater than or equal to rhs. The comparison is made by applying operator>= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_GE, check that the appropriate operator>= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_ge)
{
    // integral types
    unsigned const u = 1u;
    int const i = -10;
    char const A = 'A';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_GE(2u, u);
    BOOST_REQUIRE_GE(1u, u);
    BOOST_REQUIRE_GE(-9, i);
    BOOST_REQUIRE_GE(-10, i);
    BOOST_REQUIRE_GE('B', A);
    BOOST_REQUIRE_GE('A', A);
    BOOST_REQUIRE_GE("scoobz", s);
    BOOST_REQUIRE_GE("scooby", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___gt_.html ================================================ BOOST_level_GT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_GT(lhs, rhs) asserts that lhs is greater than rhs. The comparison is made by applying operator> to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_GT, check that the appropriate operator> and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_gt)
{
    // integral types
    unsigned const u = 1u;
    int const i = -10;
    char const A = 'A';
    // standard library types providing operator> and operator==
    std::string const s = "scooby";

    BOOST_REQUIRE_GT(2u, u);
    BOOST_REQUIRE_GT(-9, i);
    BOOST_REQUIRE_GT('B', A);
    BOOST_REQUIRE_GT("scoobz", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___le_.html ================================================ BOOST_level_LE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_LE(lhs, rhs) asserts that lhs is less than or equal to rhs. The comparison is made by applying operator<= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_LE, check that the appropriate operator<= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_le)
{
    // integral types
    unsigned const u = 10u;
    int const i = -10;
    char const M = 'M';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_LE(9u, u);
    BOOST_REQUIRE_LE(10u, u);
    BOOST_REQUIRE_LE(-11, i);
    BOOST_REQUIRE_LE(-10, i);
    BOOST_REQUIRE_LE('L', M);
    BOOST_REQUIRE_LE('M', M);
    BOOST_REQUIRE_LE("scoobx", s);
    BOOST_REQUIRE_LE("scooby", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___lt_.html ================================================ BOOST_level_LT
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_LT(lhs, rhs) asserts that lhs is less than rhs. The comparison is made by applying operator< to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_LT, check that the appropriate operator< and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_lt)
{
    // integral types
    unsigned const u = 10u;
    int const i = -10;
    char const M = 'M';
    // standard library types providing operator>= and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_LT(9u, u);
    BOOST_REQUIRE_LT(-11, i);
    BOOST_REQUIRE_LT('L', M);
    BOOST_REQUIRE_LT("scoobx", s);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___message_.html ================================================ BOOST_level_MESSAGE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_MESSAGE(predicate, message) emits message if the supplied predicate evaluates to false. The message is applied to an output stream with operator<< and the argument can contain additional applications of operator<< for building up complex messages. The predicate can return bool or __predicate_result__.

static int g_i;

// simple predicate
static bool global_int_is_positive()
{
    return g_i > 0;
}

// predicate that builds up detail message
static boost::test_tools::predicate_result global_int_equal(int expected)
{
    if (g_i == expected)
    {
        return true;
    }

    boost::test_tools::predicate_result failed = false;
    failed.message() << "g_i != " << expected << "; actual: " << g_i;
    return failed;
}

BOOST_AUTO_TEST_CASE(example_message)
{
    g_i = 1;

    BOOST_REQUIRE_MESSAGE(global_int_is_positive(),
        "g_i is not positive; actual: " << g_i);
    BOOST_REQUIRE_MESSAGE(global_int_equal(1), "");
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___ne_.html ================================================ BOOST_level_NE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_NE(lhs, rhs) asserts that lhs is not equal to rhs. The comparison is made by applying operator!= to both arguments. The diagnostic message is constructed from applying operator<< to the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_level_NE, check that the appropriate operator!= and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___no_throw_.html ================================================ BOOST_level_NO_THROW
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_NO_THROW(statement) asserts that statement does not throw an exception.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___predicate_.html ================================================ BOOST_level_PREDICATE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_PREDICATE(predicate, args) asserts that the supplied predicate applied to args evaluates to true.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost____level___small_.html ================================================ BOOST_level_SMALL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost_test_dont_print_log_value_.html ================================================ BOOST_TEST_DONT_PRINT_LOG_VALUE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_DONT_PRINT_LOG_VALUE(type) instructs the test framework to ignore values of type type when constructing diagnostic messages. It does this by defining an empty implementation of a print function specialized for type.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost_test_error_.html ================================================ BOOST_TEST_ERROR
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_ERROR(message) always fails and emits the given message at the CHECK assertion level.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/_boost_test_is_defined_.html ================================================ BOOST_TEST_IS_DEFINED
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_IS_DEFINED(symbol) asserts that symbol is a defined value.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/boost_fail.html ================================================ BOOST_TEST_FAIL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_FAIL(message) always fails and emits the given message at the REQUIRE assertion level.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/boost_level_equal.html ================================================ BOOST_level_EQUAL
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_EQUAL(lhs, rhs) compares the two arguments with operator==. The diagnostic message is constructed with operator<< on the two arguments.

[Important] Important

If you get a strange compile error when using BOOST_EQUAL check that the appropriate operator== and operator<< are defined for the arguments. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites.

BOOST_AUTO_TEST_CASE(example_equal)
{
    // integral types
    unsigned const u = 1u;
    int const i = -1;
    char const A = 'A';
    // standard library types providing operator== and operator<<
    std::string const s = "scooby";

    BOOST_REQUIRE_EQUAL(1u, u);
    BOOST_REQUIRE_EQUAL(-1, i);
    BOOST_REQUIRE_EQUAL('A', A);
    BOOST_REQUIRE_EQUAL("scooby", s);
}

// custom data structure
struct symbol
{
    char const* const name;
    int value;
};

// custom comparison operator
bool operator==(symbol const& lhs, symbol const& rhs)
{
    return lhs.value == rhs.value
        && std::string(lhs.name) == std::string(rhs.name);
}

// custom stream insertion operator
std::ostream& operator<<(std::ostream& stream, symbol const& value)
{
    return stream << value.name << ": " << value.value;
}

BOOST_AUTO_TEST_CASE(example_equal_custom_compare)
{
    symbol const s1 = { "var" , 1 };
    symbol const s2 = { "var", 1 };
    // If the compiler doesn't collapse multiple constants, then:
    // s1.name != s2.name;

    BOOST_REQUIRE_EQUAL(s1, s2);
}


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/boost_level_throw.html ================================================ BOOST_level_THROW
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_level_THROW(statement, exception) asserts that statement throws an exception of type exception.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion/levels.html ================================================ Assertion Levels
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When using the library or header-only version of Boost.Test, many assertion macros are provided in three levels that determine the behavior when the assertion fails and how a failed assertion interacts with the test runner.

Table 1.2. Assertion Levels

Level

Test Case Fails?

Aborts Execution?

WARN

No

No

CHECK

Yes

no

REQUIRE

Yes

Yes


The WARN level issues a diagnostic message, but the test case is not considered to have failed and continues executing. The CHECK level issues a message to the test log on failure, marks the test case as failed and continues executing. The REQUIRE level issues a message to the test log on failure, marks the test case as failed and halts execution of the test case.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/assertion.html ================================================ Test Assertions
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Assertions are used to validate the result of exercising the system under test. When an assertion fails, a diagnostic message is created and the failed assertion is recorded. Different assertion levels allow you to control how a failed assertion is interpreted by the test runner.

[Important] Important

When an assertion involves a user-defined datatype, a stream insertion operator (operator<<) must be defined for the user-defined datatype, or the assertion will fail to compile. Asserting a comparison operation on a value of a user-defined type will require the appropriate comparison operator (operator<, operator==, etc.) be defiend for the type or the assertion will fail to compile.

The minimal header test framework does not provide the facilities described here.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/headers.html ================================================ Header Files
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHome

#include <boost/test/debug.hpp>

namespace boost { namespace test {

bool under_debugger();

void debugger_break();

struct dbg_startup_info {
    long                    pid;
    bool                    break_or_continue;
    unit_test::const_string binary_path;
    unit_test::const_string display;
    unit_test::const_string init_done_lock;
};

typedef boost::function<void (dbg_startup_info const&)> dbg_starter;

std::string set_debugger( unit_test::const_string dbg_id, dbg_starter s = dbg_starter() );

bool attach_debugger( bool break_or_continue = true );

void detect_memory_leaks( bool on_off, unit_test::const_string report_file = unit_test::const_string() );

void break_memory_alloc( long mem_alloc_order_num );

}} // boost::test

#include <boost/test/debug_config.hpp

BOOST_TEST_DBG_LIST

BOOST_TEST_STAT_LINE_MAX

#include <boost/test/execution_monitor.hpp>

namespace boost {

class execution_exception {
    typedef boost::unit_test::const_string const_string;
public:
    enum error_code {
        no_error               = 0,
        user_error             = 200,
        cpp_exception_error    = 205,
        system_error           = 210,
        timeout_error          = 215,
        user_fatal_error       = 220,
        system_fatal_error     = 225
    };

    struct BOOST_TEST_DECL location {
        explicit    location( char const* file_name = 0, size_t line_num = 0, char const* func = 0 );

        const_string    m_file_name;
        size_t          m_line_num;
        const_string    m_function;
    };

    // Constructor
    execution_exception( error_code ec_, const_string what_msg_, location const& location_ ); // max length 256 inc '\0'

    // Access methods
    error_code      code() const    { return m_error_code; }
    const_string    what() const    { return m_what; }
    location const& where() const   { return m_location; }
}; // execution_exception

class execution_monitor {
    typedef boost::unit_test::const_string const_string;
public:
    execution_monitor();

    // Public properties

    //  The p_catch_system_errors parameter specifies whether the monitor should 
    //  try to catch system errors/exceptions that would cause program to crash 
    //  in regular case
    unit_test::readwrite_property<bool> p_catch_system_errors;

    //  The p_auto_start_dbg parameter specifies whether the monitor should 
    //  try to attach debugger in case of caught system error
    unit_test::readwrite_property<bool> p_auto_start_dbg;

    //  The p_timeout parameter specifies the seconds that elapse before
    //  a timer_error occurs.  May be ignored on some platforms.
    unit_test::readwrite_property<int>  p_timeout;

    //  The p_use_alt_stack parameter specifies whether the monitor should
    //  use alternative stack for the signal catching
    unit_test::readwrite_property<bool> p_use_alt_stack;

    //  The p_detect_fp_exceptions parameter specifies whether the monitor should
    //  try to detect hardware floating point exceptions (!= 0), and which specific exception to catch
    unit_test::readwrite_property<unsigned> p_detect_fp_exceptions;

    int         execute( boost::function<int ()> const& F );
    //  Returns:  Value returned by function call F().
    //
    //  Effects:  Calls executes supplied function F inside a try/catch block which also may
    //  include other unspecified platform dependent error detection code.
    //
    //  Throws: execution_exception on an uncaught C++ exception,
    //  a hardware or software signal, trap, or other exception.
    //
    //  Note: execute() doesn't consider it an error for F to return a non-zero value.

    void         vexecute( boost::function<void ()> const& F );
    //  Effects:  Same as above, but returns nothing

    // register custom (user supplied) exception translator
    template<typename ExceptionType, typename ExceptionTranslator>
    void        register_exception_translator( ExceptionTranslator const& tr, const_string tag = const_string(), boost::type<ExceptionType>* = 0 );

    // erase custom exception translator
    void        erase_exception_translator( const_string tag )
    {
        m_custom_translators = m_custom_translators->erase( m_custom_translators, tag );
    }
    template<typename ExceptionType>
    void        erase_exception_translator( boost::type<ExceptionType>* = 0 )
    {
        m_custom_translators = m_custom_translators->erase<ExceptionType>( m_custom_translators );
    }

}; // execution_monitor

template<typename ExceptionType, typename ExceptionTranslator>
void
execution_monitor::register_exception_translator( ExceptionTranslator const& tr, const_string tag, boost::type<ExceptionType>* )
{
    m_custom_translators.reset(
        new detail::translator_holder<ExceptionType,ExceptionTranslator>( tr, m_custom_translators, tag ) );
}

struct execution_aborted {};

class system_error {
public:
    // Constructor
    explicit    system_error( char const* exp );

    unit_test::readonly_property<long>          p_errno;
    unit_test::readonly_property<char const*>   p_failed_exp;
};

#define BOOST_TEST_SYS_ASSERT( exp ) if( (exp) ) ; else throw ::boost::system_error( BOOST_STRINGIZE( exp ) )

namespace fpe {

enum masks {
    BOOST_FPE_OFF       = 0,

#ifdef BOOST_SEH_BASED_SIGNAL_HANDLING
    BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE,
    BOOST_FPE_INEXACT   = EM_INEXACT,
    BOOST_FPE_INVALID   = EM_INVALID,
    BOOST_FPE_OVERFLOW  = EM_OVERFLOW,
    BOOST_FPE_UNDERFLOW = EM_UNDERFLOW|EM_DENORMAL,

    BOOST_FPE_ALL       = MCW_EM,
#elif defined(BOOST_NO_FENV_H) || defined(BOOST_CLANG)
    BOOST_FPE_ALL       = 1,
#else
    BOOST_FPE_DIVBYZERO = FE_DIVBYZERO,
    BOOST_FPE_INEXACT   = FE_INEXACT,
    BOOST_FPE_INVALID   = FE_INVALID,
    BOOST_FPE_OVERFLOW  = FE_OVERFLOW,
    BOOST_FPE_UNDERFLOW = FE_UNDERFLOW,

    BOOST_FPE_ALL       = FE_ALL_EXCEPT,
#endif
    BOOST_FPE_INV       = BOOST_FPE_ALL+1
};

// return the previous set of enabled exceptions when successful, and BOOST_FPE_INV otherwise
unsigned BOOST_TEST_DECL enable( unsigned mask );
unsigned BOOST_TEST_DECL disable( unsigned mask );

} // namespace fpe
} // namespace boost

PrevUpHome
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/init_unit_test_func.html ================================================ init_unit_test_func
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The init_unit_test_func function typedef identifies the signature of the user supplied initialization function. The initialization function can be used to add custom test cases and test suites to the test tree.

namespace boost { namespace unit_test {

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
typedef bool        (*init_unit_test_func)();
#else
typedef test_suite* (*init_unit_test_func)( int, char* [] );
#endif

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/master_test_suite_t.html ================================================ master_test_suite_t
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The master test suite of type master_test_suite_t is the starting point for the test runner.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL master_test_suite_t : public test_suite {
public:
    master_test_suite_t() : test_suite( "Master Test Suite" )
    , argc( 0 )
    , argv( 0 )
    {}

    // Data members
    int      argc;
    char**   argv;
};

} }

You can obtain a reference to the master test suite with the master_test_suite() function:

namespace boost { namespace unit_test { namespace framework {

BOOST_TEST_DECL master_test_suite_t& master_test_suite();

} } }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/init_unit_test_func.html ================================================ init_unit_test_func
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The init_unit_test_func function typedef identifies the signature of the user supplied initialization function. The initialization function can be used to add custom test cases and test suites to the test tree.

namespace boost { namespace unit_test {

#ifdef BOOST_TEST_ALTERNATIVE_INIT_API
typedef bool        (*init_unit_test_func)();
#else
typedef test_suite* (*init_unit_test_func)( int, char* [] );
#endif

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/master_test_suite_t.html ================================================ master_test_suite_t
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The master test suite of type master_test_suite_t is the starting point for the test runner.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL master_test_suite_t : public test_suite {
public:
    master_test_suite_t() : test_suite( "Master Test Suite" )
    , argc( 0 )
    , argv( 0 )
    {}

    // Data members
    int      argc;
    char**   argv;
};

} }

You can obtain a reference to the master test suite with the master_test_suite() function:

namespace boost { namespace unit_test { namespace framework {

BOOST_TEST_DECL master_test_suite_t& master_test_suite();

} } }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/test_case.html ================================================ test_case
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_case class represents a single test case. A test case must be added to a test suite reachable from the master test suite in order for the test runner to run the test case.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_case : public test_unit {
public:
    enum { type = tut_case };

    // Constructor
    test_case( const_string tc_name, callback0<> const& test_func );

    // Access methods
    callback0<> const&  test_func() const { return m_test_func; }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/test_observer.html ================================================ test_observer
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_observer class encapsulates observers of test execution. It provides a simple null style observer behavior.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_observer {
public:
    // test observer interface
    virtual void    test_start( counter_t /* test_cases_amount */ ) {}
    virtual void    test_finish() {}
    virtual void    test_aborted() {}

    virtual void    test_unit_start( test_unit const& ) {}
    virtual void    test_unit_finish( test_unit const&, unsigned long /* elapsed */ ) {}
    virtual void    test_unit_skipped( test_unit const& ) {}
    virtual void    test_unit_aborted( test_unit const& ) {}

    virtual void    assertion_result( bool /* passed */ ) {}
    virtual void    exception_caught( execution_exception const& ) {}

    virtual int     priority() { return 0; }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/test_suite.html ================================================ test_suite
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_suite class represents a group of test cases and suites in the test tree hierarchy.

namespace bosot { namespace unit_test {

class BOOST_TEST_DECL test_suite : public test_unit {
public:
    enum { type = tut_suite };

    // Constructor
    explicit        test_suite( const_string ts_name );

    // test unit list management
    void            add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 );
    void            add( test_unit_generator const& gen, unsigned timeout = 0 );
    void            remove( test_unit_id id );

    // access methods
    test_unit_id    get( const_string tu_name ) const;
    std::size_t     size() const { return m_members.size(); }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/test_unit.html ================================================ test_unit
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_unit class forms the basis of the hierarchical tree of test cases. Test applications will usually create instances of test_case or test_suite, both of which derive from test_unit.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_unit {
public:
    enum { type = tut_any };

    // Constructor
    test_unit( const_string tu_name, test_unit_type t );

    // dependencies management
    void    depends_on( test_unit* tu );
    bool    check_dependencies() const;

    // Public r/o properties
    typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl))  id_t;
    typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite))      parent_id_t;
    readonly_property<test_unit_type>   p_type;                 // type for this test unit
    readonly_property<const_string>     p_type_name;            // "case"/"suite"
    id_t                                p_id;                   // unique id for this test unit
    parent_id_t                         p_parent_id;            // parent test suite id

    // Public r/w properties
    readwrite_property<std::string>     p_name;                 // name for this test unit
    readwrite_property<unsigned>        p_timeout;              // timeout for the test unit execution
    readwrite_property<counter_t>       p_expected_failures;    // number of expected failures in this test unit
    mutable readwrite_property<bool>    p_enabled;              // enabled status for this unit

    void                                increase_exp_fail( unsigned num );

};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/unit_test_log_formatter.html ================================================ unit_test_log_formatter
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_log_formatter class encapsulates formatting of log events for an output stream.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL unit_test_log_formatter {
public:
    enum log_entry_types { BOOST_UTL_ET_INFO,
                           BOOST_UTL_ET_MESSAGE,
                           BOOST_UTL_ET_WARNING,
                           BOOST_UTL_ET_ERROR,
                           BOOST_UTL_ET_FATAL_ERROR };

    // Destructor
    virtual             ~unit_test_log_formatter() {}

    // Formatter interface
    virtual void        log_start( std::ostream&, counter_t test_cases_amount ) = 0;
    virtual void        log_finish( std::ostream& ) = 0;
    virtual void        log_build_info( std::ostream& ) = 0;

    virtual void        test_unit_start( std::ostream&, test_unit const& tu ) = 0;
    virtual void        test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) = 0;
    virtual void        test_unit_skipped( std::ostream&, test_unit const& ) = 0;

    virtual void        log_exception( std::ostream& os, log_checkpoint_data const& cd, execution_exception const& ex )
    {
        // for backward compatibility
        log_exception( os, cd, ex.what() );
    }
    virtual void        log_exception( std::ostream&, log_checkpoint_data const&, const_string /* explanation */ ) {}

    virtual void        log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) = 0;
    virtual void        log_entry_value( std::ostream&, const_string value ) = 0;
    virtual void        log_entry_value( std::ostream&, lazy_ostream const& value ); // there is a default impl
    virtual void        log_entry_finish( std::ostream& ) = 0;
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/unit_test_log_t.html ================================================ unit_test_log_t
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_log_t class encapsulates the unit test log. You obtain a reference to the single global unit test log instance with the unit_test_log member.

namespace boost { namespace unit_test { namespace log {

class BOOST_TEST_DECL unit_test_log_t : public test_observer, public singleton<unit_test_log_t> {
public:
    // test_observer interface implementation
    void                test_start( counter_t test_cases_amount );
    void                test_finish();
    void                test_aborted();

    void                test_unit_start( test_unit const& );
    void                test_unit_finish( test_unit const&, unsigned long elapsed );
    void                test_unit_skipped( test_unit const& );
    void                test_unit_aborted( test_unit const& );

    void                assertion_result( bool passed );
    void                exception_caught( execution_exception const& );

    virtual int         priority() { return 1; }

    // log configuration methods
    void                set_stream( std::ostream& );
    void                set_threshold_level( log_level );
    void                set_format( output_format );
    void                set_formatter( unit_test_log_formatter* );

    // test progress logging
    void                set_checkpoint( const_string file, std::size_t line_num, const_string msg = const_string() );

    // entry logging
    unit_test_log_t&    operator<<( log::begin const& );        // begin entry 
    unit_test_log_t&    operator<<( log::end const& );          // end entry
    unit_test_log_t&    operator<<( log_level );                // set entry level
    unit_test_log_t&    operator<<( const_string );             // log entry value
    unit_test_log_t&    operator<<( lazy_ostream const& );      // log entry value

    ut_detail::entry_value_collector operator()( log_level );   // initiate entry collection
};

namespace {
    unit_test_log_t& unit_test_log;
}

} } }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result/unit_test_main.html ================================================ unit_test_main
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_main function provides an implementation of main that can be used by a test executable compiled with BOOST_TEST_NO_MAIN.

namespace boost { namespace unit_test {

int BOOST_TEST_DECL unit_test_main( init_unit_test_func init_func, int argc, char* argv[] );

} }

unit_test_main initializes the test framework, traverses the test tree and reports the result as a the return value of the function. Unexpected exceptions and system errors (signals, etc.) are caught and mapped to appropriate return values by the function.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/predicate_result.html ================================================ predicate_result
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The predicate_result class combines a boolean result from a predicate with a detailed context message for a failed predicate evaluation. Usually this class is only used in the internal implementation of the test framework, but a user can define their own custom predicates that return a predicate_result to support detailed failure messages when an assertion fails.

predicate_result is constructable and assignable from bool. The message() method returns an output string stream that can be used to build up a context message.

namespace boost { namespace test_tools {

class BOOST_TEST_DECL predicate_result {
public:
    // Constructor
    predicate_result( bool pv_ )
    : p_predicate_value( pv_ )
    {}

    template<typename BoolConvertable>
    predicate_result( BoolConvertable const& pv_ ) : p_predicate_value( !!pv_ ) {}

    // Access methods
    bool                operator!() const           { return !p_predicate_value; }
    void                operator=( bool pv_ )       { p_predicate_value.value = pv_; }
    operator            safe_bool() const           { return !!p_predicate_value ? &dummy::nonnull : 0; }

    // Public properties
    BOOST_READONLY_PROPERTY( bool, (predicate_result) ) p_predicate_value;

    // Access methods
    bool                has_empty_message() const   { return !m_message; }
    wrap_stringstream&  message()
    const_string        message() const             { return !m_message ? const_string() : const_string( m_message->str() ); }
};

} }

See BOOST_REQUIRE_MESSAGE for an example using predicate_result.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/runner/argument.html ================================================ Command Line Arguments
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Table 1.3. Command Line Argument Summary

Argument

Description

--auto_start_dbg

Automatically attach debugger in case of system failure

--break_exec_path

Break execution path

--build_info

Print build information

--catch_system_errors

Catch system errors

--color_output

Produce color output

--detect_fp_exceptions

Detect floating-point exceptions

--detect_memory_leaks

Detect memory leaks

--help

Print out a summary of test runner options

--log_format

The format of the test log

--log_level

The level of logging reported

--log_sink

The log sink name

--output_format

The output format

--random

Random number seed

--report_format

The test results report format

--report_level

The test results report level

--report_sink

The report sink name

--result_code

Return result code

--run_test

Tests to run

--save_pattern

Save pattern

--show_progress

Show execution progress

--use_alt_stack

Use alternative stack

--wait_for_debugger

Wait for the debugger to attach to the test runner.


The functionality of each command-line option can also be invoked with an environment variable. The description for each option gives the environment variable associated with that option.

This argument controls whether or not a debugger is attached to the test runner when a fatal system error occurs. A fatal system error includes Unix/POSIX signals, C++ exceptions and Win32 structured exceptions.

Value

Meaning

no (default)

Do not attach a debugger to when a fatal system error occurs.

yes

Attach the default debugger when a fatal system error occurs.

Environment variable: BOOST_TEST_AUTO_START_DBG

When performing an exception safety test, this argument forces a break into the debugger at the named exection path point within the test name. The test must be named exactly, no wildcards are supported.

Value

Meaning

name:path

For test case name, break on execution path number path.

Environment variable: BOOST_TEST_BREAK_EXEC_PATH

This argument causes the test runner to report information about the build environment before running the tests. If the argument is specified but no value is given, then a value of yes is assumed.

Value

Meaning

no (default)

Do not report build information.

yes

Report build information.

Environment variable: BOOST_TEST_BUILD_INFO

This argument controls whether or not the test runner catches fatal system errors.

Value

Meaning

no

Do not handle fatal system errors.

yes (default)

Handle fatal system errors.

Environment variable: BOOST_TEST_CATCH_SYSTEM_ERRORS

On systems that support colored text output, this argument controls whether or not the test runner will color the output. This argument does nothing on systems that do not support colored text output.

Value

Meaning

no (default)

Do not color test runner output.

yes

Color test runner output, if supported.

Environment variable: BOOST_TEST_COLOR_OUTPUT

If the execution environment supoprts floating-point exceptions, this argument controls whether or not the test runner will detect floating-point exceptions.

Value

Meaning

no (default)

Do not detect floating-point exceptions.

yes

Detect floating-point exceptions, if supported.

Environment variable: BOOST_TEST_DETECT_FP_EXCEPTIONS

If the execution environment supports the detection of memory leaks, this argument controls whether or not the test runner reports memory leaks. After running the tests, a memory leak report is issued showing the allocation number and the amount of memory leaked.

Values greater than 1 for this argument cause a trap to the debugger for a particular memory allocation number. Currently, this option is only implemented for Microsoft compilers.

Value

Meaning

0

Do not detect memory leaks.

1 (default)

Detect memory leaks and issue a memory leak report.

number

Break on allocation number.

Environment variable: BOOST_TEST_DETECT_MEMORY_LEAKS

This argument controls the format of the test runner output. The value is case insensitive.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_LOG_FORMAT

This argument controls the level of test runner output. The values are cumulative, with each increase in log level including all messages at lower levels. By default, only errors are reported.

Value

Meaning

nothing

Do not report any information.

fatal_error

Report all user or system fatal errors, such as memory access violation.

system_error

Report system non-fatal errors, such as timeout or floating-point exception.

cpp_exception

Report uncaught C++ exceptions.

error (default)

Report test failures.

warning

Report test warnings.

message

Report test messages; see BOOST_TEST_MESSAGE.

test_suite

Report entering and leaving every test case and test suite.

success

Report all successful assertions.

all

Report everything.

Environment variable: BOOST_TEST_LOG_LEVEL

This argument controls the destination, or sink, of the test runner log.

Value

Meaning

stdout (default)

The test runner log is sent to the standard output stream.

stderr

The test runner log is sent to the standard error stream.

file

The test runner log is sent to the file file.

Environment variable: BOOST_TEST_LOG_SINK

This argument combines --log_format and --report_format.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_OUTPUT_FORMAT

This argument controls whether or not the test runner will execute tests in a random order. This argument can also provide a seed for the random number generator used to run tests in a random order.

Value

Meaning

0 (default)

Run tests in registration order.

1

Run tests in a random order, using the current time as the seed.

n

Run tests in a random order, using n as the seed.

Environment variable: BOOST_TEST_RANDOM

This argument controls the format of the test report.

Value

Meaning

HRF (default)

Human readable format output.

XML

XML format output.

Environment variable: BOOST_TEST_REPORT_FORMAT

This argument controls the level of the test report. The levels are cumulative, with each successive level incorporating the output of all the previous levels.

Value

Meaning

no

No test report.

confirm (default)

Confirmation test report.

short

Short test report.

detailed

Detailed test report.

Environment variable: BOOST_TEST_REPORT_LEVEL

This argument controls the destination, or sink, of the test runner report.

Value

Meaning

stdout

The test report is sent to the standard output stream.

stderr (default)

The test report is sent to the standard error stream.

file

The test report is sent to the file file.

Environment variable: BOOST_TEST_REPORT_SINK

This argument controls whether or not the test runner returns an exit code corresponding to a summary of the test execution or zero. The summary result code is determined as follows:

Result Code

Description

0 (boost::exit_success)

All executed tests passed.

200 (boost::exit_exception_failure)

Failure due to uncaught exception.

201 (boost::exit_test_failure)

One or more executed tests failed.

Value

Meaning

no

Always return zero.

yes (default)

Return a status code indicating the summary of the tests executed.

Environment variable: BOOST_TEST_RESULT_CODE

This argument controls which test cases will be executed. The value is a comma separated list of test specifiers. Test cases are arranged as leaves on a tree structure, with every test case belonging to a test suite. The test runner always creates a master test suite. Named test suites are children of the master test suite or another named test suite. Any test case that is not the child of a named test suite is a child of the unnamed master test suite.

Test specifiers select test cases or suites by naming the path from the unnamed master test suite to the case or suite, similar to a full path to a file in a hierarchical directory structure. A test specifier is one or more path specifiers, separated by a slash (/). A test specifier begins at the master test suite and proceeds down the test tree, naming suites or test cases.

The argument --report_level set to detailed can be used to output the names of all the test suites and test cases within those test suites.

Path Specifier

Tests Selected

name

The test case or suite named name.

*name

All test cases or suites whose name ends in name.

name*

All test cases or suites whose name begins with name.

*name*

All test cases or suites whose name contains name.

*

All test cases or suites.

spec1,spec2,...

The test cases or suites with the given specifier.

spec1/spec2

The test cases or suites matched by spec2 in the test suite matched by spec1.

Environment variable: BOOST_TESTS_TO_RUN

This argument informs the test runner of a boolean value used to create or save a test pattern for file-based testing. The test case uses the boolean value to determine whether or not it writes the test pattern by exercising the system under test or reads the test pattern for comparison against the values produced by the system under test. The output_test_stream class provides a facility for recording and matching against save patterns.

Value

Meaning

no (default)

Match against a saved pattern.

yes

Save a pattern for matching.

Environment variable: BOOST_TEST_SAVE_PATTERN

This parameter instructs the test runner to print progress through the test cases. The test runner has no way of determining the length of time each test case will consume; the progress percentage is determined by counting test cases.

Value

Meaning

no (default) [Do not show test execution progress.

 

yes

Show test execution progress.

Environment variable: BOOST_TEST_SHOW_PROGRESS

This parameter instructs the test runner to use an alternate stack for signals processing on platforms where this is supported.

Value

Meaning

no (default) [Do not use an alternate stack.

 

yes

Use an alternate stack, where supported.

Environment variable: BOOST_TEST_USE_ALT_STACK


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/runner/output.html ================================================ Test Output
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

BOOST_TEST_CHECKPOINT(message) registers a test case checkpoint and associated message with the test runner. A checkpoint includes the source file and line number where the macro was invoked. If the test case is aborted unexpectedly, the soruce location and message associated with the last registered checkpoint is emitted into the log. Checkpoints can be used to identify the location of an unexpected failure within a block of test case code. The message is applied to an output stream with operator<< and can include other invocations of operator<<.

BOOST_TEST_MESSAGE(message) writes the message into the test runner log file.

BOOST_TEST_PASSPOINT() is similar to BOOST_TEST_CHECKPOINT, but only registers a source file location with the test runner.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/runner.html ================================================ Test Runner
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/test_case.html ================================================ test_case
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_case class represents a single test case. A test case must be added to a test suite reachable from the master test suite in order for the test runner to run the test case.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_case : public test_unit {
public:
    enum { type = tut_case };

    // Constructor
    test_case( const_string tc_name, callback0<> const& test_func );

    // Access methods
    callback0<> const&  test_func() const { return m_test_func; }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/test_observer.html ================================================ test_observer
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_observer class encapsulates observers of test execution. It provides a simple null style observer behavior.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_observer {
public:
    // test observer interface
    virtual void    test_start( counter_t /* test_cases_amount */ ) {}
    virtual void    test_finish() {}
    virtual void    test_aborted() {}

    virtual void    test_unit_start( test_unit const& ) {}
    virtual void    test_unit_finish( test_unit const&, unsigned long /* elapsed */ ) {}
    virtual void    test_unit_skipped( test_unit const& ) {}
    virtual void    test_unit_aborted( test_unit const& ) {}

    virtual void    assertion_result( bool /* passed */ ) {}
    virtual void    exception_caught( execution_exception const& ) {}

    virtual int     priority() { return 0; }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/test_suite.html ================================================ test_suite
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_suite class represents a group of test cases and suites in the test tree hierarchy.

namespace bosot { namespace unit_test {

class BOOST_TEST_DECL test_suite : public test_unit {
public:
    enum { type = tut_suite };

    // Constructor
    explicit        test_suite( const_string ts_name );

    // test unit list management
    void            add( test_unit* tu, counter_t expected_failures = 0, unsigned timeout = 0 );
    void            add( test_unit_generator const& gen, unsigned timeout = 0 );
    void            remove( test_unit_id id );

    // access methods
    test_unit_id    get( const_string tu_name ) const;
    std::size_t     size() const { return m_members.size(); }
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/test_unit.html ================================================ test_unit
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The test_unit class forms the basis of the hierarchical tree of test cases. Test applications will usually create instances of test_case or test_suite, both of which derive from test_unit.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL test_unit {
public:
    enum { type = tut_any };

    // Constructor
    test_unit( const_string tu_name, test_unit_type t );

    // dependencies management
    void    depends_on( test_unit* tu );
    bool    check_dependencies() const;

    // Public r/o properties
    typedef BOOST_READONLY_PROPERTY(test_unit_id,(framework_impl))  id_t;
    typedef BOOST_READONLY_PROPERTY(test_unit_id,(test_suite))      parent_id_t;
    readonly_property<test_unit_type>   p_type;                 // type for this test unit
    readonly_property<const_string>     p_type_name;            // "case"/"suite"
    id_t                                p_id;                   // unique id for this test unit
    parent_id_t                         p_parent_id;            // parent test suite id

    // Public r/w properties
    readwrite_property<std::string>     p_name;                 // name for this test unit
    readwrite_property<unsigned>        p_timeout;              // timeout for the test unit execution
    readwrite_property<counter_t>       p_expected_failures;    // number of expected failures in this test unit
    mutable readwrite_property<bool>    p_enabled;              // enabled status for this unit

    void                                increase_exp_fail( unsigned num );

};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/unit_test_log_formatter.html ================================================ unit_test_log_formatter
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_log_formatter class encapsulates formatting of log events for an output stream.

namespace boost { namespace unit_test {

class BOOST_TEST_DECL unit_test_log_formatter {
public:
    enum log_entry_types { BOOST_UTL_ET_INFO,
                           BOOST_UTL_ET_MESSAGE,
                           BOOST_UTL_ET_WARNING,
                           BOOST_UTL_ET_ERROR,
                           BOOST_UTL_ET_FATAL_ERROR };

    // Destructor
    virtual             ~unit_test_log_formatter() {}

    // Formatter interface
    virtual void        log_start( std::ostream&, counter_t test_cases_amount ) = 0;
    virtual void        log_finish( std::ostream& ) = 0;
    virtual void        log_build_info( std::ostream& ) = 0;

    virtual void        test_unit_start( std::ostream&, test_unit const& tu ) = 0;
    virtual void        test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) = 0;
    virtual void        test_unit_skipped( std::ostream&, test_unit const& ) = 0;

    virtual void        log_exception( std::ostream& os, log_checkpoint_data const& cd, execution_exception const& ex )
    {
        // for backward compatibility
        log_exception( os, cd, ex.what() );
    }
    virtual void        log_exception( std::ostream&, log_checkpoint_data const&, const_string /* explanation */ ) {}

    virtual void        log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) = 0;
    virtual void        log_entry_value( std::ostream&, const_string value ) = 0;
    virtual void        log_entry_value( std::ostream&, lazy_ostream const& value ); // there is a default impl
    virtual void        log_entry_finish( std::ostream& ) = 0;
};

} }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/unit_test_log_t.html ================================================ unit_test_log_t
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_log_t class encapsulates the unit test log. You obtain a reference to the single global unit test log instance with the unit_test_log member.

namespace boost { namespace unit_test { namespace log {

class BOOST_TEST_DECL unit_test_log_t : public test_observer, public singleton<unit_test_log_t> {
public:
    // test_observer interface implementation
    void                test_start( counter_t test_cases_amount );
    void                test_finish();
    void                test_aborted();

    void                test_unit_start( test_unit const& );
    void                test_unit_finish( test_unit const&, unsigned long elapsed );
    void                test_unit_skipped( test_unit const& );
    void                test_unit_aborted( test_unit const& );

    void                assertion_result( bool passed );
    void                exception_caught( execution_exception const& );

    virtual int         priority() { return 1; }

    // log configuration methods
    void                set_stream( std::ostream& );
    void                set_threshold_level( log_level );
    void                set_format( output_format );
    void                set_formatter( unit_test_log_formatter* );

    // test progress logging
    void                set_checkpoint( const_string file, std::size_t line_num, const_string msg = const_string() );

    // entry logging
    unit_test_log_t&    operator<<( log::begin const& );        // begin entry 
    unit_test_log_t&    operator<<( log::end const& );          // end entry
    unit_test_log_t&    operator<<( log_level );                // set entry level
    unit_test_log_t&    operator<<( const_string );             // log entry value
    unit_test_log_t&    operator<<( lazy_ostream const& );      // log entry value

    ut_detail::entry_value_collector operator()( log_level );   // initiate entry collection
};

namespace {
    unit_test_log_t& unit_test_log;
}

} } }


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes/unit_test_main.html ================================================ unit_test_main
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The unit_test_main function provides an implementation of main that can be used by a test executable compiled with BOOST_TEST_NO_MAIN.

namespace boost { namespace unit_test {

int BOOST_TEST_DECL unit_test_main( init_unit_test_func init_func, int argc, char* argv[] );

} }

unit_test_main initializes the test framework, traverses the test tree and reports the result as a the return value of the function. Unexpected exceptions and system errors (signals, etc.) are caught and mapped to appropriate return values by the function.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_classes.html ================================================ Test Classes
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Most of the time you will not need to interact with the classes in Boost.Test because the macro facilities for assertions, test cases and test suites hide all the details of the classes. If you are adapting legacy test code to Boost.Test you may need to interact with these classes in order to leverage existing test code without significant refactoring of the legacy test code.

The predicate_result class is used to combine a boolean result from a predicate with a custom failure message for reporting additional detail in the context of a failed assertion. The test_unit, test_case, test_suite and master_test_suite_t classes provide the interface to test suites and their test cases for the test runner. The test_observer, unit_test_log_t and unit_test_log_formatter classes provide low-level interaction with the test runner log.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite/boost_auto_test_suite.html ================================================ BOOST_AUTO_TEST_SUITE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The BOOST_AUTO_TEST_SUITE(name) macro defines an automatically registered test suite named name and opens a namespace named name.

A test suite can be nested within another test suite. Each test suite begun with BOOST_AUTO_TEST_SUITE must be ended with BOOST_AUTO_TEST_SUITE_END The new test suite is registered within its enclosing test suite, or the master test suite if there is no enclosing test suite.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite/boost_auto_test_suite_end.html ================================================ BOOST_AUTO_TEST_SUITE_END
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The BOOST_AUTO_TEST_SUITE_END() macro ends the test suite most recently defined with BOOST_AUTO_TEST_SUITE or BOOST_FIXTURE_TEST_SUITE. The corresponding namespace created when the test suite was defined is closed by BOOST_AUTO_TEST_SUITE_END.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite/boost_fixture_test_suite.html ================================================ BOOST_FIXTURE_TEST_SUITE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The BOOST_FIXTURE_TEST_SUITE(suite, fixture) macro begins the test suite named suite and uses fixture as a test fixture to be used as the base class of all test case classes created in the suite with BOOST_AUTO_TEST_CASE.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite/boost_test_module.html ================================================ BOOST_TEST_MODULE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The BOOST_TEST_MODULE macro is used to define the name of the master test suite. If BOOST_TEST_MODULE is defined, it should be defined in exactly one source file. It can be defined to a list of preprocessor tokens or a string literal. If a string literal is used, surrounding quotation marks ("), will not appear in the name of the master test suite.

#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE "Assertions"
#include <boost/test/unit_test.hpp>

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite/boost_test_suite.html ================================================ BOOST_TEST_SUITE
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

The BOOST_TEST_SUITE(name) macro is used to create a new test suite named name. The new suite must be added to the master test suite in order for any test cases in the suite to be executed.

static test_suite*
init_unit_test_suite(int argc, char* argv[])
{
    test_suite* hello_suite = BOOST_TEST_SUITE("hello");
    register_function(*hello_suite);
    register_method_static_instance(*hello_suite);
    register_method_function_instance(*hello_suite);
    framework::master_test_suite().add(hello_suite);
    return 0;
}

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference/test_suite.html ================================================ Test Suites
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

A test suite is an ordered collection of test cases and other test suites. The test cases in a suite are executed in the order in which they are added to the suite. When test cases are automatically registered, they are added to the test suite in the order of their definition in the source file.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/reference.html ================================================ Reference
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/tutorials/hello_test.html ================================================ Hello, Test!
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

Suppose we wish to test that the following function, declared in hello.hpp and supplied by a static library hello, inserted the text Hello, world!\n to the given stream:

#if !defined(HELLO_HPP)
#define HELLO_HPP

#include <ostream>

extern void hello_world(std::ostream& stream);

#endif

We can accomplish this with the following test, saving it in test_hello.cpp:

#define BOOST_TEST_MAIN
#include <boost/test/included/unit_test.hpp>
#include "hello.hpp"
#include <sstream>

BOOST_AUTO_TEST_CASE(hello_world_inserts_text)
{
    std::ostringstream dest;

    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

We compile test_hello.cpp and link it against the static library hello using the build environment for our platform to produce an executable. No other source files or libraries are needed. When we run the executable, it will execute our test case.

Suppose that our implementation of hello_world looks like this:

#include "hello.hpp"

void hello_world(std::ostream& stream)
{
}

When we run the unit test executable we obtain output similar to the following:[1]

Running 1 test case...
src/tutorials/hello_test/1/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\n" == dest.str() failed [Hello, world!
 != ]

*** 1 failure detected in test suite "Master Test Suite"

EXIT STATUS: 201

Oops, it looks like we forgot to implement hello_world!. Let's fix that by changing hello.cpp to the following:

#include "hello.hpp"

void hello_world(std::ostream& stream)
{
    stream << "Hello, world!";
}

We can now rebuild our library, relink our unit test executable and re-run the test:

Running 1 test case...
src/tutorials/hello_test/2/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\n" == dest.str() failed [Hello, world!
 != Hello, world!]

*** 1 failure detected in test suite "Master Test Suite"

EXIT STATUS: 201

Oops, looks like we forgot to insert the newline character. Let's fix that by changing hello.cpp to the following:

#include "hello.hpp"

void hello_world(std::ostream& stream)
{
    stream << "Hello, world!" << std::endl;
}

We rebuild our library, relink our unit test executable again and re-run the test:

Running 1 test case...

*** No errors detected

EXIT STATUS: 0

Now all our tests are passing and we know that hello_world does what we expect it to do. We used std::endl to insert the newline character and it also flushes the output stream after inserting the newline. If we didn't want the output stream to be flushed, we can change hello_world to use a character literal:

#include "hello.hpp"

void hello_world(std::ostream& stream)
{
    stream << "Hello, world!\n";
}

We rebuild and re-run the test to verify that our change didn't break anything:

Running 1 test case...

*** No errors detected

EXIT STATUS: 0
Some Observations

Now that we've seen Boost.Test in action, let's take a closer look at what we have just done:

  • The entire unit test framework was brought into our test application with a single include <boost/test/included/unit_test.hpp>. We didn't link against any libraries or introduce any run-time dependencies.
  • We didn't write an implementation of main, but our test executable linked and ran. Why? The preprocessor symbol BOOST_TEST_MAIN instructed Boost.Test to supply an implementation of main that executes all tests registered with the framework.
  • The macro BOOST_AUTO_TEST_CASE registered our unit test case with the framework and provides the necessary preamble for the implementation of the testing function.
  • The argument to BOOST_AUTO_TEST_CASE is the name of our test case and is a C++ identifier, not a string.
  • The test was structured in three phases: setup, exercise, and verify.
    • Our setup phase created an output string stream in order to capture the output of hello_world, the system under test.
    • The exercise phase called the system under test, our function hello_world.
    • The verify phase checked that the function provided the expected output using the assertion macro BOOST_REQUIRE_EQUAL.
    • To make the phases of the test obvious, we used blank lines to separate them.
  • A failing test emits a message that provides information about the location of the failed assertion and the detail of the failure.
  • The above sequence is a typical example of test-driven development, proceeding through stages of "red", "green" and "refactor".
    • We wrote a failing test and just enough implementation to compile the test ("red").
    • We then wrote the implementation and ran the test to verify our implementation. We made a simple mistake, so we corrected that and re-ran the test to verify our implementation by passing the test ("green").
    • Once our implementation was correct, we looked at possible improvements we might make to the code; in our case we eliminated the side-effect of flushing the output stream ("refactor").
  • The test code and production code, or system under test, are kept separate. The production code was in a library and the test code was in an executable.
  • No news is good news! We don't see any noise from test cases when they pass and the test executable emits only a summary of all test cases when all tests pass.
Example Source Code


[1] The test runner output here is generated from the run-fail rule in Boost.Build which includes the output from the executable and appends the exit code of the process to the output.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/tutorials/running_selected_tests.html ================================================ Running Selected Tests
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

As we continue to add unit tests for a library, we can get quite a large number of tests. If they are true unit tests and each test exercises a single class isolated from its collaborators, then most of the tests are not relevant to the changes we are making. The test executable accepts a number of command-line arguments that allow us to control the behavior of the test framework, including which tests to run.

We can list the available tests in a test executable with --report_level set to detailed:

> test_hello --report_level=detailed
Running 2 test cases...

Test suite "Master Test Suite" passed with:
  2 assertions out of 2 passed
  2 test cases out of 2 passed

  Test case "hello_world_inserts_text" passed with:
    1 assertion out of 1 passed

  Test case "hello_world_stream_with_badbit_throws_runtime_error" passed with:
    1 assertion out of 1 passed

[Caution] Caution

The arguments to the test executable, such as --report_level, use an underscore (_) to separate words, not a dash (-).

Suppose we are continuing to make changes to hello_world and we want to run only the tests that apply to that function. We can easily identify the relevant tests in the output of --report_level because we have used a test naming convention of prefixing all test case names with the name of the system under test, hello_world.

Using the --run_test argument, we can specify a comma-separated list of test case names to run:

> test_hello --run_test=hello_world_inserts_text,hello_world_stream_with_badbit_throws_runtime_error
Running 2 test cases...

*** No errors detected

EXIT STATUS: 0

Wow, that's really a mouthfull! Even with command recall, typing this command for the first time will require typing the exact names of all the test cases for hello_world. As we add more test cases, we'll have to extend the command line argument to account for each new test case.

We can solve this problem by using test suites, which organize tests into a named group:

struct hello_world_fixture
{
    std::ostringstream dest;
};

BOOST_AUTO_TEST_SUITE(test_hello);

#define HELLO_WORLD_TEST_CASE(name_) \
    BOOST_FIXTURE_TEST_CASE(hello_world_##name_, hello_world_fixture)

HELLO_WORLD_TEST_CASE(inserts_text)
{
    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

HELLO_WORLD_TEST_CASE(stream_with_badbit_throws_runtime_error)
{
    dest.clear(std::ios_base::badbit);

    BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
}

BOOST_AUTO_TEST_SUITE_END();

Now --report_level outputs the following:

> test_hello --report_level=detailed
Running 2 test cases...

Test suite "Master Test Suite" passed with:
  2 assertions out of 2 passed
  2 test cases out of 2 passed

  Test suite "test_hello" passed with:
    2 assertions out of 2 passed
    2 test cases out of 2 passed

    Test case "hello_world_inserts_text" passed with:
      1 assertion out of 1 passed

    Test case "hello_world_stream_with_badbit_throws_runtime_error" passed with:
      1 assertion out of 1 passed

The indentation shows that the test cases for hello_world are organized under the test suite named test_hello_world.

[Note] Note

We can't name the suite hello_world because that would conflict with the name of our system under test, as both are declared in the same global namespace.

Now we can supply the name of the test suite to --run_test to run all the test cases in the suite:

> test_hello --run_test=test_hello
Running 2 test cases...

*** No errors detected

EXIT STATUS: 0

As we add more test cases to the suite, we don't have to change the command we are using to run the tests and we don't need to remember the exact names of the test cases.

Suites arrange test cases into a hierarchy. You can have suites within suites to provide larger groupings to test a collection of related classes together. Once a test case is part of a suite, we must use the name of the enclosing suite with the name of the test case if we wish to run a single test case within the suite by name:

> test_hello --run_test=test_hello/hello_world_inserts_text
Running 1 test case...

*** No errors detected

The names of the enclosing suites are separated from each other and from the test case name with a slash (/). The names supplied to --run_test also allow for wildcard matching:

> test_hello --run_test=hello_world/*inserts_text
Running 1 test case...

*** No errors detected

Just as we can use a fixture with a test case to eliminate repeated setup and tear down, we can use a fixture with a test suite. All test cases in the test suite will derive from the test suite's fixture. If a test case in a test suite with a fixture specifies its own fixture, then the test case derives from the fixture specified on the test case and not on the test suite. If you want the test case to use both fixtures, then make your test case fixture derive from the test suite fixture.

We can use a test suite fixture for test_hello to take care of the duplicated setup between test cases. Since our test cases are now within the scope of a suite, we don't need to give them a unique prefix anymore. Refactoring the tests to use a suite fixture and discarding the prefix gives us the following code:

#define BOOST_TEST_MAIN
#include <boost/test/included/unit_test.hpp>
#include "hello.hpp"
#include <ios>
#include <sstream>

struct hello_world_fixture
{
    std::ostringstream dest;
};

BOOST_FIXTURE_TEST_SUITE(test_hello, hello_world_fixture);

BOOST_AUTO_TEST_CASE(inserts_text)
{
    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error)
{
    dest.clear(std::ios_base::badbit);

    BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
}

BOOST_AUTO_TEST_SUITE_END();

Now --report_level outputs the following:

> test_hello.exe --report_level=detailed
Running 2 test cases...

Test suite "Master Test Suite" passed with:
  2 assertions out of 2 passed
  2 test cases out of 2 passed

  Test suite "test_hello" passed with:
    2 assertions out of 2 passed
    2 test cases out of 2 passed

    Test case "inserts_text" passed with:
      1 assertion out of 1 passed

    Test case "stream_with_badbit_throws_runtime_error" passed with:
      1 assertion out of 1 passed

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/tutorials/testing_with_exceptions.html ================================================ Testing with Exceptions
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When we're testing a system, we want to test the failure cases as well as the success cases. This means forcing the system under test down an error path by orchestrating bad inputs or synthesizing errors from code collaborating with the system under test.

Let's add the requirement that hello_world should throw the a std::runtime_error exception if the supplied stream has the badbit set on the stream.

We can add a test case for this:

BOOST_AUTO_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error)
{
    std::ostringstream dest;
    dest.clear(std::ios_base::badbit);

    hello_world(dest);

    BOOST_FAIL("std::runtime_error not thrown");
}

[Note] Note

The clear member function on a stream clears all state bits and sets the state to the value of the argument.

Instead of an assertion macro like BOOST_REQUIRE_EQUAL, we're using the BOOST_FAIL macro that guarantees test failure. If the call to hello_world doesn't throw a runtime_error exception and continues to the next line of code, then this test case fails:

Running 2 test cases...
src/tutorials/testing_with_exceptions/1/test/test_hello.cpp(24): fatal error in "hello_world_stream_with_badbit_throws_runtime_error": std::runtime_error not thrown

*** 1 failure detected in test suite "Master Test Suite"

EXIT STATUS: 201

Now let's enhance the implementation to support this requirement:

void hello_world(std::ostream& stream)
{
    if (stream.bad())
    {
        throw std::runtime_error("bad stream");
    }
    stream << "Hello, world!\n";
}

We run our test and get something similar to the following:

Running 2 test cases...
unknown location(0): fatal error in "hello_world_stream_with_badbit_throws_runtime_error": std::runtime_error: bad stream
src/tutorials/testing_with_exceptions/2/test/test_hello.cpp(13): last checkpoint

*** 1 failure detected in test suite "Master Test Suite"

EXIT STATUS: 201

Now the test is still failing, so what did we do wrong? The exception from our system under test unwound the call stack back into the unit test framework, which caught the exception and reported this as a failure. We need to tell the test framework that an exception is expected in this situation. We can use BOOST_REQUIRE_THROW to tell the test framework that an expression is expected to throw a particular type of exception. If the exception isn't thrown or an exception of a different type is thrown, then the test fails. Our test now looks like this:

BOOST_AUTO_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error)
{
    std::ostringstream dest;
    dest.clear(std::ios_base::badbit);

    BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
}

Now our test case is passing:

Running 2 test cases...

*** No errors detected

EXIT STATUS: 0
Some Observations
  • We gave our test case a name that revealed the essence of what it tests so that when it fails, we know immediately from the name of the test what requirement has been invalidated. Using intention revealing names for test cases is just as important as using intention revealing names for methods, functions and classes.
  • We kept each scenario we wanted to test separate and independent from each other. This keeps our tests robust; the state of one test does not interfere with any other test.
  • Now that we have two test cases, we can see that there is some duplication between them: the construction of an output string stream. It isn't much right now, just a single line, but duplication between tests is something we'll need to watch.
  • Every time we modify or add a test, we have to recompile our single test file test_hello.cpp, which is including the entire unit test framework source. This leads to a lengthy compile every time we have to change the tests.
Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/tutorials/testing_with_fixtures.html ================================================ Testing with Fixtures
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

When we added our second test case in the previous tutorial, we ended up with some duplicated setup between the two test cases. This is a common occurrence in unit testing. We have some prerequisites for the system under test that must be prepared in order to exercise the system. In our case, it is a single output string stream that we use for capturing the output of our hello_world function.

Boost.Test provides a facility called a fixture for encapsulating repeated setup and tear down code between test cases. In our example, there isn't any explicit tear down code because the output string streams are created on the stack and destroyed when execution exits the test case. We have a little bit of repeated setup code that we can move to a fixture that is used by both our test cases. Let's put that repeated code in a fixture:

struct hello_world_fixture
{
    hello_world_fixture()
        : dest()
    { }
    ~hello_world_fixture()
    { }

    std::ostringstream dest;
};

BOOST_FIXTURE_TEST_CASE(hello_world_inserts_text, hello_world_fixture)
{
    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

BOOST_FIXTURE_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error, hello_world_fixture)
{
    dest.clear(std::ios_base::badbit);

    BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
}

A fixture is simply a class or struct that is inherited by the test case. We connect the test case to the fixture by using BOOST_FIXTURE_TEST_CASE instead of BOOST_AUTO_TEST_CASE. The latter simply connects each test case to an empty fixture. After refactoring the test cases to use a fixture, we run the tests to make sure the tests still pass.

When using a fixture, the order of construction and destruction is as follows when a test case is executed:

  1. The fixture is constructed.
  2. The test case class is constructed.
  3. The test case test method is executed
  4. The test case class is destroyed.
  5. The fixture is destroyed.

This process happens for each test case that is executed, ensuring that each test case has a fresh fixture and remains independent of other test cases.

In most cases, the setup will be a little more involved than just creating an instance variable and there will be some work done in the constructor of the fixture. We could simply use the default constructor and destructor of our fixture in this case. We've written the constructor and destructor explicitly to emphasize that this is where setup and tear down occur.

Now that we've transformed the test cases to use a fixture, it seems we've simply traded one piece of repetition, the construction of the output string stream, for another: the repeated use of the fixture name and system under test in our test cases. We can use a custom test case macro to get rid of this duplication:

struct hello_world_fixture
{
    std::ostringstream dest;
};

#define HELLO_WORLD_TEST_CASE(name_) \
    BOOST_FIXTURE_TEST_CASE(hello_world_##name_, hello_world_fixture)

HELLO_WORLD_TEST_CASE(inserts_text)
{
    hello_world(dest);

    BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str());
}

HELLO_WORLD_TEST_CASE(stream_with_badbit_throws_runtime_error)
{
    dest.clear(std::ios_base::badbit);

    BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error);
}

Every test case has to have a unique name within the scope of its declaration, either the global namespace or a custom namespace, which is why we've been prefixing our test case names with the name of the system under test, hello_world. Once we accumulate a few tests, the chances for a clash between test names increases.

With our custom test case macro, we reduce the chance for a test case name clash by ensuring that every test case name is prefixed by the name of the system under test. We ensure that every test case for hello_world uses the same fixture and we gain some readability of the test cases by eliminating the distracting repetition. If we change the name of the fixture, then we need only edit the custom test case macro that supplies the fixture name.

In the next tutorial, we'll see an alternative way of eliminating this duplication of the prefixes of test case names.

Example Source Code

PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test/tutorials.html ================================================ Tutorials
Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

These tutorials will get you started using Boost.Test. They are intended to be read in order and proceed from the basics of writing your first test to running selected tests. Once you've finished with the tutorials, you may want to read about test case design for some suggestions on testing various situations in C++. The full details of the framework are provided in the reference section.


PrevUpHomeNext
================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/html/test_HTML.manifest ================================================ index.html test/motivation.html test/how_to_read_this_documentation.html test/tutorials.html test/tutorials/hello_test.html test/tutorials/testing_with_exceptions.html test/tutorials/testing_with_fixtures.html test/tutorials/running_selected_tests.html test/guide.html test/guide/compilation.html test/guide/compilation/minimal_header.html test/guide/compilation/_main_.html test/guide/compilation/header_only.html test/guide/compilation/static_library.html test/guide/compilation/shared_library.html test/guide/test_case_design.html test/guide/acceptance_tests.html test/guide/testing_file_io.html test/guide/mocking_collaborators.html test/guide/testing__main_.html test/guide/testing_protected_or_private_members.html test/guide/manually_registering_test_cases_and_suites.html test/reference.html test/reference/configuration_macros.html test/reference/test_case.html test/reference/test_case/boost_auto_test_case.html test/reference/test_case/boost_auto_test_case_expected_failures.html test/reference/test_case/boost_auto_test_case_template.html test/reference/test_case/boost_fixture_test_case.html test/reference/test_case/boost_global_fixture.html test/reference/test_case/boost_param_test_case.html test/reference/test_case/boost_param_class_test_case.html test/reference/test_case/boost_test_case.html test/reference/test_case/boost_test_case_template.html test/reference/test_case/boost_test_case_template_function.html test/reference/test_suite.html test/reference/test_suite/boost_auto_test_suite.html test/reference/test_suite/boost_auto_test_suite_end.html test/reference/test_suite/boost_fixture_test_suite.html test/reference/test_suite/boost_test_module.html test/reference/test_suite/boost_test_suite.html test/reference/test_classes.html test/reference/test_classes/predicate_result.html test/reference/test_classes/test_unit.html test/reference/test_classes/test_case.html test/reference/test_classes/test_suite.html test/reference/test_classes/master_test_suite_t.html test/reference/test_classes/test_observer.html test/reference/test_classes/unit_test_log_t.html test/reference/test_classes/unit_test_log_formatter.html test/reference/test_classes/init_unit_test_func.html test/reference/test_classes/unit_test_main.html test/reference/assertion.html test/reference/assertion/levels.html test/reference/assertion/_boost____level___bitwise_equal_.html test/reference/assertion/_boost____level___close_.html test/reference/assertion/_boost____level___close_fraction_.html test/reference/assertion/boost_level_equal.html test/reference/assertion/_boost____level___equal_collections_.html test/reference/assertion/boost_level_exception.html test/reference/assertion/boost_fail.html test/reference/assertion/_boost____level___ge_.html test/reference/assertion/_boost____level___gt_.html test/reference/assertion/_boost____level___le_.html test/reference/assertion/_boost____level___lt_.html test/reference/assertion/boost_level_message.html test/reference/assertion/_boost____level___ne_.html test/reference/assertion/boost_level_no_throw.html test/reference/assertion/_boost____level___predicate_.html test/reference/assertion/_boost____level___small_.html test/reference/assertion/boost_level_throw.html test/reference/assertion/boost_test_dont_print_log_value.html test/reference/runner.html test/reference/runner/argument.html test/reference/runner/argument/auto_start_dbg.html test/reference/runner/argument/___build_info_.html test/reference/runner/argument/___catch_system_errors_.html test/reference/runner/argument/___detect_fp_exceptions_.html test/reference/runner/argument/___detect_memory_leaks_.html test/reference/runner/argument/log_format.html test/reference/runner/argument/log_level.html test/reference/runner/argument/log_sink.html test/reference/runner/argument/output_format.html test/reference/runner/argument/___random_.html test/reference/runner/argument/report_format.html test/reference/runner/argument/report_level.html test/reference/runner/argument/report_sink.html test/reference/runner/argument/___result_code_.html test/reference/runner/argument/run_test.html test/reference/runner/argument/___show_progress_.html test/reference/runner/argument/___use_alt_stack_.html test/reference/runner/output.html test/reference/runner/output/log.html test/reference/runner/output/report.html test/reference/runner/output/boost_test_checkpoint.html test/reference/runner/output/boost_test_message.html test/reference/runner/output/_boost_test_passpoint_.html ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias src : tutorials system_under_test examples ; build-project tutorials ; build-project system_under_test ; build-project examples ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/UTF.log.xsd ================================================ name of the test unit Specified with value "yes" only if test unit was skipped during execution Line number corresponding to the log entry file name corresponding to the log entry Exception description Location of last checkpoint before exception occured obsolete? different log entries Log entry corresponding to the successfully passed assertion Log entry corresponding to the message generated during test execution Log entry corresponding to the warning generated during test execution Log entry corresponding to the non-fatal error occured during test execution Log entry corresponding to the fatal error occured during test execution Log entry corresponding to an exception occured during test execution approximate time spent on test unit execution List of test units composing test suite Holds whole unit test log content Optional build information for the unit test. unique identifier for the platform unit test was compiled on unique identifier for the compiler unit test was compiled with unique identifier for the STL implementation used during unit test compilation version of the boost used ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/UTF.report.xsd ================================================ name of the test unit result status for the test unit: passed, failed, skipped or aborted number of assertions that passed during execution of the test unit number of assertion that failed during execution of the test unit number of assertions that expected to fail in the test unit number of test cases that passed in the test suite number of test cases that failed in the test suite number of test cases that were skipped in the test suite number of test cases in the test suite that were aborted during execution by an exception or a fatal error ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias examples : compilation//compilation assertions assertion_failures auto_test_case_template file_system global_fixture manual_registration param_class_test_case param_test_case test_case test_case_template auto_test_case_expected_failures ; alias turtle : # no sources : # no build requirements : # no default build : ../../../../../../turtle ; explicit turtle_mock ; build-project compilation ; run assertions.cpp /boost//unit_test_framework ; run auto_test_case_template.cpp /boost//unit_test_framework : : : static ; run file_system.cpp ../system_under_test//scanner /boost//filesystem /boost//unit_test_framework : : : ../system_under_test/scanner : file_system ; run global_fixture.cpp another_global_fixture.cpp /boost//unit_test_framework : : : static ; run manual_registration.cpp ../system_under_test//hello : : : ../system_under_test/hello : manual_registration ; run param_class_test_case.cpp ../system_under_test//hello : : : ../system_under_test/hello : param_class_test_case ; run param_test_case.cpp ../system_under_test//hello : : : ../system_under_test/hello : param_test_case ; run test_case.cpp ../system_under_test//hello : : : ../system_under_test/hello : test_case ; run test_case_template.cpp ; run-fail auto_test_case_expected_failures.cpp ../system_under_test//hello /boost//unit_test_framework : : : ../system_under_test/hello static ; run-fail assertion_failures.cpp /boost//unit_test_framework ; run turtle_mock.cpp turtle ../system_under_test//scanner /boost//filesystem /boost//unit_test_framework : : : ../system_under_test/scanner : turtle_mock ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/another_global_fixture.cpp ================================================ #include #include struct global3 { global3() { std::cout << "global3 setup\n"; } ~global3() { std::cout << "global3 teardown\n"; } }; BOOST_GLOBAL_FIXTURE(global3); BOOST_AUTO_TEST_CASE(three) { std::cout << "three\n"; BOOST_REQUIRE(true); } struct global4 { global4() { std::cout << "global4 setup\n"; } ~global4() { std::cout << "global4 teardown\n"; } }; BOOST_GLOBAL_FIXTURE(global4); BOOST_AUTO_TEST_CASE(four) { std::cout << "four\n"; BOOST_REQUIRE(true); } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/assertion_failures.cpp ================================================ #define BOOST_TEST_MAIN #include #include //[example_fail BOOST_AUTO_TEST_CASE(example_fail) { BOOST_FAIL("This should never happen."); } //] //[example_passpoint BOOST_AUTO_TEST_CASE(example_passpoint) { BOOST_TEST_PASSPOINT(); throw std::runtime_error("Oops"); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/assertions.cpp ================================================ //[example_test_module #define BOOST_TEST_MAIN #define BOOST_TEST_MODULE "Assertions" #include //] #include #include #include #include #include #include //[example_bitwise_equal enum bit_flags { source_file = 1u, header_file = 2u, build_file = 4u }; BOOST_AUTO_TEST_CASE(example_bitwise_equal) { BOOST_REQUIRE_BITWISE_EQUAL( source_file | build_file, build_file | source_file); } //] //[example_close BOOST_AUTO_TEST_CASE(example_close) { BOOST_REQUIRE_CLOSE(100.f, 100.9f, 1.f); BOOST_REQUIRE_CLOSE(100.f, 99.1f, 1.f); } //] //[example_close_fraction BOOST_AUTO_TEST_CASE(example_close_fraction) { BOOST_REQUIRE_CLOSE_FRACTION(100.f, 100.9f, 1.f); BOOST_REQUIRE_CLOSE_FRACTION(100.f, 99.1f, 1.f); } //] //[example_equal BOOST_AUTO_TEST_CASE(example_equal) { // integral types unsigned const u = 1u; int const i = -1; char const A = 'A'; // standard library types providing operator== and operator<< std::string const s = "scooby"; BOOST_REQUIRE_EQUAL(1u, u); BOOST_REQUIRE_EQUAL(-1, i); BOOST_REQUIRE_EQUAL('A', A); BOOST_REQUIRE_EQUAL("scooby", s); } //] //[example_equal_custom_compare // custom data structure struct symbol { char const* const name; int value; }; // custom comparison operator static bool operator==(symbol const& lhs, symbol const& rhs) { return lhs.value == rhs.value && std::string(lhs.name) == std::string(rhs.name); } // custom stream insertion operator static std::ostream& operator<<(std::ostream& stream, symbol const& value) { return stream << value.name << ": " << value.value; } BOOST_AUTO_TEST_CASE(example_equal_custom_compare) { symbol const s1 = { "var" , 1 }; symbol const s2 = { "var", 1 }; // If the compiler doesn't collapse multiple constants, then: // s1.name != s2.name; BOOST_REQUIRE_EQUAL(s1, s2); } //] //[example_equal_collections static std::list generate_list() { std::list l; l.push_front(3); l.push_front(2); l.push_front(1); return l; } BOOST_AUTO_TEST_CASE(example_equal_collections) { std::vector expected; expected.push_back(1); expected.push_back(2); expected.push_back(3); std::list actual = generate_list(); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } BOOST_AUTO_TEST_CASE(example_equal_collections_pod) { int const expected[] = { 1, 2, 3 }; std::list actual = generate_list(); BOOST_REQUIRE_EQUAL_COLLECTIONS( &expected[0], &expected[sizeof(expected)/sizeof(expected[0])], actual.begin(), actual.end()); } //] //[example_exception class error_number_exception { public: error_number_exception(int num) : num_(num) { } int error_number() const { return num_; } private: int num_; }; static bool has_error_number_1(error_number_exception const& ex) { return ex.error_number() == 1; } BOOST_AUTO_TEST_CASE(example_exception) { BOOST_REQUIRE_EXCEPTION(throw error_number_exception(1), error_number_exception, has_error_number_1); } //] //[example_ge BOOST_AUTO_TEST_CASE(example_ge) { // integral types unsigned const u = 1u; int const i = -10; char const A = 'A'; // standard library types providing operator>= and operator<< std::string const s = "scooby"; BOOST_REQUIRE_GE(2u, u); BOOST_REQUIRE_GE(1u, u); BOOST_REQUIRE_GE(-9, i); BOOST_REQUIRE_GE(-10, i); BOOST_REQUIRE_GE('B', A); BOOST_REQUIRE_GE('A', A); BOOST_REQUIRE_GE("scoobz", s); BOOST_REQUIRE_GE("scooby", s); } //] //[example_gt BOOST_AUTO_TEST_CASE(example_gt) { // integral types unsigned const u = 1u; int const i = -10; char const A = 'A'; // standard library types providing operator> and operator== std::string const s = "scooby"; BOOST_REQUIRE_GT(2u, u); BOOST_REQUIRE_GT(-9, i); BOOST_REQUIRE_GT('B', A); BOOST_REQUIRE_GT("scoobz", s); } //] //[example_le BOOST_AUTO_TEST_CASE(example_le) { // integral types unsigned const u = 10u; int const i = -10; char const M = 'M'; // standard library types providing operator>= and operator<< std::string const s = "scooby"; BOOST_REQUIRE_LE(9u, u); BOOST_REQUIRE_LE(10u, u); BOOST_REQUIRE_LE(-11, i); BOOST_REQUIRE_LE(-10, i); BOOST_REQUIRE_LE('L', M); BOOST_REQUIRE_LE('M', M); BOOST_REQUIRE_LE("scoobx", s); BOOST_REQUIRE_LE("scooby", s); } //] //[example_lt BOOST_AUTO_TEST_CASE(example_lt) { // integral types unsigned const u = 10u; int const i = -10; char const M = 'M'; // standard library types providing operator>= and operator<< std::string const s = "scooby"; BOOST_REQUIRE_LT(9u, u); BOOST_REQUIRE_LT(-11, i); BOOST_REQUIRE_LT('L', M); BOOST_REQUIRE_LT("scoobx", s); } //] //[example_message static int g_i; // simple predicate static bool global_int_is_positive() { return g_i > 0; } // predicate that builds up detail message static boost::test_tools::predicate_result global_int_equal(int expected) { if (g_i == expected) { return true; } boost::test_tools::predicate_result failed = false; failed.message() << "g_i != " << expected << "; actual: " << g_i; return failed; } BOOST_AUTO_TEST_CASE(example_message) { g_i = 1; BOOST_REQUIRE_MESSAGE(global_int_is_positive(), "g_i is not positive; actual: " << g_i); BOOST_REQUIRE_MESSAGE(global_int_equal(1), "g_i equals 1"); } //] //[example_ne BOOST_AUTO_TEST_CASE(example_ne) { // integral types unsigned const u = 1u; int const i = -1; char const A = 'A'; // standard library types providing operator!= and operator<< std::string const s = "scooby"; BOOST_REQUIRE_NE(2u, u); BOOST_REQUIRE_NE(-2, i); BOOST_REQUIRE_NE('B', A); BOOST_REQUIRE_NE("scoobz", s); } //] //[example_no_throw BOOST_AUTO_TEST_CASE(example_no_throw) { BOOST_REQUIRE_NO_THROW(1 + 1); } //] //[example_predicate static bool custom_string_compare(char const* const expected, char const* const actual) { return std::strcmp(expected, actual) == 0; } BOOST_AUTO_TEST_CASE(example_predicate) { char const* const s = "scooby"; BOOST_REQUIRE_PREDICATE(custom_string_compare, ("scooby")(s)); } //] //[example_small BOOST_AUTO_TEST_CASE(example_small) { float const f = 0.1f; BOOST_REQUIRE_SMALL(f, 0.25f); } //] //[example_throw static void always_throws() { throw std::runtime_error("whoops"); } BOOST_AUTO_TEST_CASE(example_throw) { BOOST_REQUIRE_THROW(always_throws(), std::runtime_error); } //] //[example_test_dont_print_log_value struct custom { int value; }; BOOST_TEST_DONT_PRINT_LOG_VALUE(custom); static bool operator==(custom const& expected, custom const& actual) { return expected.value == actual.value; } BOOST_AUTO_TEST_CASE(example_test_dont_print_log_value) { custom const v1 = { 1 }; custom const v2 = { 1 }; BOOST_REQUIRE_EQUAL(v1, v2); } //] //[example_checkpoint BOOST_AUTO_TEST_CASE(example_checkpoint) { int const i = 0; BOOST_TEST_CHECKPOINT("i = " << i); BOOST_REQUIRE(i == 0); } //] //[example_test_message BOOST_AUTO_TEST_CASE(example_test_message) { int const i = 0; BOOST_TEST_MESSAGE("i = " << i); BOOST_REQUIRE(i == 0); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/auto_test_case_expected_failures.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(inserts_text_check_expected, 2) BOOST_AUTO_TEST_CASE(inserts_text_check_expected) { std::ostringstream dest; hello_world(dest); BOOST_CHECK_EQUAL("scooby-doo", dest.str()); BOOST_CHECK_EQUAL("shaggy", dest.str()); } BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(inserts_text_check_exceeded, 2) BOOST_AUTO_TEST_CASE(inserts_text_check_exceeded) { std::ostringstream dest; hello_world(dest); BOOST_CHECK_EQUAL("scooby-doo", dest.str()); BOOST_CHECK_EQUAL("shaggy", dest.str()); BOOST_CHECK_EQUAL("SCOOBY", dest.str()); } //[expected_failures BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(inserts_text_require_expected, 1) BOOST_AUTO_TEST_CASE(inserts_text_require_expected) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("scooby-doo", dest.str()); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/auto_test_case_template.cpp ================================================ #define BOOST_TEST_MODULE auto_test_case_template #define BOOST_TEST_MAIN #include //[auto_test_case_template #include #include typedef boost::mpl::list< unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long> unsigned_types; BOOST_AUTO_TEST_CASE_TEMPLATE(not_is_signed_for_unsigned_types, T, unsigned_types) { BOOST_REQUIRE(!std::numeric_limits::is_signed); } //] typedef boost::mpl::list< char, short, int, long, long long> signed_types; BOOST_AUTO_TEST_CASE_TEMPLATE(is_signed_for_signed_types, T, signed_types) { BOOST_REQUIRE(std::numeric_limits::is_signed); } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias compilation : dynamic minimal static ; explicit dynamic_main ; explicit static_main ; run dynamic/main.cpp dynamic/test_hello.cpp ../../system_under_test//hello /boost//unit_test_framework : : : ../../system_under_test/hello shared : dynamic ; # The unit test framework needs to be compiled with BOOST_TEST_NO_MAIN # for this example to compile. run dynamic_main/main.cpp dynamic_main/test_hello.cpp ../../system_under_test//hello /boost//unit_test_framework : : : ../../system_under_test/hello shared : dynamic_main ; run minimal/test_hello.cpp ../../system_under_test//hello /boost//unit_test_framework : : : ../../system_under_test/hello : minimal ; run static/main.cpp static/test_hello.cpp ../../system_under_test//hello /boost//unit_test_framework : : : ../../system_under_test/hello static : static ; # The unit test framework needs to be compiled with BOOST_TEST_NO_MAIN # for this example to compile. run static_main/main.cpp static_main/test_hello.cpp ../../system_under_test//hello /boost//unit_test_framework : : : ../../system_under_test/hello static : static_main ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/dynamic/main.cpp ================================================ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/dynamic/test_hello.cpp ================================================ #define BOOST_TEST_DYN_LINK #include #include "hello.hpp" #include #include struct hello_world_fixture { std::ostringstream dest; }; BOOST_FIXTURE_TEST_SUITE(test_hello_world, hello_world_fixture); BOOST_AUTO_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/dynamic_main/main.cpp ================================================ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_NO_MAIN #include bool init_function() { // create test cases and suites and return a boolean indicating // success (true) or failure (false). return true; } int main(int argc, char* argv[]) { return ::boost::unit_test::unit_test_main(&init_function, argc, argv); } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/dynamic_main/test_hello.cpp ================================================ #define BOOST_TEST_DYN_LINK #define BOOST_TEST_NO_MAIN #include #include "hello.hpp" #include #include struct hello_world_fixture { std::ostringstream dest; }; BOOST_FIXTURE_TEST_SUITE(test_hello_world, hello_world_fixture); BOOST_AUTO_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/minimal/test_hello.cpp ================================================ #include #include "hello.hpp" #include #include static void inserts_text() { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE("Hello, world!\n" == dest.str()); } static void stream_with_badbit_throws_runtime_error() { std::ostringstream dest; dest.clear(std::ios_base::badbit); try { hello_world(dest); } catch (std::runtime_error const&) { return; } catch (...) { BOOST_FAIL("Unknown exception thrown."); return; } BOOST_FAIL("No exception thrown."); } int test_main(int /*argc*/, char* /*argv*/[]) { inserts_text(); stream_with_badbit_throws_runtime_error(); return 0; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/static/main.cpp ================================================ #define BOOST_TEST_MAIN #include ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/static/test_hello.cpp ================================================ #include #include "hello.hpp" #include #include struct hello_world_fixture { std::ostringstream dest; }; BOOST_FIXTURE_TEST_SUITE(test_hello_world, hello_world_fixture); BOOST_AUTO_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/static_main/main.cpp ================================================ #define BOOST_TEST_NO_MAIN #include boost::unit_test::test_suite *init_function(int argc, char *argv[]) { // create test cases and suites and return a pointer to any enclosing // suite, or 0. return 0; } int main(int argc, char *argv[]) { return boost::unit_test::unit_test_main(init_function, argc, argv); } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/compilation/static_main/test_hello.cpp ================================================ #define BOOST_TEST_NO_MAIN #include #include "hello.hpp" #include #include struct hello_world_fixture { std::ostringstream dest; }; BOOST_FIXTURE_TEST_SUITE(test_hello_world, hello_world_fixture); BOOST_AUTO_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/file_system.cpp ================================================ #define BOOST_TEST_MAIN #include #include "directory_scanner.hpp" #include "scanner.hpp" //[fake_directory_scanner class fake_directory_scanner : public directory_scanner { public: fake_directory_scanner() : begin_called(false), has_next_called(false), next_called(false), next_call_count(0U) {} virtual ~fake_directory_scanner() {} virtual void begin(std::string const &directory) { begin_called = true; begin_last_directory = directory; } bool begin_called; std::string begin_last_directory; virtual bool has_next() const { has_next_called = true; return next_call_count <= next_fake_results.size(); } mutable bool has_next_called; bool has_next_fake_result; virtual std::string next() const { next_called = true; ++next_call_count; return has_next() ? next_fake_results[next_call_count - 1U] : ""; } mutable bool next_called; mutable std::size_t next_call_count; std::vector next_fake_results; }; //] //[test_scanner static std::string const ARBITRARY_DIRECTORY_NAME("foo"); static std::string const ARBITRARY_NON_TEXT_FILE_NAME("foo.foo"); static std::string const ARBITRARY_TEXT_FILE_NAME("foo.txt"); static std::string const ARBITRARY_OTHER_TEXT_FILE_NAME("bar.txt"); struct text_files_fixture { void expect_enumerate_non_text_file() { scanner.next_fake_results.push_back(ARBITRARY_NON_TEXT_FILE_NAME); } void expect_enumerate_text_file(std::string const& file_name = ARBITRARY_TEXT_FILE_NAME) { scanner.next_fake_results.push_back(file_name); expected.push_back(file_name); } fake_directory_scanner scanner; std::vector empty; std::vector expected; }; BOOST_FIXTURE_TEST_SUITE(test_text_files, text_files_fixture); BOOST_AUTO_TEST_CASE(returns_empty_for_empty_directory) { std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_empty_for_no_text_files) { expect_enumerate_non_text_file(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_file_for_text_file) { expect_enumerate_text_file(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_only_text_file_for_mixed_files) { expect_enumerate_text_file(); expect_enumerate_non_text_file(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_all_text_files) { expect_enumerate_text_file(); expect_enumerate_non_text_file(); expect_enumerate_text_file(ARBITRARY_OTHER_TEXT_FILE_NAME); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_SUITE_END(); //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/global_fixture.cpp ================================================ #define BOOST_TEST_MAIN #include #include //[global_fixture struct global_fixture { global_fixture() { std::cout << "global setup\n"; } ~global_fixture() { std::cout << "global teardown\n"; } }; BOOST_GLOBAL_FIXTURE(global_fixture); //] struct suite_fixture { suite_fixture() { std::cout << "suite setup\n"; } ~suite_fixture() { std::cout << "suite teardown\n"; } }; BOOST_FIXTURE_TEST_SUITE(suite, suite_fixture); BOOST_AUTO_TEST_CASE(one) { std::cout << "one\n"; BOOST_REQUIRE(true); } struct global2 { global2() { std::cout << "global2 setup\n"; } ~global2() { std::cout << "global2 teardown\n"; } }; BOOST_GLOBAL_FIXTURE(global2); BOOST_AUTO_TEST_CASE(two) { std::cout << "two\n"; BOOST_REQUIRE(true); } BOOST_AUTO_TEST_SUITE_END(); ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/manual_registration.cpp ================================================ #define BOOST_TEST_NO_MAIN #include #include "hello.hpp" using namespace boost::unit_test; //[register_function static void inserts_text() { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } static void register_function(test_suite& suite) { suite.add(BOOST_TEST_CASE(inserts_text)); } //] //[hello_fixture class hello_fixture { public: void stream_with_badbit_throws_runtime_error() { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } std::ostringstream dest; }; //] //[register_method_static_instance static hello_fixture hf; static void register_method_static_instance(test_suite& suite) { suite.add(BOOST_TEST_CASE( boost::bind(&hello_fixture::stream_with_badbit_throws_runtime_error, &hf))); } //] //[register_method_function_instance static void stream_with_badbit_throws_runtime_error() { hello_fixture().stream_with_badbit_throws_runtime_error(); }; static void register_method_function_instance(test_suite& suite) { suite.add(BOOST_TEST_CASE(stream_with_badbit_throws_runtime_error)); } //] //[register_test_suite static test_suite* init_unit_test_suite(int argc, char* argv[]) { test_suite* hello_suite = BOOST_TEST_SUITE("hello"); register_function(*hello_suite); register_method_static_instance(*hello_suite); register_method_function_instance(*hello_suite); framework::master_test_suite().add(hello_suite); return 0; } //] int main(int argc, char* argv[]) { return unit_test_main(init_unit_test_suite, argc, argv); } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/param_class_test_case.cpp ================================================ #define BOOST_TEST_NO_MAIN #include #include #include "hello.hpp" #include //[param_class_test_case #include #include using namespace boost::unit_test; class hello_world_tester { public: hello_world_tester() { eq_items.push_back("Hello, world!\n"); eq_items.push_back("Hello, world!\n"); ne_items.push_back("shaggy"); ne_items.push_back("scooby"); } void inserts_text(std::string const& text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL(text, dest.str()); }; void does_not_insert_text(std::string const& text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_NE(text, dest.str()); } std::vector eq_items; std::vector ne_items; }; boost::shared_ptr tester(boost::make_shared()); static test_suite* init(int argc, char* argv[]) { test_suite& suite = framework::master_test_suite(); suite.add(BOOST_PARAM_CLASS_TEST_CASE( &hello_world_tester::inserts_text, tester, tester->eq_items.begin(), tester->eq_items.end())); suite.add(BOOST_PARAM_CLASS_TEST_CASE( &hello_world_tester::does_not_insert_text, tester, tester->ne_items.begin(), tester->ne_items.end())); return 0; } int main(int argc, char* argv[]) { return unit_test_main(init, argc, argv); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/param_test_case.cpp ================================================ #define BOOST_TEST_NO_MAIN #include #include #include "hello.hpp" #include //[param_test_case using namespace boost::unit_test; static void does_not_insert_text(std::string const& text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_NE(text, dest.str()); } static std::vector text; static test_suite* init(int argc, char* argv[]) { text.push_back("scooby"); text.push_back("shaggy"); text.push_back("foo"); text.push_back("arg"); framework::master_test_suite() .add(BOOST_PARAM_TEST_CASE(does_not_insert_text, text.begin(), text.end())); return 0; } int main(int argc, char* argv[]) { return unit_test_main(init, argc, argv); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/test_case.cpp ================================================ //[test_case #define BOOST_TEST_NO_MAIN #include #include "hello.hpp" #include using namespace boost::unit_test; static void inserts_text() { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } static test_suite* init(int argc, char* argv[]) { framework::master_test_suite().add(BOOST_TEST_CASE(inserts_text)); return 0; } int main(int argc, char* argv[]) { return unit_test_main(init, argc, argv); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/test_case_template.cpp ================================================ #define BOOST_TEST_NO_MAIN #include #include using namespace boost::unit_test; typedef boost::mpl::list< unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long> unsigned_types; BOOST_TEST_CASE_TEMPLATE_FUNCTION(not_is_signed_for_unsigned_types, T) { BOOST_REQUIRE(!std::numeric_limits::is_signed); } //[test_case_template_function typedef boost::mpl::list< char, short, int, long, long long> signed_types; BOOST_TEST_CASE_TEMPLATE_FUNCTION(is_signed_for_signed_types, T) { BOOST_REQUIRE(std::numeric_limits::is_signed); } //] //[test_case_template static test_suite* init(int argc, char* argv[]) { test_suite& suite(framework::master_test_suite()); suite.add(BOOST_TEST_CASE_TEMPLATE(not_is_signed_for_unsigned_types, unsigned_types)); suite.add(BOOST_TEST_CASE_TEMPLATE(is_signed_for_signed_types, signed_types)); return 0; } int main(int argc, char* argv[]) { return unit_test_main(init, argc, argv); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/examples/turtle_mock.cpp ================================================ #define BOOST_TEST_MAIN #include #include "scanner.hpp" //[mock_directory_scanner #include "directory_scanner.hpp" #include MOCK_BASE_CLASS(mock_directory_scanner, directory_scanner) { MOCK_METHOD(begin, 1); MOCK_METHOD(has_next, 0); MOCK_METHOD(next, 0); }; //] //[test_scanner_with_mocks static std::string const ARBITRARY_DIRECTORY_NAME("foo"); static std::string const ARBITRARY_NON_TEXT_FILE_NAME("foo.foo"); static std::string const ARBITRARY_TEXT_FILE_NAME("foo.txt"); static std::string const ARBITRARY_OTHER_TEXT_FILE_NAME("bar.txt"); struct text_files_fixture { text_files_fixture() { MOCK_EXPECT(scanner.begin).once().with(ARBITRARY_DIRECTORY_NAME); } void expect_enumerate_non_text_file() { MOCK_EXPECT(scanner.has_next).once().returns(true); MOCK_EXPECT(scanner.next).once().returns(ARBITRARY_NON_TEXT_FILE_NAME); } void expect_enumerate_text_file(std::string const& file_name = ARBITRARY_TEXT_FILE_NAME) { MOCK_EXPECT(scanner.has_next).once().returns(true); MOCK_EXPECT(scanner.next).once().returns(file_name); expected.push_back(file_name); } void expect_enumerate_end() { MOCK_EXPECT(scanner.has_next).once().returns(false); } mock_directory_scanner scanner; std::vector empty; std::vector expected; }; BOOST_FIXTURE_TEST_SUITE(test_text_files, text_files_fixture); BOOST_AUTO_TEST_CASE(returns_empty_for_empty_directory) { expect_enumerate_end(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_empty_for_no_text_files) { expect_enumerate_non_text_file(); expect_enumerate_end(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(empty.begin(), empty.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_file_for_text_file) { expect_enumerate_text_file(); expect_enumerate_end(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_only_text_file_for_mixed_files) { expect_enumerate_text_file(); expect_enumerate_non_text_file(); expect_enumerate_end(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_CASE(returns_all_text_files) { expect_enumerate_text_file(); expect_enumerate_non_text_file(); expect_enumerate_text_file(ARBITRARY_OTHER_TEXT_FILE_NAME); expect_enumerate_end(); std::vector files = text_files(ARBITRARY_DIRECTORY_NAME, scanner); BOOST_REQUIRE_EQUAL_COLLECTIONS(expected.begin(), expected.end(), files.begin(), files.end()); } BOOST_AUTO_TEST_SUITE_END(); //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-assertion.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [template operator_warning_for[assertion operator element] [important If you get a strange compile error when using [assertion], check that the appropriate [operator] and `operator<<` are defined for the [element]. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define `operator<<` can be eliminated by using [link test.reference.assertion.boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=].] ] [template operator_warning[assertion operator] [operator_warning_for [assertion] [operator] arguments] ] [section:assertion Test Assertions] Assertions are used to validate the result of exercising the system under test. When an assertion fails, a diagnostic message is created and the failed assertion is recorded. Different assertion levels allow you to control how a failed assertion is interpreted by the test runner. [important When an assertion involves a user-defined datatype, a stream insertion operator (`operator<<`) must be defined for the user-defined datatype, or the assertion will fail to compile. Asserting a comparison operation on a value of a user-defined type will require the appropriate comparison operator (`operator<`, `operator==`, etc.) be defined for the type or the assertion will fail to compile. The need to define `operator<<` can be eliminated by using [link test.reference.assertion.boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=]. ] The [link test.guide.compilation.minimal_header minimal header] test framework does not provide the facilities described here. [section:levels Assertion Levels] When using the library or header-only version of __test__, many assertion macros are provided in three levels that determine the behavior when the assertion fails and how a failed assertion interacts with the test runner. [table Assertion Levels [[Level] [Test Case Fails?] [Aborts Execution?]] [[=WARN=] [No] [No]] [[=CHECK=] [Yes] [no]] [[=REQUIRE=] [Yes] [Yes]] ] The =WARN= level issues a diagnostic message, but the test case is not considered to have failed and continues executing. The =CHECK= level issues a message to the test log on failure, marks the test case as failed and continues executing. The =REQUIRE= level issues a message to the test log on failure, marks the test case as failed and halts execution of the test case. [endsect] [section =BOOST_=[~level]=_BITWISE_EQUAL=] =BITWISE_=[~level]=_EQUAL(=[~lhs], [~rhs]=)= compares the two arguments for bitwise equality and fails if they are not equal. This can be useful when testing integral values that represent a logical or combination of bit flags. [heading Example] [example_bitwise_equal] [endsect] [section =BOOST_=[~level]=_CLOSE=] =BOOST_=[~level]=_CLOSE(=[~lhs], [~rhs], [~tolerance]=)= compares the two floating-point arguments and considers them equal if they agree within the given [~tolerance]. The [~tolerance] is given as a percentage. [heading Example] [example_close] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section =BOOST_=[~level]=_CLOSE_FRACTION=] =BOOST_=[~level]=_CLOSE_FRACTION(=[~lhs], [~rhs], [~tolerance]=)= compares the two floating-point arguments and considers them equal if they agree within the given [~tolerance]. The [~tolerance] is given as a percentage. [heading Example] [example_close_fraction] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section:boost_level_equal =BOOST_=[~level]=_EQUAL=] =BOOST_EQUAL(=[~lhs], [~rhs]=)= compares the two arguments with `operator==`. The diagnostic message is constructed with `operator<<` on the two arguments. [operator_warning =BOOST_EQUAL= `operator==`] [heading Examples] [example_equal] [example_equal_custom_compare] [endsect] [section =BOOST_=[~level]=_EQUAL_COLLECTIONS=] =BOOST_=[~level]=_EQUAL_COLLECTIONS(=[~lhs_begin], [~lhs_end], [~rhs_begin], [~rhs_end]=)= compares two collections for equality. Two collections are considered equal if they have the same number of elements and the elements compare equal by `operator==`. The elements are obtained through the supplied iterators on the collections. The diagnostic message is constructed from applying `operator<<` to each of the elements in the collections. [operator_warning_for =BOOST_EQUAL_COLLECTIONS= `operator==` element type in the collection] [heading Example] [example_equal_collections] [endsect] [section:boost_level_exception =BOOST_=[~level]=_EXCEPTION=] =BOOST_=[~level]=_EXCEPTION(=[~expression], [~exception], [~predicate]=)= asserts that when [~expression] throws an exception of type [~exception], the [~predicate] applied to the instance of the exception returns =true=. This is used to verify not only that an exception of the correct type was thrown, but that the contents of the thrown exception meet the expectations of the predicate. The [~predicate] can return =bool=, or __predicate_result__ which allows the predicate to build up a detailed failure message. [heading Example] [example_exception] [endsect] [section:boost_fail =BOOST_FAIL=] =BOOST_FAIL(=[~message]=)= always fails and emits the given [~message] at the =REQUIRE= assertion level. Other assertion macros are generally preferred over =BOOST_FAIL= because they emit better diagnostics in the case of failure. There are two situations where you might be tempted to use =BOOST_FAIL=: testing the situations where the system under test will throw exceptions or comparing against the values computed by the system under test. For testing exception generation, use __boost_require_throw__, __boost_require_no_throw__ or __boost_require_exception__. For testing against values computed by the system under test, use the comparing assertions. [heading Example] [example_fail] [endsect] [section =BOOST_=[~level]=_GE=] =BOOST_=[~level]=_GE(=[~lhs], [~rhs]=)= asserts that [~lhs] is greater than or equal to [~rhs]. The comparison is made by applying `operator>=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_GE= `operator>=`] [heading Example] [example_ge] [endsect] [section =BOOST_=[~level]=_GT=] =BOOST_=[~level]=_GT(=[~lhs], [~rhs]=)= asserts that [~lhs] is greater than [~rhs]. The comparison is made by applying `operator>` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_GT= `operator>`] [heading Example] [example_gt] [endsect] [section =BOOST_=[~level]=_LE=] =BOOST_=[~level]=_LE(=[~lhs], [~rhs]=)= asserts that [~lhs] is less than or equal to [~rhs]. The comparison is made by applying `operator<=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_LE= `operator<=`] [heading Example] [example_le] [endsect] [section =BOOST_=[~level]=_LT=] =BOOST_=[~level]=_LT(=[~lhs], [~rhs]=)= asserts that [~lhs] is less than [~rhs]. The comparison is made by applying `operator<` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_LT= `operator<`] [heading Example] [example_lt] [endsect] [section:boost_level_message =BOOST_=[~level]=_MESSAGE=] =BOOST_=[~level]=_MESSAGE(=[~predicate], [~message]=)= emits [~message] if the supplied [~predicate] evaluates to false. The [~message] is applied to an output stream with `operator<<` and the argument can contain additional applications of `operator<<` for building up complex messages. The predicate can return =bool= or __predicate_result__. [heading Example] [example_message] [endsect] [section =BOOST_=[~level]=_NE=] =BOOST_=[~level]=_NE(=[~lhs], [~rhs]=)= asserts that [~lhs] is not equal to [~rhs]. The comparison is made by applying `operator!=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_NE= `operator!=`] [heading Example] [example_ne] [endsect] [section:boost_level_no_throw =BOOST_=[~level]=_NO_THROW=] =BOOST_=[~level]=_NO_THROW(=[~expression]=)= asserts that [~expression] does not throw an exception. [heading Example] [example_no_throw] [endsect] [section =BOOST_=[~level]=_PREDICATE=] =BOOST_=[~level]=_PREDICATE(=[~predicate], [~args]=)= asserts that the supplied [~predicate] applied to [~args] evaluates to true. The supplied [~predicate] must have a return type of =bool= and argument types that are compatible with the argument list [~args]. Because =BOOST_=[~level]=_PREDICATE= is a macro, the [~args] must be supplied as a sequence of parenthesized values, with no comma separating the values. [heading Example] [example_predicate] [endsect] [section =BOOST_=[~level]=_SMALL=] =BOOST_=[~level]=_SMALL(=[~value], [~tolerance]=)= checks that the [~value] is within [~tolerance] of zero. [heading Example] [example_small] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section:boost_level_throw =BOOST_=[~level]=_THROW=] =BOOST_=[~level]=_THROW(=[~expression], [~exception]=)= asserts that [~expression] throws an exception of type [~exception] or a type derived from [~exception]. [heading Example] [example_throw] [endsect] [section:boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=] =BOOST_TEST_DONT_PRINT_LOG_VALUE(=[~type]=)= instructs the test framework to ignore values of type [~type] when constructing diagnostic messages. It does this by defining an empty implementation of a print function specialized for [~type]. Because the specialization is inside an implementation namespace for __test__, the macro must be invoked at the global namespace scope. Therefore, it cannot be used inside a test suite or any other namespace. [heading Example] [example_test_dont_print_log_value] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-assertion.qbk.bak ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [template operator_warning_for[assertion operator element] [important If you get a strange compile error when using [assertion], check that the appropriate [operator] and `operator<<` are defined for the [element]. If you define these operators in your test code, keep in mind argument-dependent lookup of types based on enclosing namespaces and the namespaces opened by test suites. The need to define `operator<<` can be eliminated by using [link test.reference.assertion.boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=].] ] [template operator_warning[assertion operator] [operator_warning_for [assertion] [operator] arguments] ] [section:assertion Test Assertions] Assertions are used to validate the result of exercising the system under test. When an assertion fails, a diagnostic message is created and the failed assertion is recorded. Different assertion levels allow you to control how a failed assertion is interpreted by the test runner. [important When an assertion involves a user-defined datatype, a stream insertion operator (`operator<<`) must be defined for the user-defined datatype, or the assertion will fail to compile. Asserting a comparison operation on a value of a user-defined type will require the appropriate comparison operator (`operator<`, `operator==`, etc.) be defiend for the type or the assertion will fail to compile. The need to define `operator<<` can be eliminated by using [link test.reference.assertion.boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=]. ] The [link test.guide.compilation.minimal_header minimal header] test framework does not provide the facilities described here. [section:levels Assertion Levels] When using the library or header-only version of __test__, many assertion macros are provided in three levels that determine the behavior when the assertion fails and how a failed assertion interacts with the test runner. [table Assertion Levels [[Level] [Test Case Fails?] [Aborts Execution?]] [[=WARN=] [No] [No]] [[=CHECK=] [Yes] [no]] [[=REQUIRE=] [Yes] [Yes]] ] The =WARN= level issues a diagnostic message, but the test case is not considered to have failed and continues executing. The =CHECK= level issues a message to the test log on failure, marks the test case as failed and continues executing. The =REQUIRE= level issues a message to the test log on failure, marks the test case as failed and halts execution of the test case. [endsect] [section =BOOST_=[~level]=_BITWISE_EQUAL=] =BITWISE_=[~level]=_EQUAL(=[~lhs], [~rhs]=)= compares the two arguments for bitwise equality and fails if they are not equal. This can be useful when testing integral values that represent a logical or combination of bit flags. [heading Example] [example_bitwise_equal] [endsect] [section =BOOST_=[~level]=_CLOSE=] =BOOST_=[~level]=_CLOSE(=[~lhs], [~rhs], [~tolerance]=)= compares the two floating-point arguments and considers them equal if they agree within the given [~tolerance]. The [~tolerance] is given as a percentage. [heading Example] [example_close] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section =BOOST_=[~level]=_CLOSE_FRACTION=] =BOOST_=[~level]=_CLOSE_FRACTION(=[~lhs], [~rhs], [~tolerance]=)= compares the two floating-point arguments and considers them equal if they agree within the given [~tolerance]. The [~tolerance] is given as a percentage. [heading Example] [example_close_fraction] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section:boost_level_equal =BOOST_=[~level]=_EQUAL=] =BOOST_EQUAL(=[~lhs], [~rhs]=)= compares the two arguments with `operator==`. The diagnostic message is constructed with `operator<<` on the two arguments. [operator_warning =BOOST_EQUAL= `operator==`] [heading Examples] [example_equal] [example_equal_custom_compare] [endsect] [section =BOOST_=[~level]=_EQUAL_COLLECTIONS=] =BOOST_=[~level]=_EQUAL_COLLECTIONS(=[~lhs_begin], [~lhs_end], [~rhs_begin], [~rhs_end]=)= compares two collections for equality. Two collections are considered equal if they have the same number of elements and the elements compare equal by `operator==`. The elements are obtained through the supplied iterators on the collections. The diagnostic message is constructed from applying `operator<<` to each of the elements in the collections. [operator_warning_for =BOOST_EQUAL_COLLECTIONS= `operator==` element type in the collection] [heading Example] [example_equal_collections] [endsect] [section:boost_level_exception =BOOST_=[~level]=_EXCEPTION=] =BOOST_=[~level]=_EXCEPTION(=[~expression], [~exception], [~predicate]=)= asserts that when [~expression] throws an exception of type [~exception], the [~predicate] applied to the instance of the exception returns =true=. This is used to verify not only that an exception of the correct type was thrown, but that the contents of the thrown exception meet the expectations of the predicate. The [~predicate] can return =bool=, or __predicate_result__ which allows the predicate to build up a detailed failure message. [heading Example] [example_exception] [endsect] [section:boost_fail =BOOST_FAIL=] =BOOST_FAIL(=[~message]=)= always fails and emits the given [~message] at the =REQUIRE= assertion level. Other assertion macros are generally preferred over =BOOST_FAIL= because they emit better diagnostics in the case of failure. There are two situations where you might be tempted to use =BOOST_FAIL=: testing the situations where the system under test will throw exceptions or comparing against the values computed by the system under test. For testing exception generation, use __boost_require_throw__, __boost_require_no_throw__ or __boost_require_exception__. For testing against values computed by the system under test, use the comparing assertions. [heading Example] [example_fail] [endsect] [section =BOOST_=[~level]=_GE=] =BOOST_=[~level]=_GE(=[~lhs], [~rhs]=)= asserts that [~lhs] is greater than or equal to [~rhs]. The comparison is made by applying `operator>=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_GE= `operator>=`] [heading Example] [example_ge] [endsect] [section =BOOST_=[~level]=_GT=] =BOOST_=[~level]=_GT(=[~lhs], [~rhs]=)= asserts that [~lhs] is greater than [~rhs]. The comparison is made by applying `operator>` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_GT= `operator>`] [heading Example] [example_gt] [endsect] [section =BOOST_=[~level]=_LE=] =BOOST_=[~level]=_LE(=[~lhs], [~rhs]=)= asserts that [~lhs] is less than or equal to [~rhs]. The comparison is made by applying `operator<=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_LE= `operator<=`] [heading Example] [example_le] [endsect] [section =BOOST_=[~level]=_LT=] =BOOST_=[~level]=_LT(=[~lhs], [~rhs]=)= asserts that [~lhs] is less than [~rhs]. The comparison is made by applying `operator<` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_LT= `operator<`] [heading Example] [example_lt] [endsect] [section:boost_level_message =BOOST_=[~level]=_MESSAGE=] =BOOST_=[~level]=_MESSAGE(=[~predicate], [~message]=)= emits [~message] if the supplied [~predicate] evaluates to false. The [~message] is applied to an output stream with `operator<<` and the argument can contain additional applications of `operator<<` for building up complex messages. The predicate can return =bool= or __predicate_result__. [heading Example] [example_message] [endsect] [section =BOOST_=[~level]=_NE=] =BOOST_=[~level]=_NE(=[~lhs], [~rhs]=)= asserts that [~lhs] is not equal to [~rhs]. The comparison is made by applying `operator!=` to both arguments. The diagnostic message is constructed from applying `operator<<` to the two arguments. [operator_warning =BOOST_=[~level]=_NE= `operator!=`] [heading Example] [example_ne] [endsect] [section:boost_level_no_throw =BOOST_=[~level]=_NO_THROW=] =BOOST_=[~level]=_NO_THROW(=[~expression]=)= asserts that [~expression] does not throw an exception. [heading Example] [example_no_throw] [endsect] [section =BOOST_=[~level]=_PREDICATE=] =BOOST_=[~level]=_PREDICATE(=[~predicate], [~args]=)= asserts that the supplied [~predicate] applied to [~args] evaluates to true. The supplied [~predicate] must have a return type of =bool= and argument types that are compatible with the argument list [~args]. Because =BOOST_=[~level]=_PREDICATE= is a macro, the [~args] must be supplied as a sequence of parenthesized values, with no comma separating the values. [heading Example] [example_predicate] [endsect] [section =BOOST_=[~level]=_SMALL=] =BOOST_=[~level]=_SMALL(=[~value], [~tolerance]=)= checks that the [~value] is within [~tolerance] of zero. [heading Example] [example_small] [/ TODO: link to floating-point algorithm explanation /] [endsect] [section:boost_level_throw =BOOST_=[~level]=_THROW=] =BOOST_=[~level]=_THROW(=[~expression], [~exception]=)= asserts that [~expression] throws an exception of type [~exception] or a type derived from [~exception]. [heading Example] [example_throw] [endsect] [section:boost_test_dont_print_log_value =BOOST_TEST_DONT_PRINT_LOG_VALUE=] =BOOST_TEST_DONT_PRINT_LOG_VALUE(=[~type]=)= instructs the test framework to ignore values of type [~type] when constructing diagnostic messages. It does this by defining an empty implementation of a print function specialized for [~type]. Because the specialization is inside an implementation namespace for __test__, the macro must be invoked at the global namespace scope. Therefore, it cannot be used inside a test suite or any other namespace. [heading Example] [example_test_dont_print_log_value] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-compilation.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section Configuration Macros] [table [[Macro] [Meaning]] [[[#test.reference.compilation.boost_test_alternative_init_api]=BOOST_TEST_ALTERNATIVE_INIT_API=] [When defined, the alternative [link test.reference.test_classes.init_unit_test_func =init_unit_test_func=] test module initialization API is used.]] [[[#test.reference.compilation.boost_test_dyn_link]=BOOST_TEST_DYN_LINK=] [When defined, the implementation is compiled as a shared library. Defining =BOOST_TEST_DYN_LINK= also defines =BOOST_TEST_ALTERNATIVE_INIT_API=.]] [[[#test.reference.compilation.boost_test_main]=BOOST_TEST_MAIN=] [When defined, an implementation of main is included in the source file.]] [[[#test.reference.compilation.boost_test_module]=BOOST_TEST_MODULE=] [When defined, it provides the name of the master test suite, otherwise a default name is used.]] [[[#test.reference.compilation.boost_test_no_lib]=BOOST_TEST_NO_LIB=] [When defined, no automatic linking is performed.]] [[[#test.reference.compilation.boost_test_no_main]=BOOST_TEST_NO_MAIN=] [When defined, no implementation of main is provided in any configuration. Static and shared libraries must have been built with this symbol defined for it to take effect when using the library. The test executable must provide its own implementation of =main=; [link test.reference.test_classes.unit_test_main =unit_test_main=] may be used for this purpose.]] ] When using any of these macros, they must be defined before including any header from __test__. [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-runner-argument.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [template envar[name] [*Environment variable]: [^[name]] ] [section:argument Command Line Arguments] [table Command Line Argument Summary [[Argument] [Description]] [[=--auto_start_dbg=] [Automatically attach debugger in case of system failure]] [[=--build_info=] [Print build information]] [[=--catch_system_errors=] [Catch system errors]] [[=--detect_fp_exceptions=] [Detect floating-point exceptions]] [[=--detect_memory_leaks=] [Detect memory leaks]] [[=--help=] [Print out a summary of test runner options]] [[=--log_format=] [The format of the test log]] [[=--log_level=] [The level of logging reported]] [[=--log_sink=] [The log sink name]] [[=--output_format=] [The output format]] [[=--random=] [Random number seed]] [[=--report_format=] [The test results report format]] [[=--report_level=] [The test results report level]] [[=--report_sink=] [The report sink name]] [[=--result_code=] [Return result code]] [[=--run_test=] [Tests to run]] [[=--show_progress=] [Show execution progress]] [[=--use_alt_stack=] [Use alternative stack]] [[=--wait_for_debugger=] [Wait for the debugger to attach to the test runner.]] ] The functionality of each command-line option can also be invoked with an environment variable. The description for each option gives the environment variable associated with that option. [section:auto_start_dbg =--auto_start_dbg=] This argument controls whether or not a debugger is attached to the test runner when a fatal system error occurs. A fatal system error includes Unix/POSIX signals, C++ exceptions and Win32 structured exceptions. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not attach a debugger to when a fatal system error occurs.]] [[=yes=] [Attach the default debugger when a fatal system error occurs.]] ] [envar BOOST_TEST_AUTO_START_DBG] [endsect] [section =--build_info=] This argument causes the test runner to report information about the build environment before running the tests. If the argument is specified but no value is given, then a value of =yes= is assumed. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not report build information.]] [[=yes=] [Report build information.]] ] [envar BOOST_TEST_BUILD_INFO] [endsect] [section =--catch_system_errors=] This argument controls whether or not the test runner catches fatal system errors. [table [[Value] [Meaning]] [[=no=] [Do not handle fatal system errors.]] [[[*=yes=] (default)] [Handle fatal system errors.]] ] [envar BOOST_TEST_CATCH_SYSTEM_ERRORS] [endsect] [section =--detect_fp_exceptions=] If the execution environment supports floating-point exceptions, this argument controls whether or not the test runner will detect floating-point exceptions. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not detect floating-point exceptions.]] [[=yes=] [Detect floating-point exceptions, if supported.]] ] [envar BOOST_TEST_DETECT_FP_EXCEPTIONS] [endsect] [section =--detect_memory_leaks=] If the execution environment supports the detection of memory leaks, this argument controls whether or not the test runner reports memory leaks. After running the tests, a memory leak report is issued showing the allocation number and the amount of memory leaked. Values greater than =1= for this argument cause a trap to the debugger for a particular memory allocation number. Currently, this option is only implemented for Microsoft compilers. [table [[Value] [Meaning]] [[=0=] [Do not detect memory leaks.]] [[[*=1=] (default)] [Detect memory leaks and issue a memory leak report.]] [[[~number]] [Break on allocation [~number].]] ] [envar BOOST_TEST_DETECT_MEMORY_LEAKS] [endsect] [section:log_format =--log_format=] This argument controls the format of the test runner output. The value is case insensitive. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_LOG_FORMAT] [endsect] [section:log_level =--log_level=] This argument controls the level of test runner output. The values are cumulative, with each increase in log level including all messages at lower levels. By default, only errors are reported. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[=nothing=] [Do not report any information.]] [[=fatal_error=] [Report all user or system fatal errors, such as memory access violation.]] [[=system_error=] [Report system non-fatal errors, such as timeout or floating-point exception.]] [[=cpp_exception=] [Report uncaught C++ exceptions.]] [[[*=error=] (default)] [Report test failures.]] [[=warning=] [Report test warnings.]] [[=message=] [Report test messages; see __boost_test_message__.]] [[=test_suite=] [Report entering and leaving every test case and test suite.]] [[=success=] [Report all successful assertions.]] [[=all=] [Report everything.]] ] [envar BOOST_TEST_LOG_LEVEL] [endsect] [section:log_sink =--log_sink=] This argument controls the destination, or sink, of the test runner log. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[[*=stdout=] (default)] [The test runner log is sent to the standard output stream.]] [[=stderr=] [The test runner log is sent to the standard error stream.]] [[[~file]] [The test runner log is sent to the file [~file].]] ] [envar BOOST_TEST_LOG_SINK] [endsect] [section:output_format =--output_format=] This argument combines __log_format__ and __report_format__. See [link test.reference.runner.output.log test runner log] for more information on the log. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_OUTPUT_FORMAT] [endsect] [section =--random=] This argument controls whether or not the test runner will execute tests in a random order. This argument can also provide a seed for the random number generator used to run tests in a random order. [table [[Value] [Meaning]] [[[*=0=] (default)] [Run tests in registration order.]] [[=1=] [Run tests in a random order, using the current time as the seed.]] [[[~n]] [Run tests in a random order, using [~n] as the seed.]] ] [envar BOOST_TEST_RANDOM] [endsect] [section:report_format =--report_format=] This argument controls the format of the test report. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_REPORT_FORMAT] [endsect] [section:report_level =--report_level=] This argument controls the level of the test report. The levels are cumulative, with each successive level incorporating the output of all the previous levels. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[=no=] [No test report.]] [[[*=confirm=] (default)] [Confirmation test report.]] [[=short=] [Short test report.]] [[=detailed=] [Detailed test report.]] ] [envar BOOST_TEST_REPORT_LEVEL] [endsect] [section:report_sink =--report_sink=] This argument controls the destination, or sink, of the test runner report. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[=stdout=] [The test report is sent to the standard output stream.]] [[[*=stderr=] (default)] [The test report is sent to the standard error stream.]] [[[~file]] [The test report is sent to the file [~file].]] ] [envar BOOST_TEST_REPORT_SINK] [endsect] [section =--result_code=] This argument controls whether or not the test runner returns an exit code corresponding to a summary of the test execution or zero. The summary result code is determined as follows: [table [[Result Code] [Description]] [[0 (=boost::exit_success=)] [All executed tests passed.]] [[200 (=boost::exit_exception_failure=)] [Failure due to uncaught exception.]] [[201 (=boost::exit_test_failure=)] [One or more executed tests failed.]] ] [table [[Value] [Meaning]] [[=no=] [Always return zero.]] [[[*=yes=] (default)] [Return a status code indicating the summary of the tests executed.]] ] [envar BOOST_TEST_RESULT_CODE] [endsect] [section:run_test =--run_test=] This argument controls which test cases will be executed. The value is a comma separated list of test specifiers. Test cases are arranged as leaves on a tree structure, with every test case belonging to a test suite. The test runner always creates a master test suite. Named test suites are children of the master test suite or another named test suite. Any test case that is not the child of a named test suite is a child of the unnamed master test suite. Test specifiers select test cases or suites by naming the path from the unnamed master test suite to the case or suite, similar to a full path to a file in a hierarchical directory structure. A test specifier is one or more path specifiers, separated by a slash (=/=). A test specifier begins at the master test suite and proceeds down the test tree, naming suites or test cases. The argument __report_level__ set to =detailed= can be used to output the names of all the test suites and test cases within those test suites. [table [[Path Specifier] [Tests Selected]] [[[~name]] [The test case or suite named [~name].]] [[=*=[~name]] [All test cases or suites whose name ends in [~name].]] [[[~name]=*=] [All test cases or suites whose name begins with [~name].]] [[=*=[~name]=*=] [All test cases or suites whose name contains [~name].]] [[=*=] [All test cases or suites.]] [[[~spec1]=,=[~spec2]=,=[~...]] [The test cases or suites with the given specifier.]] [[[~spec1]=/=[~spec2]] [The test cases or suites matched by [~spec2] in the test suite matched by [~spec1].]] ] [envar BOOST_TESTS_TO_RUN] [endsect] [section =--show_progress=] This parameter instructs the test runner to print progress through the test cases. The test runner has no way of determining the length of time each test case will consume; the progress percentage is determined by counting test cases. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not show test execution progress.]] [[=yes=] [Show test execution progress.]] ] [envar BOOST_TEST_SHOW_PROGRESS] [endsect] [section =--use_alt_stack=] This parameter instructs the test runner to use an alternate stack for signals processing on platforms where this is supported. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not use an alternate stack.]] [[=yes=] [Use an alternate stack, where supported.]] ] [envar BOOST_TEST_USE_ALT_STACK] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-runner-argument.qbk.bak ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [template envar[name] [*Environment variable]: [^[name]] ] [section:argument Command Line Arguments] [table Command Line Argument Summary [[Argument] [Description]] [[=--auto_start_dbg=] [Automatically attach debugger in case of system failure]] [[=--build_info=] [Print build information]] [[=--catch_system_errors=] [Catch system errors]] [[=--detect_fp_exceptions=] [Detect floating-point exceptions]] [[=--detect_memory_leaks=] [Detect memory leaks]] [[=--help=] [Print out a summary of test runner options]] [[=--log_format=] [The format of the test log]] [[=--log_level=] [The level of logging reported]] [[=--log_sink=] [The log sink name]] [[=--output_format=] [The output format]] [[=--random=] [Random number seed]] [[=--report_format=] [The test results report format]] [[=--report_level=] [The test results report level]] [[=--report_sink=] [The report sink name]] [[=--result_code=] [Return result code]] [[=--run_test=] [Tests to run]] [[=--show_progress=] [Show execution progress]] [[=--use_alt_stack=] [Use alternative stack]] [[=--wait_for_debugger=] [Wait for the debugger to attach to the test runner.]] ] The functionality of each command-line option can also be invoked with an environment variable. The description for each option gives the environment variable associated with that option. [section:auto_start_dbg =--auto_start_dbg=] This argument controls whether or not a debugger is attached to the test runner when a fatal system error occurs. A fatal system error includes Unix/POSIX signals, C++ exceptions and Win32 structured exceptions. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not attach a debugger to when a fatal system error occurs.]] [[=yes=] [Attach the default debugger when a fatal system error occurs.]] ] [envar BOOST_TEST_AUTO_START_DBG] [endsect] [section =--build_info=] This argument causes the test runner to report information about the build environment before running the tests. If the argument is specified but no value is given, then a value of =yes= is assumed. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not report build information.]] [[=yes=] [Report build information.]] ] [envar BOOST_TEST_BUILD_INFO] [endsect] [section =--catch_system_errors=] This argument controls whether or not the test runner catches fatal system errors. [table [[Value] [Meaning]] [[=no=] [Do not handle fatal system errors.]] [[[*=yes=] (default)] [Handle fatal system errors.]] ] [envar BOOST_TEST_CATCH_SYSTEM_ERRORS] [endsect] [section =--detect_fp_exceptions=] If the execution environment supoprts floating-point exceptions, this argument controls whether or not the test runner will detect floating-point exceptions. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not detect floating-point exceptions.]] [[=yes=] [Detect floating-point exceptions, if supported.]] ] [envar BOOST_TEST_DETECT_FP_EXCEPTIONS] [endsect] [section =--detect_memory_leaks=] If the execution environment supports the detection of memory leaks, this argument controls whether or not the test runner reports memory leaks. After running the tests, a memory leak report is issued showing the allocation number and the amount of memory leaked. Values greater than =1= for this argument cause a trap to the debugger for a particular memory allocation number. Currently, this option is only implemented for Microsoft compilers. [table [[Value] [Meaning]] [[=0=] [Do not detect memory leaks.]] [[[*=1=] (default)] [Detect memory leaks and issue a memory leak report.]] [[[~number]] [Break on allocation [~number].]] ] [envar BOOST_TEST_DETECT_MEMORY_LEAKS] [endsect] [section:log_format =--log_format=] This argument controls the format of the test runner output. The value is case insensitive. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_LOG_FORMAT] [endsect] [section:log_level =--log_level=] This argument controls the level of test runner output. The values are cumulative, with each increase in log level including all messages at lower levels. By default, only errors are reported. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[=nothing=] [Do not report any information.]] [[=fatal_error=] [Report all user or system fatal errors, such as memory access violation.]] [[=system_error=] [Report system non-fatal errors, such as timeout or floating-point exception.]] [[=cpp_exception=] [Report uncaught C++ exceptions.]] [[[*=error=] (default)] [Report test failures.]] [[=warning=] [Report test warnings.]] [[=message=] [Report test messages; see __boost_test_message__.]] [[=test_suite=] [Report entering and leaving every test case and test suite.]] [[=success=] [Report all successful assertions.]] [[=all=] [Report everything.]] ] [envar BOOST_TEST_LOG_LEVEL] [endsect] [section:log_sink =--log_sink=] This argument controls the destination, or sink, of the test runner log. See [link test.reference.runner.output.log test runner log] for more information on the log. [table [[Value] [Meaning]] [[[*=stdout=] (default)] [The test runner log is sent to the standard output stream.]] [[=stderr=] [The test runner log is sent to the standard error stream.]] [[[~file]] [The test runner log is sent to the file [~file].]] ] [envar BOOST_TEST_LOG_SINK] [endsect] [section:output_format =--output_format=] This argument combines __log_format__ and __report_format__. See [link test.reference.runner.output.log test runner log] for more information on the log. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_OUTPUT_FORMAT] [endsect] [section =--random=] This argument controls whether or not the test runner will execute tests in a random order. This argument can also provide a seed for the random number generator used to run tests in a random order. [table [[Value] [Meaning]] [[[*=0=] (default)] [Run tests in registration order.]] [[=1=] [Run tests in a random order, using the current time as the seed.]] [[[~n]] [Run tests in a random order, using [~n] as the seed.]] ] [envar BOOST_TEST_RANDOM] [endsect] [section:report_format =--report_format=] This argument controls the format of the test report. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[[*=HRF=] (default)] [Human readable format output.]] [[=XML=] [XML format output.]] ] [envar BOOST_TEST_REPORT_FORMAT] [endsect] [section:report_level =--report_level=] This argument controls the level of the test report. The levels are cumulative, with each successive level incorporating the output of all the previous levels. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[=no=] [No test report.]] [[[*=confirm=] (default)] [Confirmation test report.]] [[=short=] [Short test report.]] [[=detailed=] [Detailed test report.]] ] [envar BOOST_TEST_REPORT_LEVEL] [endsect] [section:report_sink =--report_sink=] This argument controls the destination, or sink, of the test runner report. See [link test.reference.runner.output.report test runner report] for more information on the report. [table [[Value] [Meaning]] [[=stdout=] [The test report is sent to the standard output stream.]] [[[*=stderr=] (default)] [The test report is sent to the standard error stream.]] [[[~file]] [The test report is sent to the file [~file].]] ] [envar BOOST_TEST_REPORT_SINK] [endsect] [section =--result_code=] This argument controls whether or not the test runner returns an exit code corresponding to a summary of the test execution or zero. The summary result code is determined as follows: [table [[Result Code] [Description]] [[0 (=boost::exit_success=)] [All executed tests passed.]] [[200 (=boost::exit_exception_failure=)] [Failure due to uncaught exception.]] [[201 (=boost::exit_test_failure=)] [One or more executed tests failed.]] ] [table [[Value] [Meaning]] [[=no=] [Always return zero.]] [[[*=yes=] (default)] [Return a status code indicating the summary of the tests executed.]] ] [envar BOOST_TEST_RESULT_CODE] [endsect] [section:run_test =--run_test=] This argument controls which test cases will be executed. The value is a comma separated list of test specifiers. Test cases are arranged as leaves on a tree structure, with every test case belonging to a test suite. The test runner always creates a master test suite. Named test suites are children of the master test suite or another named test suite. Any test case that is not the child of a named test suite is a child of the unnamed master test suite. Test specifiers select test cases or suites by naming the path from the unnamed master test suite to the case or suite, similar to a full path to a file in a hierarchical directory structure. A test specifier is one or more path specifiers, separated by a slash (=/=). A test specifier begins at the master test suite and proceeds down the test tree, naming suites or test cases. The argument __report_level__ set to =detailed= can be used to output the names of all the test suites and test cases within those test suites. [table [[Path Specifier] [Tests Selected]] [[[~name]] [The test case or suite named [~name].]] [[=*=[~name]] [All test cases or suites whose name ends in [~name].]] [[[~name]=*=] [All test cases or suites whose name begins with [~name].]] [[=*=[~name]=*=] [All test cases or suites whose name contains [~name].]] [[=*=] [All test cases or suites.]] [[[~spec1]=,=[~spec2]=,=[~...]] [The test cases or suites with the given specifier.]] [[[~spec1]=/=[~spec2]] [The test cases or suites matched by [~spec2] in the test suite matched by [~spec1].]] ] [envar BOOST_TESTS_TO_RUN] [endsect] [section =--show_progress=] This parameter instructs the test runner to print progress through the test cases. The test runner has no way of determining the length of time each test case will consume; the progress percentage is determined by counting test cases. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not show test execution progress.]] [[=yes=] [Show test execution progress.]] ] [envar BOOST_TEST_SHOW_PROGRESS] [endsect] [section =--use_alt_stack=] This parameter instructs the test runner to use an alternate stack for signals processing on platforms where this is supported. [table [[Value] [Meaning]] [[[*=no=] (default)] [Do not use an alternate stack.]] [[=yes=] [Use an alternate stack, where supported.]] ] [envar BOOST_TEST_USE_ALT_STACK] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-runner-output.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:output Test Output] [section:log Test Log] The test log contains detailed information on every assertion in every test case. The log can be formatted as plain human readable text or as XML and can be sent to the standard output stream, the standard error stream or a file. The amount of detail in the log is set with the __log_level__ option. The format of the log is set with the __log_format__ option. The destination of the log is set with the __log_sink__ option. The __output_format__ option sets both the log format and the report format. The XML format for the test log conforms to the schema [@boost:/libs/test/doc/src/UTF.log.xsd UTF.log.xsd]. [endsect] [section:report Test Report] The report contains summary information about the test cases executed and the count of failures. The report can be formatted as plain human readable text or as XML and can be sent to the standard output stream, standard error stream or a file. The amount of detail in the report is controlled by the __report_level__ option. The format of the report can be changed with the __report_format__ option. The destination of the report can be set with the __report_sink__ option. The __output_format__ option sets both the report format and the log format. The XML format for the test report conforms to the schema [@boost:/libs/test/doc/src/UTF.report.xsd UTF.report.xsd]. [endsect] [section:boost_test_checkpoint =BOOST_TEST_CHECKPOINT=] =BOOST_TEST_CHECKPOINT(=[~message]=)= registers a test case checkpoint and associated [~message] with the test runner. A checkpoint includes the source file and line number where the macro was invoked. If the test case is aborted unexpectedly, the source location and message associated with the last registered checkpoint is emitted into the log. Checkpoints can be used to identify the location of an unexpected failure within a block of test case code. The [~message] is applied to an output stream with `operator<<` and can include other invocations of `operator<<`. [example_checkpoint] [endsect] [section:boost_test_message =BOOST_TEST_MESSAGE=] =BOOST_TEST_MESSAGE(=[~message]=)= unconditionally writes the [~message] into the test runner log file. Unlike __boost_test_checkpoint__ no file and line number information is written into the log file. The [~message] is applied to an output stream with `operator<<` and can include other invocations of `operator<<`. [example_test_message] [endsect] [section =BOOST_TEST_PASSPOINT=] =BOOST_TEST_PASSPOINT()= is similar to __boost_test_checkpoint__, but only registers a source file location with the test runner. [example_passpoint] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-runner.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:runner Test Runner] [include:test ref-runner-argument.qbk] [include:test ref-runner-output.qbk] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-test-case.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:test_case Test Cases] A test case is a named body of code providing the three phases of a test: setup, exercise and verify. A test case is most conveniently created using one of the provided test case macros listed in the following table. [table Test Case Macros [[Macro] [Description]] [[=BOOST_AUTO_TEST_CASE(=[~name]=)=] [Creates test case [~name] and automatically registers it with the test runner.]] [[=BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(=[~name], [~count]=)=] [Informs the test runner that test case [~name] should result in [~count] failures.]] [[=BOOST_AUTO_TEST_CASE_TEMPLATE(=[~name], [~T], [~types]=)=] [Automatically registers a test case [~name] parameterized by the template argument [~T] over the collection of [~types].]] [[=BOOST_FIXTURE_TEST_CASE(=[~name], [~fixture]=)=] [Creates test case [~name] derived from the fixture [~fixture] and automatically registers it with the test runner.]] [[=BOOST_PARAM_TEST_CASE(=[~fn], [~begin], [~end]=)=] [Manually creates a parameterized test case using the supplied callable object [~fn] and parameter iterators [~begin] and [~end].]] [[=BOOST_PARAM_CLASS_TEST_CASE(=[~fn], [~instance], [~begin], [~end]=)=] [Manually creates a parameterized test case using the supplied callable object [~fn], class instance [~instance] and parameter iterators [~begin] and [~end].]] [[=BOOST_TEST_CASE(=[~fn]=)=] [Manually creates a test case using the supplied callable object [~fn].]] [[=BOOST_TEST_CASE_TEMPLATE(=[~name], [~types]=)=] [Manually creates a set of test cases from the template test case [~name] for each type in [~types].]] [[=BOOST_TEST_CASE_TEMPLATE_FUNCTION(=[~name], [~T]=)=] [Manually creates a template test case [~name] parameterized by the template argument [~T].]] ] [section:boost_auto_test_case =BOOST_AUTO_TEST_CASE=] =BOOST_AUTO_TEST_CASE(=[~name]=)= creates a test case class, a test case invocation function, a test case unique identifier, registers the invocation function as a test case and begins the definition of the test method on the test class. The test case class [~name] is derived from =BOOST_AUTO_TEST_CASE_FIXTURE= and contains a single method named =test_method=. The test invocation function instantiates the test case class and invokes the test case method. Test log checkpoints are made before the test case class is instantiated and bracketing the test method invocation. This provides diagnostic checkpoints should a runtime error cause a test case to be aborted before any assertions are made. [heading Example Source Code] * Tutorials: * [link test.tutorials.hello_test Hello, Test!] * System under test: * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/hello_test/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_auto_test_case_expected_failures =BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES=] =BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(=[~name], [~n]=)= is used to decorate a test case with an expected failure count of [~n]. It should appear immediately preceding the macro that defines the test case, such as __boost_auto_test_case__ or __boost_fixture_test_case__. It can be used for test cases declared at file scope or within a test suite. This macro should only be used in the most exceptional of circumstances. Unit tests are designed to provide a safety net of regression tests against our code. If we allow tests to stay failing, we are less motivated to correct them. As a temporary measure, we may wish to annotate certain tests as known failures. The count [~n] is the number of expected failed assertions during the execution of the test case. When using the [link test.reference.assertion.levels =CHECK=] level assertions, the total failure count can be larger than one since the test case continues executing past a failed assertion. When using =REQUIRE= level assertions, the total failure count will only be one as execution of the test case terminates on the first failed assertion. If =CHECK= level assertions are used and the number of failures is less than or equal to [~n], the test runner will return a status code of =0=. If the number of failures is greater than [~n], the test runner will return a status code of =201=. If =REQUIRE= level assertions are used, the number of expected failures can be at most one and the test runner will return a status code of =200= when one failed assertion is found. [import examples/auto_test_case_expected_failures.cpp] [expected_failures] [note When using the compiler formatted test output, Visual Studio interprets the failed assertion output as a detected error, it will fail the Post-Build event mechanism recommended in [link test.guide.test_case_design Test Case Design and Maintenance].] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/auto_test_case_expected_failures.cpp auto_test_case_expected_failures.cpp] [endsect] [section:boost_auto_test_case_template =BOOST_AUTO_TEST_CASE_TEMPLATE=] =BOOST_AUTO_TEST_CASE_TEMPLATE(=[~name], [~var], [~types]=)= declares a test case [~name] parameterized by a single template argument [~var] that is evaluated for each type in [~types]. This allows you to write a test case that exercises an invariant across a collection of types. The macro expands into one test case for each type in [~types], with the template argument [~var] assigned to each type. The [~types] argument must be a Boost.MPL type list and must be defined as a =typedef=. [import examples/auto_test_case_template.cpp] [auto_test_case_template] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/auto_test_case_template.cpp auto_test_case_template.cpp] [endsect] [section:boost_fixture_test_case =BOOST_FIXTURE_TEST_CASE=] =BOOST_FIXTURE_TEST_CASE(=[~name], [~fixture]=)= defines a test case class [~name] that derives from [~fixture]. If the test case is declared within a test suite that also has a test fixture, then to get the cumulative effect of both fixtures the test case fixture should derive from the test suite's fixture. Otherwise, the test case fixture will replace the test suite fixture for a test case defined with =BOOST_FIXTURE_TEST_CASE=. [heading Example Source Code] * Tutorials: * [link test.tutorials.testing_with_fixtures Testing With Fixtures] * System under test: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_global_fixture =BOOST_GLOBAL_FIXTURE=] =BOOST_GLOBAL_FIXTURE(=[~name]=)= declares a global fixture that is constructed before executing any test cases and is destroyed after executing all test cases. If more than one global fixture is defined in a single source file, the fixtures are constructed in the order they appear in the source file and destroyed in the reverse order. If global fixtures are defined in multiple source files, the order in which global fixtures are initialized between source files is implementation dependent. Because global fixtures are not created and destroyed for each test case, they represent shared state that prevents test cases from executing independently from each other. For this reason, test case fixtures created with __boost_fixture_test_case__ and test suite fixtures created with __boost_fixture_test_suite__ are preferred over global fixtures. [import examples/global_fixture.cpp][global_fixture] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/another_global_fixture.cpp another_global_fixture.cpp] * [@boost:/libs/test/doc/src/examples/global_fixture.cpp global_fixture.cpp] [endsect] [section:boost_param_test_case =BOOST_PARAM_TEST_CASE=] =BOOST_PARAM_TEST_CASE(=[~fn], [~begin], [~end]=)= creates a series of test cases that invoking the callable object [~fn] on the items in the collection defined by [~begin] and [~end]. The test case returned by =BOOST_PARAM_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. The iterators [~begin] and [~end] must be valid at the time the test case executes and not just at the time the test case is created. [import examples/param_test_case.cpp][param_test_case] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/param_test_case.cpp param_test_case.cpp] [endsect] [section:boost_param_class_test_case =BOOST_PARAM_CLASS_TEST_CASE=] =BOOST_PARAM_CLASS_TEST_CASE(=[~memfn], [~instance], [~begin], [~end]=)= works similarly to __boost_param_test_case__. It creates a collection of test cases that invoke the member function [~memfn] on the instance pointer [~instance]. The member function is passed an item obtained by iterating the collection defined by the [~begin] and [~end] iterators. The [~instance] pointer must be passed as a =boost::shared_ptr= to ensure the lifetime of the instance exceeds that of any test case using the instance. The test case returned by =BOOST_PARAM_CLASS_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. [import examples/param_class_test_case.cpp][param_class_test_case] [note The single [~instance] is shared among all test cases and therefore should not keep any shared state that may couple independent test cases. In this example, the output string stream is created fresh inside each test method and not shared between calls to the method.] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/param_class_test_case.cpp param_class_test_case.cpp] [endsect] [section:boost_test_case =BOOST_TEST_CASE=] =BOOST_TEST_CASE(=[~fn]=)= creates a new test case named "fn" that executes the callable function [~fn]. The test case returned by =BOOST_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. [import examples/test_case.cpp][test_case] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/test_case.cpp test_case.cpp] [endsect] [section:boost_test_case_template =BOOST_TEST_CASE_TEMPLATE=] =BOOST_TEST_CASE_TEMPLATE(=[~name], [~types]=)= manually creates a set of test cases from the template test case [~name] for each type in [~types]. The test case returned by =BOOST_TEST_CASE_TEMPLATE= must be added to a test suite in an initialization function for the tests to be executed. The test case function is defined with the __boost_test_case_template_function__ macro. [import examples/test_case_template.cpp][test_case_template] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/test_case_template.cpp test_case_template.cpp] [endsect] [section:boost_test_case_template_function =BOOST_TEST_CASE_TEMPLATE_FUNCTION=] =BOOST_TEST_CASE_TEMPLATE_FUNCTION(=[~name], [~T]=)= defines a test case function named [~name] that is parameterized by a type parameter [~T]. The defined functions are then available for registration as parameterized test cases with __boost_test_case_template__. [test_case_template_function] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/test_case_template.cpp test_case_template.cpp] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-test-case.qbk.bak ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:test_case Test Cases] A test case is a named body of code providing the three phases of a test: setup, exercise and verify. A test case is most conveniently created using one of the provided test case macros listed in the following table. [table Test Case Macros [[Macro] [Description]] [[=BOOST_AUTO_TEST_CASE(=[~name]=)=] [Creates test case [~name] and automatically registers it with the test runner.]] [[=BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(=[~name], [~count]=)=] [Informs the test runner that test case [~name] should result in [~count] failures.]] [[=BOOST_AUTO_TEST_CASE_TEMPLATE(=[~name], [~T], [~types]=)=] [Automatically registers a test case [~name] parameterized by the template argument [~T] over the collection of [~types].]] [[=BOOST_FIXTURE_TEST_CASE(=[~name], [~fixture]=)=] [Creates test case [~name] derived from the fixture [~fixture] and automatically registers it with the test runner.]] [[=BOOST_PARAM_TEST_CASE(=[~fn], [~begin], [~end]=)=] [Manually creates a parameterized test case using the supplied callable object [~fn] and parameter iterators [~begin] and [~end].]] [[=BOOST_PARAM_CLASS_TEST_CASE(=[~fn], [~instance], [~begin], [~end]=)=] [Manually creates a parameterized test case using the supplied callable object [~fn], class instance [~instance] and parameter iterators [~begin] and [~end].]] [[=BOOST_TEST_CASE(=[~fn]=)=] [Manually creates a test case using the supplied callable object [~fn].]] [[=BOOST_TEST_CASE_TEMPLATE(=[~name], [~types]=)=] [Manually creates a set of test cases from the template test case [~name] for each type in [~types].]] [[=BOOST_TEST_CASE_TEMPLATE_FUNCTION(=[~name], [~T]=)=] [Manually creates a template test case [~name] parameterized by the template argument [~T].]] ] [section:boost_auto_test_case =BOOST_AUTO_TEST_CASE=] =BOOST_AUTO_TEST_CASE(=[~name]=)= creates a test case class, a test case invocation function, a test case unique identifier, registers the invocation function as a test case and begins the definition of the test method on the test class. The test case class [~name] is derived from =BOOST_AUTO_TEST_CASE_FIXTURE= and contains a single method named =test_method=. The test invocation function instantiates the test case class and invokes the test case method. Test log checkpoints are made before the test case class is instantiated and bracketing the test method invocation. This provides diagnostic checkpoints should a runtime error cause a test case to be aborted before any assertions are made. [heading Example Source Code] * Tutorials: * [link test.tutorials.hello_test Hello, Test!] * System under test: * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/hello_test/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_auto_test_case_expected_failures =BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES=] =BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES(=[~name], [~n]=)= is used to decorate a test case with an expected failure count of [~n]. It should appear immediately preceding the macro that defines the test case, such as __boost_auto_test_case__ or __boost_fixture_test_case__. It can be used for test cases declared at file scope or within a test suite. This macro should only be used in the most exceptional of circumstances. Unit tests are designed to provide a safety net of regression tests against our code. If we allow tests to stay failing, we are less motivated to correct them. As a temporary measure, we may wish to annotate certain tests as known failures. The count [~n] is the number of expected failed assertions during the execution of the test case. When using the [link test.reference.assertion.levels =CHECK=] level assertions, the total failure count can be larger than one since the test case continues executing past a failed assertion. When using =REQUIRE= level assertions, the total failure count will only be one as execution of the test case terminates on the first failed assertion. If =CHECK= level assertions are used and the number of failures is less than or equal to [~n], the test runner will return a status code of =0=. If the number of failures is greather than [~n], the test runner will return a status code of =201=. If =REQUIRE= level assertions are used, the number of expected failures can be at most one and the test runner will return a status code of =200= when one failed assertion is found. [import examples/auto_test_case_expected_failures.cpp] [expected_failures] [note When using the compiler formatted test output, Visual Studio interprets the failed assertion output as a detected error, it will fail the Post-Build event mechanism recommended in [link test.guide.test_case_design Test Case Design and Maintenance].] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/auto_test_case_expected_failures.cpp auto_test_case_expected_failures.cpp] [endsect] [section:boost_auto_test_case_template =BOOST_AUTO_TEST_CASE_TEMPLATE=] =BOOST_AUTO_TEST_CASE_TEMPLATE(=[~name], [~var], [~types]=)= declares a test case [~name] parameterized by a single template argument [~var] that is evaluated for each type in [~types]. This allows you to write a test case that exercises an invariant across a collection of types. The macro expands into one test case for each type in [~types], with the template argument [~var] assigned to each type. The [~types] argument must be a Boost.MPL type list and must be defined as a =typedef=. [import examples/auto_test_case_template.cpp] [auto_test_case_template] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/auto_test_case_template.cpp auto_test_case_template.cpp] [endsect] [section:boost_fixture_test_case =BOOST_FIXTURE_TEST_CASE=] =BOOST_FIXTURE_TEST_CASE(=[~name], [~fixture]=)= defines a test case class [~name] that derives from [~fixture]. If the test case is declared within a test suite that also has a test fixture, then to get the cumulative effect of both fixtures the test case fixture should derive from the test suite's fixture. Otherwise, the test case fixture will replace the test suite fixture for a test case defined with =BOOST_FIXTURE_TEST_CASE=. [heading Example Source Code] * Tutorials: * [link test.tutorials.testing_with_fixtures Testing With Fixtures] * System under test: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_global_fixture =BOOST_GLOBAL_FIXTURE=] =BOOST_GLOBAL_FIXTURE(=[~name]=)= declares a global fixture that is constructed before executing any test cases and is destroyed after executing all test cases. If more than one global fixture is defined in a single source file, the fixtures are constructed in the order they appear in the source file and destroyed in the reverse order. If global fixtures are defined in multiple source files, the order in which global fixtures are initialized between source files is implementation dependent. Because global fixtures are not created and destroyed for each test case, they represent shared state that prevents test cases from executing independently from each other. For this reason, test case fixtures created with __boost_fixture_test_case__ and test suite fixtures created with __boost_fixture_test_suite__ are preferred over global fixtures. [import examples/global_fixture.cpp][global_fixture] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/another_global_fixture.cpp another_global_fixture.cpp] * [@boost:/libs/test/doc/src/examples/global_fixture.cpp global_fixture.cpp] [endsect] [section:boost_param_test_case =BOOST_PARAM_TEST_CASE=] =BOOST_PARAM_TEST_CASE(=[~fn], [~begin], [~end]=)= creates a series of test cases that invoking the callable object [~fn] on the items in the collection defined by [~begin] and [~end]. The test case returned by =BOOST_PARAM_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. The iterators [~begin] and [~end] must be valid at the time the test case executes and not just at the time the test case is created. [import examples/param_test_case.cpp][param_test_case] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/param_test_case.cpp param_test_case.cpp] [endsect] [section:boost_param_class_test_case =BOOST_PARAM_CLASS_TEST_CASE=] =BOOST_PARAM_CLASS_TEST_CASE(=[~memfn], [~instance], [~begin], [~end]=)= works similarly to __boost_param_test_case__. It creates a collection of test cases that invoke the member function [~memfn] on the instance pointer [~instance]. The member function is passed an item obtained by iterating the collection defined by the [~begin] and [~end] iterators. The [~instance] pointer must be passed as a =boost::shared_ptr= to ensure the lifetime of the instance exceeds that of any test case using the instance. The test case returned by =BOOST_PARAM_CLASS_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. [import examples/param_class_test_case.cpp][param_class_test_case] [note The single [~instance] is shared among all test cases and therefore should not keep any shared state that may couple independent test cases. In this example, the output string stream is created fresh inside each test method and not shared between calls to the method.] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/param_class_test_case.cpp param_class_test_case.cpp] [endsect] [section:boost_test_case =BOOST_TEST_CASE=] =BOOST_TEST_CASE(=[~fn]=)= creates a new test case named "fn" that executes the callable function [~fn]. The test case returned by =BOOST_TEST_CASE= must be added to a test suite in an initialization function for the tests to be executed. [import examples/test_case.cpp][test_case] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/test_case.cpp test_case.cpp] [endsect] [section:boost_test_case_template =BOOST_TEST_CASE_TEMPLATE=] =BOOST_TEST_CASE_TEMPLATE(=[~name], [~types]=)= manually creates a set of test cases from the template test case [~name] for each type in [~types]. The test case returned by =BOOST_TEST_CASE_TEMPLATE= must be added to a test suite in an initialization function for the tests to be executed. The test case function is defined with the __boost_test_case_template_function__ macro. [import examples/test_case_template.cpp][test_case_template] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/test_case_template.cpp test_case_template.cpp] [endsect] [section:boost_test_case_template_function =BOOST_TEST_CASE_TEMPLATE_FUNCTION=] =BOOST_TEST_CASE_TEMPLATE_FUNCTION(=[~name], [~T]=)= defines a test case function named [~name] that is parameterized by a type parameter [~T]. The defined functions are then available for registration as parameterized test cases with __boost_test_case_template__. [test_case_template_function] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/test_case_template.cpp test_case_template.cpp] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-test-classes.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:test_classes Test Classes] Most of the time you will not need to interact with the classes in __test__ because the macro facilities for assertions, test cases and test suites hide all the details of the classes. If you are adapting legacy test code to __test__ you may need to interact with these classes in order to leverage existing test code without significant refactoring of the legacy test code. The [link test.reference.test_classes.predicate_result =predicate_result=] class is used to combine a boolean result from a predicate with a custom failure message for reporting additional detail in the context of a failed assertion. The [link test.reference.test_classes.test_unit =test_unit=], [link test.reference.test_classes.test_case =test_case=], [link test.reference.test_classes.test_suite =test_suite=] and [link test.reference.test_classes.master_test_suite_t =master_test_suite_t=] classes provide the interface to test suites and their test cases for the test runner. The [link test.reference.test_classes.test_observer =test_observer=], [link test.reference.test_classes.unit_test_log_t =unit_test_log_t=] and [link test.reference.test_classes.unit_test_log_formatter =unit_test_log_formatter=] classes provide low-level interaction with the test runner log. [section:predicate_result =predicate_result=] The =predicate_result= class combines a boolean result from a predicate with a detailed context message for a failed predicate evaluation. Usually this class is only used in the internal implementation of the test framework, but a user can define their own custom predicates that return a =predicate_result= to support detailed failure messages when an assertion fails. =predicate_result= is constructable and assignable from =bool=. The =message()= method returns an output string stream that can be used to build up a context message. [import ../../../../boost/test/predicate_result.hpp] [predicate_result_decl] See __boost_require_message__ for an example using =predicate_result=. [endsect] [section:test_unit =test_unit=] The =test_unit= class forms the basis of the hierarchical tree of test cases. Test applications will usually create instances of =test_case= or =test_suite=, both of which derive from =test_unit=. [import ../../../../boost/test/unit_test_suite_impl.hpp][test_unit_decl] [endsect] [section:test_case =test_case=] The =test_case= class represents a single test case. A test case must be added to a test suite reachable from the master test suite in order for the test runner to run the test case. [test_case_decl] [endsect] [section:test_suite =test_suite=] The =test_suite= class represents a group of test cases and suites in the test tree hierarchy. [test_suite_decl] [endsect] [section:master_test_suite_t =master_test_suite_t=] The master test suite of type =master_test_suite_t= is the starting point for the test runner. [master_test_suite_t_decl] You can obtain a reference to the master test suite with the =master_test_suite()= function: [import ../../../../boost/test/framework.hpp][master_test_suite_decl] [endsect] [section:test_observer =test_observer=] The =test_observer= class encapsulates observers of test execution. It provides a simple /null/ style observer behavior. [import ../../../../boost/test/test_observer.hpp][test_observer_decl] [endsect] [section:unit_test_log_t =unit_test_log_t=] The =unit_test_log_t= class encapsulates the unit test log. You obtain a reference to the single global unit test log instance with the =unit_test_log= member. [import ../../../../boost/test/unit_test_log.hpp][unit_test_log_t_decl] [endsect] [section:unit_test_log_formatter =unit_test_log_formatter=] The =unit_test_log_formatter= class encapsulates formatting of log events for an output stream. [import ../../../../boost/test/unit_test_log_formatter.hpp][unit_test_log_formatter_decl] [endsect] [section:init_unit_test_func =init_unit_test_func=] The =init_unit_test_func= function typedef identifies the signature of the user supplied initialization function. The initialization function can be used to add custom test cases and test suites to the test tree. [init_unit_test_func_decl] [endsect] [section:unit_test_main =unit_test_main=] The =unit_test_main= function provides an implementation of =main= that can be used by a test executable compiled with __boost_test_no_main__. [import ../../../../boost/test/unit_test.hpp][unit_test_main_decl] =unit_test_main= initializes the test framework, traverses the test tree and reports the result as a the return value of the function. Unexpected exceptions and system errors (signals, etc.) are caught and mapped to appropriate return values by the function. [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/ref-test-suite.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:test_suite Test Suites] A test suite is an ordered collection of test cases and other test suites. The test cases in a suite are executed in the order in which they are added to the suite. When test cases are automatically registered, they are added to the test suite in the order of their definition in the source file. [section:boost_auto_test_suite =BOOST_AUTO_TEST_SUITE=] The =BOOST_AUTO_TEST_SUITE(=[~name]=)= macro defines an automatically registered test suite named [~name] and opens a namespace named [~name]. A test suite can be nested within another test suite. Each test suite begun with =BOOST_AUTO_TEST_SUITE= must be ended with [link test.reference.test_suite.boost_auto_test_suite_end =BOOST_AUTO_TEST_SUITE_END=] The new test suite is registered within its enclosing test suite, or the master test suite if there is no enclosing test suite. [heading Example Source Code] * Tutorials: * [link test.tutorials.running_selected_tests Running Selected Tests] * System under test: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_auto_test_suite_end =BOOST_AUTO_TEST_SUITE_END=] The =BOOST_AUTO_TEST_SUITE_END()= macro ends the test suite most recently defined with [link test.reference.test_suite.boost_auto_test_suite =BOOST_AUTO_TEST_SUITE=] or [link test.reference.test_suite.boost_fixture_test_suite =BOOST_FIXTURE_TEST_SUITE=]. The corresponding namespace created when the test suite was defined is closed by =BOOST_AUTO_TEST_SUITE_END=. [heading Example Source Code] * Tutorials: * [link test.tutorials.running_selected_tests Running Selected Tests] * System under test: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_fixture_test_suite =BOOST_FIXTURE_TEST_SUITE=] The =BOOST_FIXTURE_TEST_SUITE(=[~suite], [~fixture]=)= macro begins the test suite named [~suite] and uses [~fixture] as a test fixture to be used as the base class of all test case classes created in the suite with =BOOST_AUTO_TEST_CASE=. [heading Example Source Code] * Tutorials: * [link test.tutorials.running_selected_tests Running Selected Tests] * System under test: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/test/test_hello.cpp test_hello.cpp] [endsect] [section:boost_test_module =BOOST_TEST_MODULE=] The =BOOST_TEST_MODULE= macro is used to define the name of the master test suite. If =BOOST_TEST_MODULE= is defined, it should be defined in exactly one source file. It can be defined to a list of preprocessor tokens or a string literal. If a string literal is used, surrounding quotation marks (="=), will not appear in the name of the master test suite. [example_test_module] [heading Example Source Code] * Tests: * [@boost:/libs/test/doc/src/examples/assertions.cpp assertions.cpp] [endsect] [section:boost_test_suite =BOOST_TEST_SUITE=] The =BOOST_TEST_SUITE(=[~name]=)= macro is used to create a new test suite named [~name]. The new suite must be added to the master test suite in order for any test cases in the suite to be executed. [register_test_suite] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/manual_registration.cpp manual_registration.cpp] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/reference.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:reference Reference] [import examples/assertions.cpp] [import examples/assertion_failures.cpp] [include:test ref-compilation.qbk] [include:test ref-test-case.qbk] [include:test ref-test-suite.qbk] [include:test ref-test-classes.qbk] [include:test ref-assertion.qbk] [include:test ref-runner.qbk] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias system_under_test : hello//hello scanner//scanner ; build-project hello ; build-project scanner ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/hello/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) lib hello : hello.cpp : static ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/hello/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/hello/hello.hpp ================================================ //[ hello_test_sut_hpp #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/scanner/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) lib scanner : scanner.cpp : static ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/scanner/directory_scanner.hpp ================================================ #if !defined(DIRECTORY_SCANNER_H) #define DIRECTORY_SCANNER_H #include //[directory_scanner class directory_scanner { public: virtual ~directory_scanner() {} virtual void begin(std::string const &directory) = 0; virtual bool has_next() const = 0; virtual std::string next() const = 0; }; //] #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/scanner/filesystem_directory_scanner.hpp ================================================ #if !defined(FILESYSTEM_DIRECTORY_SCANNER_H) #define FILESYSTEM_DIRECTORY_SCANNER_H #include "directory_scanner.hpp" #include //[filesystem_directory_scanner class filesystem_directory_scanner : public directory_scanner { public: filesystem_directory_scanner() {} virtual ~filesystem_directory_scanner() {} virtual void begin(std::string const &directory) { current = boost::filesystem::directory_iterator(directory); } virtual bool has_next() const { return current != end; } virtual std::string next() const { if (has_next()) { std::string const result = (*current).path().filename().string(); do { ++current; } while (has_next() && !boost::filesystem::is_regular_file((*current).path())); return result; } throw std::runtime_error("no next path"); } private: mutable boost::filesystem::directory_iterator current; boost::filesystem::directory_iterator end; }; //] #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/scanner/scanner.cpp ================================================ #include "scanner.hpp" #include "filesystem_directory_scanner.hpp" //[text_files_dependency_impl extern std::vector text_files(std::string const &directory, directory_scanner &scanner) { std::vector files; scanner.begin(directory); while (scanner.has_next()) { std::string file(scanner.next()); if (file.length() >= 4 && file.substr(file.length() - 4) == ".txt") { files.push_back(file); } } return files; } //] //[text_files_impl extern std::vector text_files(std::string const& directory) { filesystem_directory_scanner scanner; return text_files(directory, scanner); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/system_under_test/scanner/scanner.hpp ================================================ #if !defined(SCANNER_HPP) #define SCANNER_HPP #include #include //[text_files_decl extern std::vector text_files(std::string const& directory); //] //[text_files_dependency_decl class directory_scanner; extern std::vector text_files( std::string const& directory, directory_scanner& scanner); //] #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/test.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [library Boost.Test [quickbook 1.5] [authors [Thomson, Richard]] [copyright 2013 Richard Thomson] [/ purpose Unit Testing Library] [license Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at [@http://www.boost.org/LICENSE_1_0.txt]) ] [id test] [source-mode c++] [dirname test] ] [/ April 23, 2013 ] [/ TODO: Stuff that needs to be fixed by these docs: https://svn.boost.org/trac/boost/ticket/2600 document method test_unit::depends_on https://svn.boost.org/trac/boost/ticket/7136 Correct documentation for BOOST__CLOSE_FRACTION is not reflected into released documents ] [/ Some symbols ] [def __test__ Boost.Test] [/ Some web links ] [def __test_driven_development__ [@http://en.wikipedia.org/wiki/Test-driven_development test-driven development]] [def __xunit_patterns__ [@http://xunitpatterns.com xUnit Test Patterns]] [/ Internal links to the reference ] [def __boost_fail__ [link test.reference.assertion.boost_fail =BOOST_FAIL=]] [def __boost_require_equal__ [link test.reference.assertion.boost_level_equal =BOOST_REQUIRE_EQUAL=]] [def __boost_require_exception__ [link test.reference.assertion.boost_level_exception =BOOST_REQUIRE_EXCEPTION=]] [def __boost_require_message__ [link test.reference.assertion.boost_level_message =BOOST_REQUIRE_MESSAGE=]] [def __boost_require_no_throw__ [link test.reference.assertion.boost_level_no_throw =BOOST_REQUIRE_NO_THROW=]] [def __boost_require_throw__ [link test.reference.assertion.boost_level_throw =BOOST_REQUIRE_THROW=]] [def __boost_test_alternative_init_api__ [link test.reference.compilation.boost_test_alternative_init_api =BOOST_TEST_ALTERNATIVE_INIT_API=]] [def __boost_test_dyn_link__ [link test.reference.compilation.boost_test_dyn_link =BOOST_TEST_DYN_LINK=]] [def __boost_test_main__ [link test.reference.compilation.boost_test_main =BOOST_TEST_MAIN=]] [def __boost_test_no_lib__ [link test.reference.compilation.boost_test_no_lib =BOOST_TEST_NO_LIB=]] [def __boost_test_no_main__ [link test.reference.compilation.boost_test_no_main =BOOST_TEST_NO_MAIN=]] [def __auto_start_dbg__ [link test.reference.runner.argument.auto_start_dbg =--auto_start_dbg=]] [def __log_format__ [link test.reference.runner.argument.log_format =--log_format=]] [def __log_level__ [link test.reference.runner.argument.log_level =--log_level=]] [def __log_sink__ [link test.reference.runner.argument.log_sink =--log_sink=]] [def __output_format__ [link test.reference.runner.argument.output_format =--output_format=]] [def __report_format__ [link test.reference.runner.argument.report_format =--report_format=]] [def __report_level__ [link test.reference.runner.argument.report_level =--report_level=]] [def __report_sink__ [link test.reference.runner.argument.report_sink =--report_sink=]] [def __run_test__ [link test.reference.runner.argument.run_test =--run_test=]] [def __boost_test_checkpoint__ [link test.reference.runner.output.boost_test_checkpoint =BOOST_TEST_CHECKPOINT=]] [def __boost_test_message__ [link test.reference.runner.output.boost_test_message =BOOST_TEST_MESSAGE=]] [def __boost_auto_test_case__ [link test.reference.test_case.boost_auto_test_case =BOOST_AUTO_TEST_CASE=]] [def __boost_fixture_test_case__ [link test.reference.test_case.boost_fixture_test_case =BOOST_FIXTURE_TEST_CASE=]] [def __boost_param_test_case__ [link test.reference.test_case.boost_param_test_case =BOOST_PARAM_TEST_CASE=]] [def __boost_test_case__ [link test.reference.test_case.boost_test_case =BOOST_TEST_CASE=]] [def __boost_test_case_template__ [link test.reference.test_case.boost_test_case_template =BOOST_TEST_CASE_TEMPLATE=]] [def __boost_test_case_template_function__ [link test.reference.test_case.boost_test_case_template_function =BOOST_TEST_CASE_TEMPLATE_FUNCTION=]] [def __boost_auto_test_suite__ [link test.reference.test_suite.boost_auto_test_suite =BOOST_AUTO_TEST_SUITE=]] [def __boost_fixture_test_suite__ [link test.reference.test_suite.boost_fixture_test_suite =BOOST_FIXTURE_TEST_SUITE=]] [def __boost_test_suite__ [link test.reference.test_suite.boost_test_suite =BOOST_TEST_SUITE=]] [def __predicate_result__ [link test.reference.test_classes.predicate_result =predicate_result=]] [def __unit_test_main__ [link test.reference.test_classes.unit_test_main =unit_test_main=]] [/ Some images ] [def __note__ [$./images/note.png]] [def __tip__ [$./images/tip.png]] [def __important__ [$./images/important.png]] [def __caution__ [$./images/caution.png]] [def __danger__ [$./images/alert.png]] This is the documentation for __test__, a library designed to support automated testing of software generally and unit testing specifically. [/----------------------------------------------------------------------] [section Motivation] Automated tests are an important part of verifying software. At the developer level, automated tests provide confidence that changes made to the software do not result in new defects. At the customer level, automated tests provide confidence that new features meet expectations and existing features continue to function unchanged. __test__ is a library that supports the automated testing of software, primarily aimed at satisfying the needs of the developer. [endsect] [/----------------------------------------------------------------------] [section How To Read This Documentation] This documentation provides material for both new users and advanced users. If you are completely new to automated testing, you may wish to read Wikipedia's article on __test_driven_development__ and consult the online book __xunit_patterns__. The amount of information available on automated testing has exploded in the past decade and these are only some suggested starting points and not intended to be an exhaustive list. To get started quickly writing your first test, read the [link test.tutorials tutorial] sections. For advice on designing and maintaining your tests, read the section on [link test.guide.test_case_design test case design]. For advanced uses of the library, consult the [link test.reference reference]. [endsect] [include:test tutorials.qbk] [include:test user-guide.qbk] [include:test reference.qbk] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias tutorials : hello_test//tutorial_hello_test running_selected_tests testing_with_exceptions testing_with_fixtures ; build-project hello_test ; build-project running_selected_tests ; build-project testing_with_exceptions ; build-project testing_with_fixtures ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/1/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias tutorial_hello_test.1 : hello.1 hello_test.1 ; lib hello.1 : sut/hello.cpp : static ; run-fail test/test_hello.cpp hello.1 : : : sut : hello_test.1 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/1/hello_test~1.output ================================================ [pre Running 1 test case... src/tutorials/hello_test/1/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\\n" == dest.str() failed [Hello, world! != \] *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/1/sut/hello.cpp ================================================ //[ hello_test_sut_cpp1 #include "hello.hpp" void hello_world(std::ostream& stream) { } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/1/sut/hello.hpp ================================================ //[ hello_test_sut_hpp1 #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/1/test/test_hello.cpp ================================================ //[ hello_test_test_cpp1 #define BOOST_TEST_MAIN #include #include "hello.hpp" #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/2/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias tutorial_hello_test.2 : hello.2 hello_test.2 ; lib hello.2 : sut/hello.cpp : static ; run-fail test/test_hello.cpp hello.2 : : : sut : hello_test.2 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/2/hello_test~2.output ================================================ [pre Running 1 test case... src/tutorials/hello_test/2/test/test_hello.cpp(13): fatal error in "hello_world_inserts_text": critical check "Hello, world!\\n" == dest.str() failed [Hello, world! != Hello, world!\] *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/2/sut/hello.cpp ================================================ //[ hello_test_sut_cpp2 #include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!"; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/2/sut/hello.hpp ================================================ //[ hello_test_sut_hpp2 #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/2/test/test_hello.cpp ================================================ //[ hello_test_test_cpp2 #define BOOST_TEST_MAIN #include #include "hello.hpp" #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/3/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias tutorial_hello_test.3 : hello.3 hello_test.3 ; lib hello.3 : sut/hello.cpp : static ; run test/test_hello.cpp hello.3 : : : sut : hello_test.3 ;  ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/3/hello_test~3.output ================================================ [pre Running 1 test case... *** No errors detected EXIT STATUS: 0 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/3/sut/hello.cpp ================================================ //[ hello_test_sut_cpp3 #include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!" << std::endl; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/3/sut/hello.hpp ================================================ //[ hello_test_sut_hpp3 #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/3/test/test_hello.cpp ================================================ //[ hello_test_test_cpp2 #define BOOST_TEST_MAIN #include #include "hello.hpp" #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias tutorial_hello_test : 1//tutorial_hello_test.1 2//tutorial_hello_test.2 3//tutorial_hello_test.3 hello.tutorial_hello_test hello_test ; build-project 1 ; build-project 2 ; build-project 3 ; lib hello.tutorial_hello_test : sut/hello.cpp : static ; run test/test_hello.cpp hello.tutorial_hello_test : : : sut : hello_test ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/hello_test.output ================================================ [pre Running 1 test case... *** No errors detected EXIT STATUS: 0 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/sut/hello.cpp ================================================ //[ hello_test_sut_cpp #include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!\n"; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/sut/hello.hpp ================================================ //[ hello_test_sut_hpp #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/hello_test/test/test_hello.cpp ================================================ //[ hello_test_test_cpp #define BOOST_TEST_MAIN #include #include "hello.hpp" #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias running_selected_tests.1 : hello.running_selected_tests.1 test_hello.running_selected_tests.1 ; lib hello.running_selected_tests.1 : sut/hello.cpp : static ; run test/test_hello.cpp hello.running_selected_tests.1 : --run_test=hello_world_inserts_text,hello_world_stream_with_badbit_throws_runtime_error : : sut : test_hello.running_selected_tests.1 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/report_level_detailed.output ================================================ [pre > test_hello --report_level=detailed Running 2 test cases... Test suite "Master Test Suite" passed with: 2 assertions out of 2 passed 2 test cases out of 2 passed Test case "hello_world_inserts_text" passed with: 1 assertion out of 1 passed Test case "hello_world_stream_with_badbit_throws_runtime_error" passed with: 1 assertion out of 1 passed ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/sut/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/sut/hello.hpp ================================================ #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include //[running_selected_tests_test_cpp_1 struct hello_world_fixture { std::ostringstream dest; }; #define HELLO_WORLD_TEST_CASE(name_) \ BOOST_FIXTURE_TEST_CASE(hello_world_##name_, hello_world_fixture) HELLO_WORLD_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } HELLO_WORLD_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/1/test_hello~running_selected_tests~1.output ================================================ [pre > test_hello --run_test=hello_world_inserts_text,hello_world_stream_with_badbit_throws_runtime_error Running 2 test cases... *** No errors detected EXIT STATUS: 0 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias running_selected_tests.2 : hello.running_selected_tests.2 test_hello.running_selected_tests.2 ; lib hello.running_selected_tests.2 : sut/hello.cpp : static ; run test/test_hello.cpp hello.running_selected_tests.2 : --run_test=test_hello : : sut : test_hello.running_selected_tests.2 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/report_level_detailed.output ================================================ [pre > test_hello --report_level=detailed Running 2 test cases... Test suite "Master Test Suite" passed with: 2 assertions out of 2 passed 2 test cases out of 2 passed Test suite "test_hello" passed with: 2 assertions out of 2 passed 2 test cases out of 2 passed Test case "hello_world_inserts_text" passed with: 1 assertion out of 1 passed Test case "hello_world_stream_with_badbit_throws_runtime_error" passed with: 1 assertion out of 1 passed ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/run_test_hello_inserts_text.output ================================================ [pre > test_hello --run_test=test_hello/hello_world_inserts_text Running 1 test case... *** No errors detected ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/run_test_hello_star_inserts_text.output ================================================ [pre > test_hello --run_test=hello_world/*inserts_text Running 1 test case... *** No errors detected ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/sut/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/sut/hello.hpp ================================================ #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include //[running_selected_tests_test_cpp_2 struct hello_world_fixture { std::ostringstream dest; }; BOOST_AUTO_TEST_SUITE(test_hello); #define HELLO_WORLD_TEST_CASE(name_) \ BOOST_FIXTURE_TEST_CASE(hello_world_##name_, hello_world_fixture) HELLO_WORLD_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } HELLO_WORLD_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/2/test_hello~running_selected_tests~2.output ================================================ [pre > test_hello --run_test=test_hello Running 2 test cases... *** No errors detected EXIT STATUS: 0 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias running_selected_tests : 1//running_selected_tests.1 2//running_selected_tests.2 ; build-project 1 ; build-project 2 ; lib hello.running_selected_tests : sut/hello.cpp : static ; run test/test_hello.cpp hello.running_selected_tests : : : sut : test_hello ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/report_level_detailed.output ================================================ [pre > test_hello.exe --report_level=detailed Running 2 test cases... Test suite "Master Test Suite" passed with: 2 assertions out of 2 passed 2 test cases out of 2 passed Test suite "test_hello" passed with: 2 assertions out of 2 passed 2 test cases out of 2 passed Test case "inserts_text" passed with: 1 assertion out of 1 passed Test case "stream_with_badbit_throws_runtime_error" passed with: 1 assertion out of 1 passed ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.hpp ================================================ #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/running_selected_tests/test/test_hello.cpp ================================================ //[ running_selected_tests_test_cpp #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include struct hello_world_fixture { std::ostringstream dest; }; BOOST_FIXTURE_TEST_SUITE(test_hello, hello_world_fixture); BOOST_AUTO_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_AUTO_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } BOOST_AUTO_TEST_SUITE_END(); //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/1/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias testing_with_exceptions.1 : hello.testing_with_exceptions.1 test_hello.testing_with_exceptions.1 ; lib hello.testing_with_exceptions.1 : sut/hello.cpp : static ; run-fail test/test_hello.cpp hello.testing_with_exceptions.1 : : : sut : test_hello.testing_with_exceptions.1 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/1/sut/hello.cpp ================================================ //[ testing_with_exceptions_sut_cpp_1 #include "hello.hpp" void hello_world(std::ostream& stream) { stream << "Hello, world!\n"; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/1/sut/hello.hpp ================================================ //[ testing_with_exceptions_sut_hpp_1 #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/1/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //[ hello_world_stream_with_badbit_throws_runtime_error_1 BOOST_AUTO_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error) { std::ostringstream dest; dest.clear(std::ios_base::badbit); hello_world(dest); BOOST_FAIL("std::runtime_error not thrown"); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/1/test_hello~testing_with_exceptions~1.output ================================================ [pre Running 2 test cases... src/tutorials/testing_with_exceptions/1/test/test_hello.cpp(24): fatal error in "hello_world_stream_with_badbit_throws_runtime_error": std::runtime_error not thrown *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/2/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias testing_with_exceptions.2 : hello.testing_with_exceptions.2 test_hello.testing_with_exceptions.2 ; lib hello.testing_with_exceptions.2 : sut/hello.cpp : static ; run-fail test/test_hello.cpp hello.testing_with_exceptions.2 : : : sut : test_hello.testing_with_exceptions.2 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/2/sut/hello.cpp ================================================ #include "hello.hpp" //[ testing_with_exceptions_sut_hello_cpp_2 void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/2/sut/hello.hpp ================================================ //[ testing_with_exceptions_sut_hpp_1 #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/2/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //[ hello_world_stream_with_badbit_throws_runtime_error_1 BOOST_AUTO_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error) { std::ostringstream dest; dest.clear(std::ios_base::badbit); hello_world(dest); BOOST_FAIL("std::runtime_error not thrown"); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/2/test_hello~testing_with_exceptions~2.output ================================================ [pre Running 2 test cases... unknown location(0): fatal error in "hello_world_stream_with_badbit_throws_runtime_error": std::runtime_error: bad stream src/tutorials/testing_with_exceptions/2/test/test_hello.cpp(13): last checkpoint *** 1 failure detected in test suite "Master Test Suite" EXIT STATUS: 201 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias testing_with_exceptions : 1//testing_with_exceptions.1 2//testing_with_exceptions.2 test_hello.testing_with_exceptions ; lib hello.testing_with_exceptions : sut/hello.cpp : static ; run test/test_hello.cpp hello.testing_with_exceptions : : : sut : test_hello.testing_with_exceptions ; build-project 1 ; build-project 2 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/sut/hello.cpp ================================================ //[ testing_with_exceptions_sut_cpp #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/sut/hello.hpp ================================================ //[ testing_with_exceptions_sut_hpp #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include BOOST_AUTO_TEST_CASE(hello_world_inserts_text) { std::ostringstream dest; hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } //[ hello_world_stream_with_badbit_throws_runtime_error BOOST_AUTO_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error) { std::ostringstream dest; dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_exceptions/test_hello~testing_with_exceptions.output ================================================ [pre Running 2 test cases... *** No errors detected EXIT STATUS: 0 ] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/1/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias testing_with_fixtures.1 : hello.testing_with_fixtures.1 test_hello.testing_with_fixtures.1 ; lib hello.testing_with_fixtures.1 : sut/hello.cpp : static ; run test/test_hello.cpp hello.testing_with_fixtures.1 : : : sut : test_hello.testing_with_fixtures.1 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/1/sut/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/1/sut/hello.hpp ================================================ #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/1/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include //[testing_with_fixtures_test_cpp_1 struct hello_world_fixture { hello_world_fixture() : dest() { } ~hello_world_fixture() { } std::ostringstream dest; }; BOOST_FIXTURE_TEST_CASE(hello_world_inserts_text, hello_world_fixture) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } BOOST_FIXTURE_TEST_CASE(hello_world_stream_with_badbit_throws_runtime_error, hello_world_fixture) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/Jamfile.v2 ================================================ # Jamfile.v2 # # Copyright (c) 2013 # Richard Thomson # # Distributed Under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) alias testing_with_fixtures : 1//testing_with_fixtures.1 test_hello.testing_with_fixtures ; lib hello.testing_with_fixtures : sut/hello.cpp : static ; run test/test_hello.cpp hello.testing_with_fixtures : : : sut : test_hello.testing_with_fixtures ; build-project 1 ; ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.cpp ================================================ #include "hello.hpp" void hello_world(std::ostream& stream) { if (stream.bad()) { throw std::runtime_error("bad stream"); } stream << "Hello, world!\n"; } ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.hpp ================================================ #if !defined(HELLO_HPP) #define HELLO_HPP #include extern void hello_world(std::ostream& stream); #endif ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials/testing_with_fixtures/test/test_hello.cpp ================================================ #define BOOST_TEST_MAIN #include #include "hello.hpp" #include #include //[testing_with_fixtures_test_cpp struct hello_world_fixture { std::ostringstream dest; }; #define HELLO_WORLD_TEST_CASE(name_) \ BOOST_FIXTURE_TEST_CASE(hello_world_##name_, hello_world_fixture) HELLO_WORLD_TEST_CASE(inserts_text) { hello_world(dest); BOOST_REQUIRE_EQUAL("Hello, world!\n", dest.str()); } HELLO_WORLD_TEST_CASE(stream_with_badbit_throws_runtime_error) { dest.clear(std::ios_base::badbit); BOOST_REQUIRE_THROW(hello_world(dest), std::runtime_error); } //] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/tutorials.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:tutorials Tutorials] These tutorials will get you started using __test__. They are intended to be read in order and proceed from the basics of [link test.tutorials.hello_test writing your first test] to [link test.tutorials.running_selected_tests running selected tests]. Once you've finished with the tutorials, you may want to read about [link test.guide.test_case_design test case design] for some suggestions on testing various situations in C++. The full details of the framework are provided in the [link test.reference reference] section. [/----------------------------------------------------------------------] [section:hello_test Hello, Test!] Suppose we wish to test that the following function, declared in =hello.hpp= and supplied by a static library =hello=, inserted the text =Hello, world!\n= to the given =stream=: [import tutorials/hello_test/1/sut/hello.hpp] [hello_test_sut_hpp1] We can accomplish this with the following test, saving it in =test_hello.cpp=: [import tutorials/hello_test/1/test/test_hello.cpp] [hello_test_test_cpp1] We compile =test_hello.cpp= and link it against the static library =hello= using the build environment for our platform to produce an executable. No other source files or libraries are needed. When we run the executable, it will execute our test case. Suppose that our implementation of =hello_world= looks like this: [import tutorials/hello_test/1/sut/hello.cpp] [hello_test_sut_cpp1] When we run the unit test executable we obtain output similar to the following:[footnote The test runner output here is generated from the =run-fail= rule in Boost.Build which includes the output from the executable and appends the exit code of the process to the output.] [include tutorials/hello_test/1/hello_test~1.output] Oops, it looks like we forgot to implement =hello_world=!. Let's fix that by changing =hello.cpp= to the following: [import tutorials/hello_test/2/sut/hello.cpp] [hello_test_sut_cpp2] We can now rebuild our library, relink our unit test executable and re-run the test: [include tutorials/hello_test/2/hello_test~2.output] Oops, looks like we forgot to insert the newline character. Let's fix that by changing =hello.cpp= to the following: [import tutorials/hello_test/3/sut/hello.cpp] [hello_test_sut_cpp3] We rebuild our library, relink our unit test executable again and re-run the test: [include tutorials/hello_test/3/hello_test~3.output] Now all our tests are passing and we know that =hello_world= does what we expect it to do. We used =std::endl= to insert the newline character and it also flushes the output stream after inserting the newline. If we didn't want the output stream to be flushed, we can change =hello_world= to use a character literal: [import tutorials/hello_test/sut/hello.cpp] [hello_test_sut_cpp] We rebuild and re-run the test to verify that our change didn't break anything: [include tutorials/hello_test/hello_test.output] [heading Some Observations] Now that we've seen __test__ in action, let's take a closer look at what we have just done: * The entire unit test framework was brought into our test application with a single include ==. We didn't link against any libraries or introduce any run-time dependencies. * We didn't write an implementation of =main=, but our test executable linked and ran. Why? The preprocessor symbol __boost_test_main__ instructed __test__ to supply an implementation of =main= that executes all tests registered with the framework. * The macro __boost_auto_test_case__ registered our unit test case with the framework and provides the necessary preamble for the implementation of the testing function. * The argument to __boost_auto_test_case__ is the name of our test case and is a C++ identifier, not a string. * The test was structured in three phases: setup, exercise, and verify. * Our setup phase created an output string stream in order to capture the output of =hello_world=, the system under test. * The exercise phase called the system under test, our function =hello_world=. * The verify phase checked that the function provided the expected output using the assertion macro __boost_require_equal__. * To make the phases of the test obvious, we used blank lines to separate them. * A failing test emits a message that provides information about the location of the failed assertion and the detail of the failure. * The above sequence is a typical example of test-driven development, proceeding through stages of "red", "green" and "refactor". * We wrote a failing test and just enough implementation to compile the test ("red"). * We then wrote the implementation and ran the test to verify our implementation. We made a simple mistake, so we corrected that and re-ran the test to verify our implementation by passing the test ("green"). * Once our implementation was correct, we looked at possible improvements we might make to the code; in our case we eliminated the side-effect of flushing the output stream ("refactor"). * The test code and production code, or system under test, are kept separate. The production code was in a library and the test code was in an executable. * No news is good news! We don't see any noise from test cases when they pass and the test executable emits only a summary of all test cases when all tests pass. [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/hello_test/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/hello_test/test/test_hello.cpp test_hello.cpp] [endsect] [/----------------------------------------------------------------------] [section:testing_with_exceptions Testing with Exceptions] When we're testing a system, we want to test the failure cases as well as the success cases. This means forcing the system under test down an error path by orchestrating bad inputs or synthesizing errors from code collaborating with the system under test. Let's add the requirement that [link test.tutorials.hello_test =hello_world=] should throw the a =std::runtime_error= exception if the supplied stream has the =badbit= set on the stream. We can add a test case for this: [import tutorials/testing_with_exceptions/1/test/test_hello.cpp] [hello_world_stream_with_badbit_throws_runtime_error_1] [note The [@http://en.cppreference.com/w/cpp/io/basic_ios/clear =clear= member function] on a stream clears all state bits and sets the state to the value of the argument.] Instead of an assertion macro like __boost_require_equal__, we're using the __boost_fail__ macro that guarantees test failure. If the call to =hello_world= doesn't throw a =runtime_error= exception and continues to the next line of code, then this test case fails: [include tutorials/testing_with_exceptions/1/test_hello~testing_with_exceptions~1.output] Now let's enhance the implementation to support this requirement: [import tutorials/testing_with_exceptions/2/sut/hello.cpp] [testing_with_exceptions_sut_hello_cpp_2] We run our test and get something similar to the following: [include tutorials/testing_with_exceptions/2/test_hello~testing_with_exceptions~2.output] Now the test is still failing, so what did we do wrong? The exception from our system under test unwound the call stack back into the unit test framework, which caught the exception and reported this as a failure. We need to tell the test framework that an exception is expected in this situation. We can use __boost_require_throw__ to tell the test framework that an expression is expected to throw a particular type of exception. If the exception isn't thrown or an exception of a different type is thrown, then the test fails. Our test now looks like this: [import tutorials/testing_with_exceptions/test/test_hello.cpp] [hello_world_stream_with_badbit_throws_runtime_error] Now our test case is passing: [include tutorials/testing_with_exceptions/test_hello~testing_with_exceptions.output] [heading Some Observations] * We gave our test case a name that revealed the essence of what it tests so that when it fails, we know immediately from the name of the test what requirement has been invalidated. Using intention revealing names for test cases is just as important as using intention revealing names for methods, functions and classes. * We kept each scenario we wanted to test separate and independent from each other. This keeps our tests robust; the state of one test does not interfere with any other test. * Now that we have two test cases, we can see that there is some duplication between them: the construction of an output string stream. It isn't much right now, just a single line, but duplication between tests is something we'll need to watch. * Every time we modify or add a test, we have to recompile our single test file =test_hello.cpp=, which is including the entire unit test framework source. This leads to a lengthy compile every time we have to change the tests. [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/tutorials/testing_with_exceptions/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/testing_with_exceptions/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/testing_with_exceptions/test/test_hello.cpp test_hello.cpp] [endsect] [/----------------------------------------------------------------------] [section:testing_with_fixtures Testing with Fixtures] When we added our second test case in the [link test.tutorials.testing_with_exceptions previous tutorial], we ended up with some duplicated setup between the two test cases. This is a common occurrence in unit testing. We have some prerequisites for the system under test that must be prepared in order to exercise the system. In our case, it is a single output string stream that we use for capturing the output of our =hello_world= function. __test__ provides a facility called a fixture for encapsulating repeated setup and tear down code between test cases. In our example, there isn't any explicit tear down code because the output string streams are created on the stack and destroyed when execution exits the test case. We have a little bit of repeated setup code that we can move to a fixture that is used by both our test cases. Let's put that repeated code in a fixture: [import tutorials/testing_with_fixtures/1/test/test_hello.cpp] [testing_with_fixtures_test_cpp_1] A fixture is simply a class or struct that is inherited by the test case. We connect the test case to the fixture by using __boost_fixture_test_case__ instead of __boost_auto_test_case__. The latter simply connects each test case to an empty fixture. After refactoring the test cases to use a fixture, we run the tests to make sure the tests still pass. When using a fixture, the order of construction and destruction is as follows when a test case is executed: # The fixture is constructed. # The test case class is constructed. # The test case test method is executed # The test case class is destroyed. # The fixture is destroyed. This process happens for each test case that is executed, ensuring that each test case has a fresh fixture and remains independent of other test cases. In most cases, the setup will be a little more involved than just creating an instance variable and there will be some work done in the constructor of the fixture. We could simply use the default constructor and destructor of our fixture in this case. We've written the constructor and destructor explicitly to emphasize that this is where setup and tear down occur. Now that we've transformed the test cases to use a fixture, it seems we've simply traded one piece of repetition, the construction of the output string stream, for another: the repeated use of the fixture name and system under test in our test cases. We can use a custom test case macro to get rid of this duplication: [import tutorials/testing_with_fixtures/test/test_hello.cpp] [testing_with_fixtures_test_cpp] Every test case has to have a unique name within the scope of its declaration, either the global namespace or a custom namespace, which is why we've been prefixing our test case names with the name of the system under test, =hello_world=. Once we accumulate a few tests, the chances for a clash between test names increases. With our custom test case macro, we reduce the chance for a test case name clash by ensuring that every test case name is prefixed by the name of the system under test. We ensure that every test case for =hello_world= uses the same fixture and we gain some readability of the test cases by eliminating the distracting repetition. If we change the name of the fixture, then we need only edit the custom test case macro that supplies the fixture name. In the next tutorial, we'll see an alternative way of eliminating this duplication of the prefixes of test case names. [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/testing_with_fixtures/test/test_hello.cpp test_hello.cpp] [endsect] [/----------------------------------------------------------------------] [section:running_selected_tests Running Selected Tests] As we continue to add unit tests for a library, we can get quite a large number of tests. If they are true unit tests and each test exercises a single class isolated from its collaborators, then most of the tests are not relevant to the changes we are making. The test executable accepts a number of command-line arguments that allow us to control the behavior of the test framework, including which tests to run. We can list the available tests in a test executable with __report_level__ set to detailed: [include tutorials/running_selected_tests/1/report_level_detailed.output] [caution The arguments to the test executable, such as __report_level__, use an underscore (=_=) to separate words, not a dash (=-=).] Suppose we are continuing to make changes to =hello_world= and we want to run only the tests that apply to that function. We can easily identify the relevant tests in the output of __report_level__ because we have used a test naming convention of prefixing all test case names with the name of the system under test, =hello_world=. Using the __run_test__ argument, we can specify a comma-separated list of test case names to run: [include tutorials/running_selected_tests/1/test_hello~running_selected_tests~1.output] Wow, that's really a mouthfull! Even with command recall, typing this command for the first time will require typing the exact names of all the test cases for =hello_world=. As we add more test cases, we'll have to extend the command line argument to account for each new test case. We can solve this problem by using test suites, which organize tests into a named group: [import tutorials/running_selected_tests/2/test/test_hello.cpp] [running_selected_tests_test_cpp_2] Now __report_level__ outputs the following: [include tutorials/running_selected_tests/2/report_level_detailed.output] The indentation shows that the test cases for =hello_world= are organized under the test suite named =test_hello_world=. [note We can't name the suite =hello_world= because that would conflict with the name of our system under test, as both are declared in the same global namespace.] Now we can supply the name of the test suite to __run_test__ to run all the test cases in the suite: [include tutorials/running_selected_tests/2/test_hello~running_selected_tests~2.output] As we add more test cases to the suite, we don't have to change the command we are using to run the tests and we don't need to remember the exact names of the test cases. Suites arrange test cases into a hierarchy. You can have suites within suites to provide larger groupings to test a collection of related classes together. Once a test case is part of a suite, we must use the name of the enclosing suite with the name of the test case if we wish to run a single test case within the suite by name: [include tutorials/running_selected_tests/2/run_test_hello_inserts_text.output] The names of the enclosing suites are separated from each other and from the test case name with a slash (=/=). The names supplied to __run_test__ also allow for wildcard matching: [include tutorials/running_selected_tests/2/run_test_hello_star_inserts_text.output] Just as we can use a fixture with a test case to eliminate repeated setup and tear down, we can use a fixture with a test suite. All test cases in the test suite will derive from the test suite's fixture. If a test case in a test suite with a fixture specifies its own fixture, then the test case derives from the fixture specified on the test case and not on the test suite. If you want the test case to use both fixtures, then make your test case fixture derive from the test suite fixture. We can use a test suite fixture for =test_hello= to take care of the duplicated setup between test cases. Since our test cases are now within the scope of a suite, we don't need to give them a unique prefix anymore. Refactoring the tests to use a suite fixture and discarding the prefix gives us the following code: [import tutorials/running_selected_tests/test/test_hello.cpp] [running_selected_tests_test_cpp] Now __report_level__ outputs the following: [include tutorials/running_selected_tests/report_level_detailed.output] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/sut/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/tutorials/running_selected_tests/test/test_hello.cpp test_hello.cpp] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/user-compilation.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:compilation Compilation and Usage Variants] __test__ is available in several forms: * a single, minimal header * a header-only form * a static library * a shared library The minimal header can be useful in situations where you don't already have the library built and want to quickly explore a test with a minimal amount of fuss. Once you need to create multiple unit tests, you will quickly outgrow the minimal header. The header only form is useful when you don't want to be bothered with compiling the library. Once you have multiple compilation units with unit tests in each compilation unit, you will grow tired of the compilation cost involved with the header only form of the framework. The static library form is the easiest to integrate into your build system as it doesn't require any installation of runtime files in order to execute your tests. This runtime simplicity comes at the cost of increased link times and executable sizes. The dynamic library form requires the most effort for successful test execution, but provides faster link times than the static library, faster compile times than the header only form and provides all the features of the framework compared to the minimal header. [caution __test__ is not a thread-safe library. Care should be taken when automated tests create multiple threads and interact with data structures passed to __test__ macros or functions.] [section:minimal_header Minimal Header] A lightweight, minimal version of the testing framework can be obtained by including ==. This header provides only the following macros: [table [[Macro] [Meaning]] [[=BOOST_CHECK(=['expression]=)=] [If ['expression] is false, the test fails and test execution continues.]] [[=BOOST_REQUIRE(=['expression]=)=] [If ['expression] is false, the test fails and test execution terminates.]] [[=BOOST_ERROR(=['message]=)=] [Report ['message], fail the test and continue test execution.]] [[=BOOST_FAIL(=['message]=)=] [Report ['message], fail the test and terminate test execution.]] ] The header supplies an implementation of =main= that executes a single test case by calling a free function named =test_main= with the following signature: ``` int test_main(int argc, char *argv[]); ``` The arguments =argc= and =argv= are passed to =test_main= from the implementation of =main= supplied by the test framework. No command-line argument processing is performed by =main=. A summary report of errors recorded by the test case is printed out after executing the test case. If any exception is thrown by the test case, it is caught by =main= and treated as an error from the test case. ``` #include int test_main(int argc, char *argv[]) { // test case } ``` [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * An example of using the minimal test framework: * [@boost:/libs/test/doc/src/examples/compilation/minimal/test_hello.cpp test_hello.cpp]. [endsect] [section =main=] To use the implementation of =main= provided by __test__, exactly one source file must define __boost_test_main__ before including ==. If multiple source files define __boost_test_main__, then a multiply defined symbol error will occur during linking. If __boost_test_no_main__ is defined, then no implementation of =main= will be provided and the test executable must provide an initialization function. The exact initialization function that must be provided varies depending on how the library is compiled. The details are shown in the discussion of each compilation variation. When __test__ is compiled as a library, __boost_test_no_main__ must be defined when the library is compiled for it to work properly in those circumstances. [endsect] [section:header_only Header Only] The entire unit test framework can be incorporated into an executable by including the file ==. Because the entire implementation is incorporated into the source file including this header, only a single source file in the test executable can include this header. Additional source files must define __boost_test_no_lib__ before including == to prevent any automatic linking to a shared library. If additional source files attempt to include ==, a multiply defined symbol error will occur during linking. ``` // In exactly one source file: #include // test cases (optional) ``` ``` // In additional source files #define BOOST_TEST_NO_LIB #include // test cases ``` If __boost_test_no_main__ is defined, then an implementation of =main= must be provided that executes the test cases. This is most readily done by delegating to __unit_test_main__. ``` // In exactly one source file #define BOOST_TEST_NO_MAIN #include boost::unit_test::test_suite *init_function(int argc, char *argv[]) { // create test cases and suites and return a pointer to any enclosing // suite, or 0. return 0; } int main(int argc, char* argv[]) { return ::boost::unit_test::unit_test_main(&init_function, argc, argv); } ``` [heading Example Source Code] The [link test.tutorials tutorials] all use the header-only version of __test__. [endsect] [section Static Library] To build __test__ as a static library, first build the boost build tools, as described in the [@boost:/more/getting_started/index.html Getting Started] documentation. After you have bootstrapped the build tools, build the test library with by invoking =b2= with arguments similar to the following: ``b2 --with-test link=static`` This will place the resulting libraries in =stage/lib= at the top level of the boost tree. In a static library configuration, __test__ is compiled into a single static library named =boost_unit_test_framework= and the test executable is linked against that library. Exactly one compilation unit in the test executable should define __boost_test_main__, in order run the tests. ``` // In exactly one source file #define BOOST_TEST_MAIN #include // test cases (optional) ``` Additional source files simply include the main unit test header and define more test cases and/or suites. ``` // In additional source files #include // test cases ``` To compile the library with no implementation of =main=, add __boost_test_no_main__ to the =cxxflags= property for b2: ``b2 --with-test link=static define=BOOST_TEST_NO_MAIN`` When the library is compiled with __boost_test_no_main__ defined, one source file must provide a definition for =main=. The simplest is to delegate to __unit_test_main__ and provide an implementation of an initialization function that manually adds test cases and suites to the test tree. Any test cases or test suites added with __boost_auto_test_case__, __boost_fixture_test_case__, __boost_auto_test_suite__ or __boost_fixture_test_suite__ are automatically added. ``` // In exactly one source file #define BOOST_TEST_NO_MAIN #include boost::unit_test::test_suite *init_function(int argc, char *argv[]) { // create test cases and suites and return a pointer to any enclosing // suite, or 0. return 0; } int main(int argc, char *argv[]) { return boost::unit_test::unit_test_main(init_function, argc, argv); } ``` [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp]. * An example of using the standard implementation of =main=: * [@boost:/libs/test/doc/src/examples/compilation/static/main.cpp main.cpp] * [@boost:/libs/test/doc/src/examples/compilation/static/test_hello.cpp test_hello.cpp]. * An example of using a custom =main=: * [@boost:/libs/test/doc/src/examples/compilation/static_main/main.cpp main.cpp] * [@boost:/libs/test/doc/src/examples/compilation/static_main/test_hello.cpp test_hello.cpp]. [endsect] [section Shared Library] To build __test__ as a shared library, first build the boost build tools, as described in the [@boost:/more/getting_started/index.html Getting Started] documentation. After you have bootstrapped the build tools, build the test library with by invoking =b2= with arguments similar to the following: ``b2 --with-test link=shared`` This will place the resulting libraries in =stage/lib= at the top level of the boost tree. In a shared library configuration, __test__ is compiled into a single shared library named =boost_unit_test_framework= and the test executable is linked against that library to import symbols from the library. The __test__ shared library must be available to the runtime loader in order for the tests to execute. Every compilation unit that includes a header from __test__ must define __boost_test_dyn_link__ first so that declarations are properly annotated as imported symbols. When __boost_test_dyn_link__ is defined, __test__ also defines __boost_test_alternative_init_api__. Exactly one compilation unit in the test executable should define __boost_test_main__, in order run the tests. ``` // In exactly one compilation unit #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #include // test cases (optional) ``` Additional source files define __boost_test_dyn_link__, include the main unit test header and define more test cases and/or suites. ``` // In additional source files #define BOOST_TEST_DYN_LINK #include // test cases ``` To compile the library with no implementation of =main=, add __boost_test_no_main__ to the =cxxflags= property for b2: ``b2 --with-test link=shared define=BOOST_TEST_NO_MAIN`` When the library is compiled with __boost_test_no_main__ defined, one source file must provide a definition for =main=. The simplest is to delegate to __unit_test_main__ and provide an implementation of an initialization function that manually adds test cases and suites to the test tree. Any test cases or test suites added with __boost_auto_test_case__, __boost_fixture_test_case__, __boost_auto_test_suite__ or __boost_fixture_test_suite__ are automatically added. ``` // In exactly one source file #define BOOST_TEST_NO_MAIN #include bool init_function() { // create test cases and suites and return a boolean indicating // success (true) or failure (false). return true; } int main(int argc, char* argv[]) { return ::boost::unit_test::unit_test_main(&init_function, argc, argv); } ``` [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * An example of using the standard implementation of =main=: * [@boost:/libs/test/doc/src/examples/compilation/dynamic/main.cpp main.cpp] * [@boost:/libs/test/doc/src/examples/compilation/dynamic/test_hello.cpp test_hello.cpp]. * An example of using a custom =main=: * [@boost:/libs/test/doc/src/examples/compilation/dynamic_main/main.cpp main.cpp] * [@boost:/libs/test/doc/src/examples/compilation/dynamic_main/test_hello.cpp test_hello.cpp]. [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/src/user-guide.qbk ================================================ [/============================================================================== Copyright (C) 2013 Richard Thomson Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ===============================================================================/] [section:guide User's Guide] [include:test user-compilation.qbk] [section:test_case_design Test Case Design and Maintenance] [@http://xunitpatterns.com/Goals%20of%20Test%20Automation.html xUnit Patterns][footnote The term ['xUnit] is a generic term for unit testing frameworks, such as jUnit. The advice in ['xUnit Patterns] applies equally well to __test__.], by Gerard Meszaros, presents several high level objectives for automated tests and individual goals for achieving those objectives: * Objective: Tests should help us improve quality. * Goal: [link tests_as_specifications Tests as specifications] * Goal: [link bug_repellant Bug repellant] * Goal: [link defect_localization Defect localization] * Objective: Tests should help us understand the system under test. * Goal: [link tests_as_documentation Tests as documentation] * Objective: Tests should reduce, not increase, risk. * Goal: [link tests_as_safety_net Tests as safety net] * Goal: [link do_no_harm Do No Harm] * Objective: Tests should be easy to run. * Goal: [link fully_automated_test Fully Automated Test] * Goal: [link self_checking_test Self-Checking Test] * Goal: [link repeatable_test Repeatable Test] * Objective: Tests should be easy to write and maintain. * Goal: [link simple_tests Simple Tests] * Goal: [link expressive_tests Expressive Tests] * Goal: [link separation_of_concerns Separation of Concerns] * Objective: Tests should require minimal maintenance as the system evolves around them. * Goal: [link robust_test Robust Test] In this section, we will discuss how the facilities in __test__ can support these goals; see ['xUnit Patterns] for the description and rationale of these goals. [#tests_as_specifications][heading Goal: Tests as Specifications] Tests can serve as specifications for the system under test if we write the test for the system first, using test-driven development. We imagine the perfect system that does exactly what we need and write a test as if that system existed. In order to achieve a failing test, we write just enough of the implementation to make the test compile. A good way to ensure that the implementation causes a test failure is for called methods and functions to throw an exception indicating that the method or function called is not implemented: ``` #include void free_function() { throw std::runtime_error("free_function not implemented."); } ``` We get a failing test right away, while still satisfying just enough syntax to satisfy the compiler. [#bug_repellant][heading Goal: Bug Repellant] It is well known that the longer a bug remains undetected in a software, the more expensive it is to fix.[footnote [@https://en.wikipedia.org/wiki/Software_testing#Economics Software Testing: Economics]] If we are practicing test-driven development, then we find bugs in our implementation as soon as we code them. The time to find a bug in this manner can be as little as seconds and was demonstrated in the tutorial [link test.tutorials.hello_test "Hello, Test!"]. The easiest way to achieve this rapid feedback is to run the tests as part of the build. The details vary depending on your build system. In Visual Studio 2012, this is most readily achieved by setting a post-build build event as shown below. Because [^$(TargetPath)] may contain spaces, the variable is surrounded by double quotes to ensure that the entire path to the executable is found. The description is given generically using [^$(TargetName)] so that this build event can be copied to any test project's properties and be used without modification. Take care that you define the build event for all configurations and all platforms used by your build system so that the unit tests always run. [$../src/user-vs2012-build-event.png] If you are using a =Makefile= to compile your code, create a phony target that depends on your unit test executable and specify the command to execute your unit test and create the phony target if the test passes. This will ensure that the unit tests continue to run as long as they fail because the phony target will only be updated when the tests pass. If you are using Boost.Build and Jamfiles to compile your code, you can use the rules in the =testing= module to incorporate your unit tests into your build. The =unit-test= rule will build an executable and run it, failing the build when the executable returns a non-zero exit status. Other rules in the =testing= module may also be useful. [#defect_localization][heading Goal: Defect Localization] If we keep our test cases focused on only a single behavior in our system under test, then there is only a single cause for any particular unit test to fail. We saw this in [link test.tutorials.testing_with_exceptions "Testing With Exceptions"] when we added a new test case to =hello_world= for a bad stream. By choosing [@http://c2.com/cgi/wiki?IntentionRevealingNames intention revealing names] for our test cases, we can identify the source of the failure simply by reading the name of the failed test case. Since each test case excercises only one scenario for the system under test, we must make at least one test case for each possible scenario. We can use the [@http://en.wikipedia.org/wiki/Cyclomatic_complexity cyclomatic complexity] as a rough proxy for the number of tests cases needed for any particular method or function to ensure that we have sufficient [@http://en.wikipedia.org/wiki/Code_coverage coverage] of the system under test. [#tests_as_documentation][heading Goal: Tests as Documentation] When confronted with a new software component or a new code base, how do we understand its behavior? We can read the documentation, but ultimately the behavior is defined by the code executed. Comments and documentation can lag the actual implementation. Sometimes, the only answer to our questions about a software component come from the implementation. If the component is only available to us in binary form, we don't have the luxury of consulting the source code in order to answer our questions. Unit tests can serve as a form of executable documentation for software components. They tell us how the system responds to the scenarios orchestrated by the test cases. When faced with a confusing aspect of a software component, we can answer questions about the behavior of the component by writing a unit test that describes our hypothesis about the component's behavior. If the unit test passes, we have verified our hypothesis. If the unit test fails, our hypothesis was incorrect; either way, we have learned something about the component. We can use unit tests to document subtle and unexpected behaviors of components. Unit tests are also the perfect documentation for a bug report on a component maintained by others. [#tests_as_safety_net][heading Goal: Tests as Safety Net] When we start building a software system, we are able to keep all the details of the system in our mind because the system is small. As the size of the system increases, it becomes harder and harder to keep all the details of the system in mind as we make modifications. A comprehensive suite of unit tests over the system give us an automated regression test that gives us the confidence of knowing that our changes are not introducing any problems elsewhere in the code. [#do_no_harm][heading Goal: Do No Harm] Automated tests should only reduce risk, not introduce risk into the system. To achieve this, we want to keep all test code separated from production code. The easiest way to do this is to put the system under test into a library (static or shared) and link the test executable against the library. We saw this in the tutorial [link test.tutorials.hello_test "Hello, Test!"], when we separated the system under test into the =hello= library and the test code into =test_hello.cpp=. [#fully_automated_test][heading Goal: Fully Automated Test] __test__ supports fully automated tests by allowing us to supply the inputs to the system under test in each test case in order to drive the system into the scenario of interest. Test cases should never rely on user input, or they will not be fully automated tests that can run unattended. [#self_checking_test][heading Goal: Self-Checking Test] __test__ supports self-checking tests through its rich set of [link test.reference.assertion assertions]. Each test case supplies the inputs to the system under test and validates the behavior of the system using assertions. Self-checking tests report only bad news and good news results in no notifications. The default output from the test runner only reports failing tests and a summary of all tests executed. The test runner also returns a non-zero status code when a test fails, allowing easy failure of [@http://en.wikipedia.org/wiki/Continuous_integration continuous integration] builds. [#repeatable_test][heading Goal: Repeatable Test] We should get the same results from automated tests every time we run them, provided the implementation of the system under test has not changed between runs. In the context of unit testing, this implies that a test case must control all the collaborators that can influence the system. The most troublesome collaborators are among the following: * current date and time * device input * file system * system services (Windows registry, networking, etc.) * C style apis In the book "Working Effectively with Legacy Code", Michael Feathers described a number of techniques for decoupling the system under test from such troublesome collaborators that can cause unit tests to spuriously fail. All the techniques are variations on a theme: introduce a level of indirection to decouple the system under test from a collaborator. C++ offers [@http://en.wikipedia.org/wiki/Template_metaprogramming#Static_polymorphism static polymorphism] via templates as well as the usual dynamic polymorphism via interfaces to decouple a system under test from a collaborator. [#simple_tests][heading Goal: Simple Tests] We keep tests simple by exercising only one scenario for each test case. Simple test cases read linearly through the phases of setup, exercise and verify. Trying to exercise too much functionality in a single test case can introduce unnecessary complexity into the test. Duplication between test cases can make tests hard to read by distracting us from the steady rhythm of setup, exercise and verify of test cases. You may find it useful to apply the [@http://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) rule of three] when writing test cases to decide when to extract duplication into a fixture. [#expressive_tests][heading Goal: Expressive Tests] Sometimes low-level setup details get in the way of a test reading clearly. This could be the result of a complicated data structure needed in order to exercise the system down a particular code path. Similarly, the verification of a result produced by the system under test may involve a series of assertions that make the test hard to follow. __test__ provides fixtures as a way to localize these distracting details by extracting setup and assertion methods into the fixture. Over time we build up a series of methods in the fixture that allow us to express domain concepts succinctly and clearly in the tests, making them more expressive of the scenario in the domain. Fixtures can be combined through aggregation or inheritance in order to express combinations and hierarchies of domain concepts. [#separation_of_concerns][heading Goal: Separation of Concerns] We keep test code separated from production code with the packaging mechanisms provided by C++. Production code is supplied to the test executable as a library, either static or dynamic. The test code resides in separate source files from the production code. The production code consumed by the test code is compiled with the exact same preprocessor settings as the production code to ensure that tests do not influence the production code. We keep concerns separated in our tests by testing each concern in its own test case. Each test case exercises a single scenario and our tests exercise the responsibilities or classes individually. If we are practicing test-driven development, we keep the [@http://en.wikipedia.org/wiki/Single_responsibility_principle single responsibility principle] in mind as we are creating the system to satisfy the evolving tests. When our tests start involving more than one concern, it can be a sign that our system under test is covering more than one responsibility. [#robust_test][heading Goal: Robust Test] Test cases are robust when small changes to the system under test result in a small number of test cases failing. If a small change to the system results in many test cases failing, then our tests are not robust. If our tests cases do not sufficiently isolate the system under test from its collaborators, then a change to one part of the system can cause tests on seemingly unrelated parts of the system to fail. If we have repeated assertions in many test cases for the same system under test, then many test cases can fail if that single assertion fails. Each of these situations is a case of overlap between test cases; in the first case, the overlap is between the parts of the production code unrelated to the system under test that we exercise and in the second case, the overlap is between test cases on the system under test. [endsect] [section:acceptance_tests Acceptance Tests and Unit Tests] Unit testing helps us to find bugs "in the small"; little implementation details that we got wrong while we were building a function, a method or a class. When we test each class as an isolated unit, we can miss errors in the way two classes interact or in the way a whole ensemble of classes cooperate in an integrated system. An acceptance test is an automated test that exercises our system as an integrated whole and not as a collection of isolated units. In a unit test, we decouple ourselves from the execution environment in order to test a piece of code in isolation. In an acceptance test, we run the whole system and provide controlled inputs to the system. This may consist of prepared input data files, prepared input databases and so-on. Using these two forms of automated testing, we can use them as a vise to squeeze bugs between the two forms of automated tests. Unit tests push from below and acceptance tests push from above. While the facilities in __test__ can be used to create an automated acceptance test, the tools are fairly low-level for the kinds of high-level criteria that an acceptance test would use. Acceptance tests are usually defined by the [@http://en.wikipedia.org/wiki/Product_owner#Roles product owner] or customer and will describe acceptance criteria in the language closest to the problem domain and farthest away from the details of the implementation. A better approach for automated acceptance tests would be a tool such as [@http://www.fitnesse.org FitNesse] that is designed for automated acceptance testing. [endsect] [section:testing_file_io Testing File I/O] A common problem encountered in unit testing is interaction with the file system: scanning directories, creating files, opening files, reading files, writing files, creating symbolic links and so-on. Interacting directly with the file system when executing unit tests can lead to a failure of tests to be [link robust_test robust] or [link repeatable_test repeatable]. We also want our unit tests to be fast; an execution time of 100 milliseconds is considered a slow unit test. Interacting directly with the file system can make our unit tests take too long to execute. The simplest approach is to wrap file system operations in an interface and perform all operations through the interface. Consider the following example of a function that returns a vector of filenames ending in ".txt" in a given directory: [import system_under_test/scanner/scanner.hpp][text_files_decl] How can we unit test =text_files= without relying on the actual contents of the file system? We can decouple =text_files= from the file system by introducing an interface: [text_files_dependency_decl] We've used a forward declaration of =directory_scanner= where =text_files= is declared. The interface looks like this: [import system_under_test/scanner/directory_scanner.hpp][directory_scanner] The interface =directory_scanner= is used to isolate the free function =text_files= from directly interacting with the file system. In the unit tests, we use an implementation of =directory_scanner= that senses how =text_files= uses the interface and allows us to control the data made available to =text_files=. The tests can use a hand-crafted fake implementation or an implementation from a mock library. The fake might look something like this: [import examples/file_system.cpp][fake_directory_scanner] The tests for =text_files= use the =fake_directory_scanner= to specify the configuration of the file system for the different test cases: [test_scanner] In production code, we use an implementation of =directory_scanner= that interacts directly with the file system using Boost.FileSystem. [import system_under_test/scanner/filesystem_directory_scanner.hpp][filesystem_directory_scanner] We've wrapped just enough of Boost.FileSystem for our needs; Boost.FileSystem has a very large surface area and we don't need to put an interface around the entire thing, just enough to satisfy the needs of =text_files=. If we don't want production code to have to worry about supplying an instance of =filesystem_directory_scanner= to =text_files=, we can use overloading on =text_files= and use simple delegation to supply the dependency: [import system_under_test/scanner/scanner.cpp][text_files_impl] Seeing this, you might wonder if we need to unit test the overload we just created? Because we are using simple delegation here, there isn't sufficient complexity to warrant unit testing. However, we have no unit tests for =filesystem_directory_scanner=, which does have control structures. We will want some sort of automated tests around this code to verify that it functions properly. We can use [link test.guide.acceptance_tests acceptance tests] to verify the system as a whole, exercising all the components end-to-end and not just in isolation. [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/scanner/scanner.hpp scanner.hpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/scanner.cpp scanner.cpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/directory_scanner.hpp directory_scanner.hpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/filesystem_directory_scanner.hpp filesystem_directory_scanner.hpp] * Tests: * [@boost:/libs/test/doc/src/examples/file_system.cpp file_system.cpp] [endsect] [section Mocking Collaborators] In [link test.guide.testing_file_io testing file I/O], we showed an example of creating a class =fake_directory_scanner= that acted as a simple test double for an interface. Such simple fake objects are fine at first, but they're full of boring boiler plate code and after a while it becomes tedious to write them by hand. For collaborators defined by a pure virtual base class, also known as an interface, there are mock object frameworks that alleviate the need to write the repetitive boiler plate code. One such mock object framework that is designed to work with __test__ is the [@http://turtle.sourceforge.net Turtle mock object framework]. Here is an example of the file system tests written using turtle: [import examples/turtle_mock.cpp] [mock_directory_scanner] Defining the mock object is considerably simpler than writing a fake object by hand. Turtle uses variadic argument macros and template based type deduction to infer the type signature of the methods simply from the number of arguments each method takes. This alleviates us from having to repeat all of this information from the interface into the implementation of the test double. Now we can rewrite our tests to use a mock object configured for each test case: [test_scanner_with_mocks] The tests themselves are largely unchanged and what is different is the intention revealing methods we placed in the test fixture. Mock object frameworks generally provide a rich set of methods on the mock object for setting the expectations on the number of times a method is called, such as =once()=, the expected arguments to a method, such as =with()=, and the return value of a method, such as =returns()=. With a turtle mock, the expectations are verified when the mock object is destroyed. The mock is a member in our fixture and will be destroyed at the end of every test case. [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/scanner/scanner.hpp scanner.hpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/scanner.cpp scanner.cpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/directory_scanner.hpp directory_scanner.hpp] * [@boost:/libs/test/doc/src/system_under_test/scanner/filesystem_directory_scanner.hpp filesystem_directory_scanner.hpp] * Tests: * [@boost:/libs/test/doc/src/examples/turtle_mock.cpp turtle_mock.cpp] [endsect] [section Testing =main=] If there is considerable logic in an appliation's =main= function, this can be difficult to unit test. The [@http://en.wikipedia.org/wiki/One_definition_rule One Definition Rule] prevents us from having the application's =main= and the unit test executable's =main= in the same executable. Furthermore, even if we could perform some trick to resolve the multiply defined symbol[footnote We could abuse the C++ preprocessor or use object file symbol modification.], we would still need to figure out how to link the test executable with the application's =main= function to test the code. When it becomes difficult to test code where it is currently, such as in the body of =main=, the simplest thing to do is to move the code somewhere else that makes it easy to test. Here is one way to accomplish this: # rename =main= to =app_main=. # move =app_main= to a library. # create a simple delegating =main= that calls =app_main=. # write tests for =app_main= by linking against the library. The delegating =main= looks like this: ``` extern int app_main(int argc, char* argv[]); int main(int argc, char* argv[]) { return app_main(argc, argv); } ``` If you don't already have a library for =app_main=, then create one and add all the other application code to the library as well. The build logic for making the executable will consist of compiling a single source file containing your delegating implementation of =main= and linking against a library containing the rest of the application. This will give you a starting point for writing unit tests for anything in your application. [endsect] [section Testing Protected or Private Members] When testing a large class, you may find yourself wanting to test protected or private members of the class. The best approach is to test those members by testing the public members of the class. If using the public members of a class requires considerable setup in order to force execution down a particular path that exercises the protected or private member in question, then you may wish to refactor the code to enhance testability. The most expedient technique for protected members is to raise their visibility through derivation. Suppose we have a base class `B` with a protected member `p` that we wish to test: ``` class B { // ... other stuff in B protected: bool p(); }; ``` We can derive a class `D` in the test code from the class `B` in the production code that raises the visibility of `p`: ``` class D : public B { // ... other stuff needed to build a D from a B public: using B::p; }; ``` Now we can write a test for `D::p`. While this certainly seems expedient, it's annoying to write these derived classes simply for the purposes of hoisting members into public visibility. It also just feels dirty. We're taking implementation details that are supposed to be hidden from consumers of the class and we're exposing them. If we are not diligent and watchful, this class `D` in the test project that was only intended for testing may find itself showing up in the production code. Maybe the problem isn't one of visibility but that we simply aren't listening closely enough to the code in the first place. As Herb Sutter shows us in [@http://www.gotw.ca/gotw/076.htm Uses and Abuses of Access Rights], the "Liar", the "Pickpocket", the "Cheat" and the "Language Lawyer" can all find ways to subvert the access protections afforded to a class. When we are tempted to test non-public methods of a class, it's because we feel that there is sufficient complexity in these non-public methods to warrant testing them. What if that complexity is trying to tell us something? If our class is so complex, isn't it possible that it's violating the [@http://en.wikipedia.org/wiki/Single_responsibility_principle Single Responsibility Principle]? Maybe the class is trying to encompass several responsibilities and should be decomposed into two or more classes, each with a single responsibility. We could perform the [@http://www.refactoring.com/catalog/extractClass.html Extract Class] refactoring to create two classes with appropriate public interfaces and then write tests against those new public interfaces. Another choice is to refactor the original class using the [@http://en.wikipedia.org/wiki/Opaque_pointer "pimpl idiom"], elevate the visibility to public of all the methods on the implementation class and write tests against the implementation class. This has the same downsides as the derive-and-elevate approach and we're still ignoring the whispers of the code. When your code is hard to test, your code is telling you something. Listen to the code! [endsect] [section Manually Registering Test Cases and Suites] [heading Registering Test Cases] You may have an existing body of tests that you wish to register with __test__ manually. You can use __boost_test_case__ to register a function taking no arguments and returning =void= as a test case: [import examples/manual_registration.cpp][register_function] You can use a test case method on a fixture class by registering a function that creates an instance of the fixture and invokes the test method. This assures that a fresh fixture is created for each test case, ensuring that each test executes independently of other tests. [hello_fixture] [register_method_function_instance] You can register a method on a class as a test case by using Boost.Bind to bind the method to a static instance of the class. This can cause oen test case to influence the execution of another test case because they share the static fixture. [register_method_static_instance] A static instance of the class is used so that the instance exists at the time the test case is invoked. Test case invocation happens after registration, so using a local instance in the registration function is insufficient. [heading Registering Test Suites] A new test suite is created with the __boost_test_suite__ macro. The new suite must be added to the master test suite to execute its tests. Any number of test suites can be added in a hierarchy of suites and any test case can be added to any test suite. [register_test_suite] [heading Example Source Code] * System under test: * [@boost:/libs/test/doc/src/system_under_test/hello/hello.hpp hello.hpp] * [@boost:/libs/test/doc/src/system_under_test/hello/hello.cpp hello.cpp] * Tests: * [@boost:/libs/test/doc/src/examples/manual_registration.cpp manual_registration.cpp] [endsect] [endsect] ================================================ FILE: files/test_driven/Boost.Test Documentation Rewrite/libs/test/doc/todo.txt ================================================ - Document floating-point comparison algorithms - BOOST_REQUIRE_CLOSE - BOOST_REQUIRE_CLOSE_FRACTION - BOOST_REQUIRE_SMALL - --run_test comma and slash confusion ================================================ FILE: files/test_driven/ReadMe.txt ================================================ Here's how you can work through this workshop following along at your computer. Prerequisites: 1. Download and install CMake 2.8 2. Download and unpack boost 1.55 somewhere on your local machine. You do not need built libraries for this workshop. 3. Download and unpack Turtle 1.2.5 somewhere on your local machine. Turtle is a header-only library. Understanding the slides: Each slide has a folder icon in the upper right with a number on it identifying the snapshot that corresponds to the code on the slide. Many snapshots are associated with multiple slides as the explanation proceeds. Each slide has an icon in the lower-right corner that indicates if the code is currently failing (red X), passing (green check mark) or being refactored (green triangular cyclic arrow). The changes being made in each slide are shown in blue and error messages are shown in yellow. Bootstrapping your workspace: 1. Create a directory for your workspace on your local machine. 2. Start by copying the contents of the snapshot directory 0 to your workspace. Follow along with the slides and edit LocalPaths.txt at the appropriate time. This is the only file you should need to edit by hand. Snapshot 0 contains an initial version of this file with a path that is almost certainly wrong for your machine. 3. As directed in the sldies, run CMake to bootstrap your build. 4. CMake should then automatically regenerate your build every time CMakeLists.txt or LocalPaths.txt changes when you build the code. If not, you can re-run the CMake command to regenerate your build from the CMakeLists.txt and LocalPaths.txt files. 5. As you proceed through the workshop, copy the contents of the numbered snapshot to your workspace, overwriting all files. LocalPaths.txt, which contains paths specific to your local machine, is only present in snapshot 0 and will not be overwritten from other snapshots. Working the hangman game exercise problem: Use a CMake build recipe similar to the one used in the slides to get your build going ASAP -- just copy the workspace CMakeLists.txt and LocalPaths.txt to your exercise workspace and edit appropriately. Consult the Boost.Test documentation rewrite included with the presentation and the Turtle documentation included in it's distribution for a reference to assertion macros and more options for the mock object framework. ================================================ FILE: files/test_driven/snapshots/00/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/00/LocalPaths.txt ================================================ set(BOOST_INCLUDEDIR D:/Code/boost/boost_1_55_0) ================================================ FILE: files/test_driven/snapshots/00/factors/factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/00/factors/factors.h ================================================ ================================================ FILE: files/test_driven/snapshots/00/test/test_factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/01/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/01/factors/factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/01/factors/factors.h ================================================ ================================================ FILE: files/test_driven/snapshots/01/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include ================================================ FILE: files/test_driven/snapshots/02/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/02/factors/factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/02/factors/factors.h ================================================ ================================================ FILE: files/test_driven/snapshots/02/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" ================================================ FILE: files/test_driven/snapshots/03/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/03/factors/factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/03/factors/factors.h ================================================ ================================================ FILE: files/test_driven/snapshots/03/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/04/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/04/factors/factors.cpp ================================================ ================================================ FILE: files/test_driven/snapshots/04/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/04/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/05/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/05/factors/factors.cpp ================================================ #include "factors.h" #include extern std::vector prime_factors(int n) { throw std::runtime_error("not implemented"); } ================================================ FILE: files/test_driven/snapshots/05/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/05/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/06/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/06/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { return std::vector(); } ================================================ FILE: files/test_driven/snapshots/06/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/06/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/07/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/07/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { return std::vector(); } ================================================ FILE: files/test_driven/snapshots/07/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/07/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } BOOST_AUTO_TEST_CASE(two_yields_2) { vector expected; expected.push_back(2); vector actual = prime_factors(2); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/08/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/08/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/08/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/08/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; BOOST_AUTO_TEST_CASE(one_yields_empty) { vector expected; vector actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } BOOST_AUTO_TEST_CASE(two_yields_2) { vector expected; expected.push_back(2); vector actual = prime_factors(2); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/09/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/09/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/09/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/09/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; }; BOOST_AUTO_TEST_CASE(one_yields_empty) { fixture f; f.actual = prime_factors(1); BOOST_REQUIRE_EQUAL_COLLECTIONS( begin(f.expected), end(f.expected), begin(f.actual), end(f.actual)); } BOOST_AUTO_TEST_CASE(two_yields_2) { vector expected; expected.push_back(2); vector actual = prime_factors(2); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/10/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/10/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/10/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/10/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_AUTO_TEST_CASE(one_yields_empty) { fixture f; f.prime_factors(1); f.verify_expected_factors(); } BOOST_AUTO_TEST_CASE(two_yields_2) { vector expected; expected.push_back(2); vector actual = prime_factors(2); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/11/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/11/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/11/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/11/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_AUTO_TEST_CASE(two_yields_2) { vector expected; expected.push_back(2); vector actual = prime_factors(2); BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } ================================================ FILE: files/test_driven/snapshots/12/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/12/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/12/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/12/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/13/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/13/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(2); } return primes; } ================================================ FILE: files/test_driven/snapshots/13/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/13/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/14/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/14/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(n); } return primes; } ================================================ FILE: files/test_driven/snapshots/14/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/14/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/15/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/15/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { primes.push_back(n); } return primes; } ================================================ FILE: files/test_driven/snapshots/15/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/15/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/16/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/16/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { if (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/16/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/16/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/17/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/17/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { if (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/17/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/17/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/18/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/18/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { if (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/18/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/18/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/19/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/19/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { while (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/19/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/19/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } void verify_expected_factors() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); verify_expected_factors(); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); verify_expected_factors(); } ================================================ FILE: files/test_driven/snapshots/20/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/20/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { while (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/20/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/20/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } ================================================ FILE: files/test_driven/snapshots/21/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/21/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; if (n > 1) { while (n % 2 == 0) { primes.push_back(2); n /= 2; } if (n > 1) { primes.push_back(n); } } return primes; } ================================================ FILE: files/test_driven/snapshots/21/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/21/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/22/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/22/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { while (n % candidate == 0) { primes.push_back(candidate); n /= candidate; } ++candidate; } if (n > 1) { primes.push_back(n); } return primes; } ================================================ FILE: files/test_driven/snapshots/22/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/22/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/23/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/23/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { while (n % candidate == 0) { primes.push_back(candidate); n /= candidate; } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/23/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/23/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/24/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/24/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/24/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/24/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/25/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/25/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/25/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/25/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/25/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include "mediator.h" ================================================ FILE: files/test_driven/snapshots/26/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/26/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/26/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/26/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #endif ================================================ FILE: files/test_driven/snapshots/26/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/26/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include "mediator.h" ================================================ FILE: files/test_driven/snapshots/27/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/27/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/27/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/27/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #endif ================================================ FILE: files/test_driven/snapshots/27/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/27/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include "mediator.h" BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { // ?what_type? dialog; prime_factors_mediator mediator(dialog); // ?how? verify that ok button is initially disabled } ================================================ FILE: files/test_driven/snapshots/28/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/28/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/28/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/28/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { } }; #endif ================================================ FILE: files/test_driven/snapshots/28/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/28/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include "mediator.h" BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { prime_factors_dialog dialog; prime_factors_mediator mediator(dialog); BOOST_REQUIRE(!"verify that ok button is initially disabled"); } ================================================ FILE: files/test_driven/snapshots/29/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/29/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/29/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/29/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { } }; #endif ================================================ FILE: files/test_driven/snapshots/29/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/29/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include "mediator.h" BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { prime_factors_dialog dialog; prime_factors_mediator mediator(dialog); BOOST_REQUIRE(!"verify that ok button is initially disabled"); } ================================================ FILE: files/test_driven/snapshots/30/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) target_include_directories(test_factors PRIVATE factors ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/30/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/30/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/30/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { } }; #endif ================================================ FILE: files/test_driven/snapshots/30/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/30/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { prime_factors_dialog dialog; prime_factors_mediator mediator(dialog); BOOST_REQUIRE(!"verify that ok button is initially disabled"); } ================================================ FILE: files/test_driven/snapshots/31/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/31/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/31/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/31/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { } }; #endif ================================================ FILE: files/test_driven/snapshots/31/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/31/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { prime_factors_dialog dialog; prime_factors_mediator mediator(dialog); BOOST_REQUIRE(!"verify that ok button is initially disabled"); } ================================================ FILE: files/test_driven/snapshots/32/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/32/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/32/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/32/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { } }; #endif ================================================ FILE: files/test_driven/snapshots/32/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/32/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } ================================================ FILE: files/test_driven/snapshots/33/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/33/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/33/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/33/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { dialog.enable_ok_button(false); } }; #endif ================================================ FILE: files/test_driven/snapshots/33/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/33/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } ================================================ FILE: files/test_driven/snapshots/34/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/34/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/34/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/34/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) { dialog.enable_ok_button(false); } }; #endif ================================================ FILE: files/test_driven/snapshots/34/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/34/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } ================================================ FILE: files/test_driven/snapshots/35/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/35/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/35/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/35/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #include class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; virtual std::string value_text() const = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) : dialog_(dialog) { dialog.enable_ok_button(false); } void value_changed() { dialog_.enable_ok_button(true); } private: prime_factors_dialog& dialog_; }; #endif ================================================ FILE: files/test_driven/snapshots/35/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/35/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } ================================================ FILE: files/test_driven/snapshots/36/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/36/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/36/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/36/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #include class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; virtual std::string value_text() const = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) : dialog_(dialog) { dialog.enable_ok_button(false); } void value_changed() { dialog_.enable_ok_button(true); } private: prime_factors_dialog& dialog_; }; #endif ================================================ FILE: files/test_driven/snapshots/36/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/36/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(empty_text_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns(""); prime_factors_mediator mediator(dialog); mediator.value_changed(); } ================================================ FILE: files/test_driven/snapshots/37/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/37/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/37/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/37/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #include class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; virtual std::string value_text() const = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) : dialog_(dialog) { dialog.enable_ok_button(false); } void value_changed() { dialog_.enable_ok_button(dialog_.value_text().length() > 0); } private: prime_factors_dialog& dialog_; }; #endif ================================================ FILE: files/test_driven/snapshots/37/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/37/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(empty_text_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns(""); prime_factors_mediator mediator(dialog); mediator.value_changed(); } ================================================ FILE: files/test_driven/snapshots/38/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/38/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/38/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/38/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #include class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; virtual std::string value_text() const = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) : dialog_(dialog) { dialog.enable_ok_button(false); } void value_changed() { dialog_.enable_ok_button(dialog_.value_text().length() > 0); } private: prime_factors_dialog& dialog_; }; #endif ================================================ FILE: files/test_driven/snapshots/38/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/38/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(empty_text_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns(""); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(not_a_number_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns("junk"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } ================================================ FILE: files/test_driven/snapshots/39/CMakeLists.txt ================================================ cmake_minimum_required(VERSION 2.8) project(prime_factors CXX) add_library(factors STATIC factors/factors.cpp factors/factors.h factors/mediator.h) include(LocalPaths.txt) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) set(Boost_USE_STATIC_RUNTIME OFF) find_package(Boost 1.55) add_executable(test_factors test/test_factors.cpp test/test_mediator.cpp) add_dependencies(test_factors factors) set(TURTLE_INCLUDE D:/Code/turtle) target_include_directories(test_factors PRIVATE factors ${TURTLE_INCLUDE} ${Boost_INCLUDE_DIRS}) target_link_libraries(test_factors factors) add_custom_command(TARGET test_factors POST_BUILD COMMAND test_factors) ================================================ FILE: files/test_driven/snapshots/39/factors/factors.cpp ================================================ #include "factors.h" extern std::vector prime_factors(int n) { std::vector primes; int candidate = 2; while (n > 1) { for (; n % candidate == 0; n /= candidate) { primes.push_back(candidate); } ++candidate; } return primes; } ================================================ FILE: files/test_driven/snapshots/39/factors/factors.h ================================================ #if !defined(FACTORS_H) #define FACTORS_H #include extern std::vector prime_factors(int n); #endif ================================================ FILE: files/test_driven/snapshots/39/factors/mediator.h ================================================ #if !defined(MEDIATOR_H) #define MEDIATOR_H #include #include class prime_factors_dialog { public: virtual ~prime_factors_dialog() { } virtual void enable_ok_button(bool enabled) = 0; virtual std::string value_text() const = 0; }; class prime_factors_mediator { public: prime_factors_mediator(prime_factors_dialog& dialog) : dialog_(dialog) { dialog.enable_ok_button(false); } void value_changed() { std::istringstream stream(dialog_.value_text()); int n; stream >> n; dialog_.enable_ok_button(!stream.fail() && dialog_.value_text().length() > 0); } private: prime_factors_dialog& dialog_; }; #endif ================================================ FILE: files/test_driven/snapshots/39/test/test_factors.cpp ================================================ #define BOOST_TEST_MAIN #include #include "factors.h" using namespace std; struct fixture { vector expected; vector actual; void prime_factors(int n) { actual = ::prime_factors(n); } ~fixture() { BOOST_REQUIRE_EQUAL_COLLECTIONS( expected.begin(), expected.end(), actual.begin(), actual.end()); } }; BOOST_FIXTURE_TEST_CASE(one_yields_empty, fixture) { prime_factors(1); } BOOST_FIXTURE_TEST_CASE(two_yields_2, fixture) { expected.push_back(2); prime_factors(2); } BOOST_FIXTURE_TEST_CASE(three_yields_3, fixture) { expected.push_back(3); prime_factors(3); } BOOST_FIXTURE_TEST_CASE(four_yields_2_2, fixture) { expected.push_back(2); expected.push_back(2); prime_factors(4); } BOOST_FIXTURE_TEST_CASE(six_yields_2_3, fixture) { expected.push_back(2); expected.push_back(3); prime_factors(6); } BOOST_FIXTURE_TEST_CASE(eight_yields_2_2_2, fixture) { expected.push_back(2); expected.push_back(2); expected.push_back(2); prime_factors(8); } BOOST_FIXTURE_TEST_CASE(nine_yields_3_3, fixture) { expected.push_back(3); expected.push_back(3); prime_factors(9); } ================================================ FILE: files/test_driven/snapshots/39/test/test_mediator.cpp ================================================ #define BOOST_TEST_NO_LIB #include #include #include "mediator.h" MOCK_BASE_CLASS(mock_dialog, prime_factors_dialog) { MOCK_METHOD(enable_ok_button, 1); MOCK_METHOD(value_text, 0); }; BOOST_AUTO_TEST_CASE(ok_button_initially_disabled) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); prime_factors_mediator mediator(dialog); } BOOST_AUTO_TEST_CASE(ok_button_enabled_with_valid_integer) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).once().with(false); MOCK_EXPECT(dialog.enable_ok_button).once().with(true); MOCK_EXPECT(dialog.value_text).returns("123"); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(empty_text_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns(""); prime_factors_mediator mediator(dialog); mediator.value_changed(); } BOOST_AUTO_TEST_CASE(not_a_number_disables_button) { mock_dialog dialog; MOCK_EXPECT(dialog.enable_ok_button).at_least(1).with(false); MOCK_EXPECT(dialog.value_text).returns("junk"); prime_factors_mediator mediator(dialog); mediator.value_changed(); }