diff --git a/CMakeLists.txt b/CMakeLists.txt index 97d05b44..d191757a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,9 @@ include(GNUInstallDirs) # Collect and display summary of options/dependencies include(FeatureSummary) +# Unit test management +include(CTest) + ################ OPTIONS ################## # Optional build settings for libopenshot option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON) @@ -76,7 +79,6 @@ option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF) option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF) -option(ENABLE_TESTS "Build unit tests (requires Catch2)" ON) option(ENABLE_PARALLEL_CTEST "Run CTest using multiple processors" ON) option(ENABLE_COVERAGE "Scan test coverage using gcov and report" OFF) @@ -88,11 +90,11 @@ option(ENABLE_OPENCV "Build with OpenCV algorithms (requires Boost, Protobuf 3)" # Legacy commandline override if (DISABLE_TESTS) - set(ENABLE_TESTS OFF) + set(BUILD_TESTING OFF) endif() -if(DEFINED ENABLE_TESTS) - set(ENABLE_TESTS ${ENABLE_TESTS} CACHE BOOL "Build unit tests (requires Catch2)" FORCE) +if(ENABLE_TESTS) + set(BUILD_TESTING ${ENABLE_TESTS}) endif() #### Work around a GCC < 9 bug with handling of _Pragma() in macros @@ -173,51 +175,68 @@ if (ENABLE_DOCS) endif() ############# PROCESS tests/ DIRECTORY ############## -set(CAN_BUILD_TESTS ${ENABLE_TESTS}) find_package(Catch2 QUIET) if(NOT Catch2_FOUND) - set(CAN_BUILD_TESTS FALSE) + set(BUILD_TESTING FALSE) endif() -if(CAN_BUILD_TESTS) - enable_testing() +if(BUILD_TESTING) + include(Catch) if(ENABLE_PARALLEL_CTEST) # Figure out the amount of parallelism for CTest include(ProcessorCount) ProcessorCount(CPU_COUNT) - if(NOT CPU_COUNT EQUAL 0) - message(STATUS "Setting up unit tests to use ${CPU_COUNT} processors") + if(CPU_COUNT GREATER 1) + add_feature_info("Parallel tests" TRUE "Unit tests can use ${CPU_COUNT} processors") set(CTEST_OPTIONS "-j${CPU_COUNT}") endif() endif() - include(CTest) - include(Catch) add_subdirectory(tests) endif() -add_feature_info("Unit tests" CAN_BUILD_TESTS "Compile unit tests for library functions") +add_feature_info("Unit tests" ${BUILD_TESTING} "Compile unit tests for library functions") ############## COVERAGE REPORTING ################# if (ENABLE_COVERAGE AND DEFINED UNIT_TEST_TARGETS) + set(COVERAGE_EXCLUDES + "bindings/*" + "examples/*" + "${CMAKE_CURRENT_BINARY_DIR}/bindings/*" + "${CMAKE_CURRENT_BINARY_DIR}/src/*_autogen/*" + ) setup_target_for_coverage_lcov( NAME coverage LCOV_ARGS "--no-external" EXECUTABLE ctest EXECUTABLE_ARGS ${CTEST_OPTIONS} DEPENDENCIES openshot ${UNIT_TEST_TARGETS} - EXCLUDE - "bindings/*" - "examples/*" - "${CMAKE_CURRENT_BINARY_DIR}/bindings/*" - "${CMAKE_CURRENT_BINARY_DIR}/src/*_autogen/*" + EXCLUDE ${COVERAGE_EXCLUDES} ) + foreach(_t IN LISTS UNIT_TEST_NAMES) + setup_target_for_coverage_lcov( + NAME "${_t}_coverage" + LCOV_ARGS "--no-external" + EXECUTABLE ctest + EXECUTABLE_ARGS ${CTEST_OPTIONS} -L "^${_t}$" + DEPENDENCIES openshot openshot-${_t}-test + EXCLUDE ${COVERAGE_EXCLUDES} + ) + endforeach() endif() -if(CAN_BUILD_TESTS AND NOT TARGET coverage) +if(DEFINED UNIT_TEST_TARGETS AND NOT TARGET coverage) add_custom_target(coverage COMMAND ctest ${CTEST_OPTIONS} DEPENDS openshot ${UNIT_TEST_TARGETS} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running unit tests (coverage disabled)" ) + foreach(_t IN LISTS UNIT_TEST_NAMES) + add_custom_target("${_t}_coverage" + COMMAND ctest ${CTEST_OPTIONS} -L "^${_t}$" + DEPENDS openshot openshot-${_t}-test + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Running unit tests for ${_t} class (coverage disabled)" + ) + endforeach() endif() if(TARGET test AND NOT TARGET os_test) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d39c416e..6c5c6d51 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,6 +48,8 @@ set(OPENSHOT_TESTS Color Coordinate DummyReader + ReaderBase + ImageWriter FFmpegReader FFmpegWriter Fraction @@ -56,20 +58,14 @@ set(OPENSHOT_TESTS KeyFrame Point QtImageReader - ReaderBase Settings Timeline ) -# ImageMagick related test files -if(DEFINED CACHE{HAVE_IMAGEMAGICK}) - list(APPEND OPENSHOT_TESTS - ImageWriter - ) -endif() - -# OPENCV RELATED TEST FILES -if(DEFINED CACHE{HAVE_OPENCV}) +### +### OPENCV RELATED TEST FILES +### +if(ENABLE_OPENCV) list(APPEND OPENSHOT_TESTS CVTracker CVStabilizer @@ -80,13 +76,13 @@ endif() ### ### Catch2 unit tests ### -if (NOT CAN_BUILD_TESTS) - return() -endif() - include(CTest) include(Catch) +if(NOT BUILD_TESTING) + return() +endif() + # Create object library for test executable main(), # to avoid recompiling for every test add_library(catch-main OBJECT catch_main.cpp) @@ -96,13 +92,17 @@ foreach(tname ${OPENSHOT_TESTS}) target_compile_definitions(openshot-${tname}-test PRIVATE TEST_MEDIA_PATH="${TEST_MEDIA_PATH}" ) - target_link_libraries(openshot-${tname}-test Catch2::Catch2 openshot) - # Automatically configure CTest targets from Catch2 test cases - catch_discover_tests( + target_link_libraries(openshot-${tname}-test Catch2::Catch2 openshot) + # Automatically configure CTest targets from Catch2 test cases + catch_discover_tests( openshot-${tname}-test TEST_PREFIX ${tname}: + PROPERTIES + LABELS ${tname} ) list(APPEND CATCH2_TEST_TARGETS openshot-${tname}-test) + list(APPEND CATCH2_TEST_NAMES ${tname}) endforeach() # Export target list for coverage use set(UNIT_TEST_TARGETS ${CATCH2_TEST_TARGETS} PARENT_SCOPE) +set(UNIT_TEST_NAMES ${CATCH2_TEST_NAMES} PARENT_SCOPE) diff --git a/tests/KeyFrame.cpp b/tests/KeyFrame.cpp index b919e8a5..feb4ccb7 100644 --- a/tests/KeyFrame.cpp +++ b/tests/KeyFrame.cpp @@ -38,7 +38,7 @@ using namespace openshot; -TEST_CASE( "GetPoint_With_No_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "GetPoint (no Points)", "[libopenshot][keyframe]" ) { // Create an empty keyframe Keyframe k1; @@ -46,7 +46,7 @@ TEST_CASE( "GetPoint_With_No_Points", "[libopenshot][keyframe]" ) CHECK_THROWS_AS(k1.GetPoint(0), OutOfBoundsPoint); } -TEST_CASE( "GetPoint_With_1_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "GetPoint (1 Point)", "[libopenshot][keyframe]" ) { // Create an empty keyframe Keyframe k1; @@ -60,7 +60,7 @@ TEST_CASE( "GetPoint_With_1_Points", "[libopenshot][keyframe]" ) } -TEST_CASE( "AddPoint_With_1_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "AddPoint (1 Point)", "[libopenshot][keyframe]" ) { // Create an empty keyframe Keyframe k1; @@ -71,7 +71,7 @@ TEST_CASE( "AddPoint_With_1_Point", "[libopenshot][keyframe]" ) CHECK_THROWS_AS(k1.GetPoint(1), OutOfBoundsPoint); } -TEST_CASE( "AddPoint_With_2_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "AddPoint (2 Points)", "[libopenshot][keyframe]" ) { // Create an empty keyframe Keyframe k1; @@ -84,7 +84,7 @@ TEST_CASE( "AddPoint_With_2_Points", "[libopenshot][keyframe]" ) CHECK_THROWS_AS(k1.GetPoint(2), OutOfBoundsPoint); } -TEST_CASE( "GetValue_For_Bezier_Curve_2_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "GetValue (Bezier curve, 2 Points)", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -103,7 +103,7 @@ TEST_CASE( "GetValue_For_Bezier_Curve_2_Points", "[libopenshot][keyframe]" ) CHECK(kf.GetLength() == 51); } -TEST_CASE( "GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle", "[libopenshot][keyframe]" ) +TEST_CASE( "GetValue (Bezier, 5 Points, 40% handle)", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -126,7 +126,7 @@ TEST_CASE( "GetValue_For_Bezier_Curve_5_Points_40_Percent_Handle", "[libopenshot CHECK(kf.GetLength() == 201); } -TEST_CASE( "GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle", "[libopenshot][keyframe]" ) +TEST_CASE( "GetValue (Bezier, 5 Points, 25% Handle)", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -149,7 +149,7 @@ TEST_CASE( "GetValue_For_Bezier_Curve_5_Points_25_Percent_Handle", "[libopenshot CHECK(kf.GetLength() == 201); } -TEST_CASE( "GetValue_For_Linear_Curve_3_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "GetValue (Linear, 3 Points)", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -169,7 +169,7 @@ TEST_CASE( "GetValue_For_Linear_Curve_3_Points", "[libopenshot][keyframe]" ) CHECK(kf.GetLength() == 51); } -TEST_CASE( "GetValue_For_Constant_Curve_3_Points", "[libopenshot][keyframe]" ) +TEST_CASE( "GetValue (Constant, 3 Points)", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -190,7 +190,7 @@ TEST_CASE( "GetValue_For_Constant_Curve_3_Points", "[libopenshot][keyframe]" ) CHECK(kf.GetLength() == 51); } -TEST_CASE( "Check_Direction_and_Repeat_Fractions", "[libopenshot][keyframe]" ) +TEST_CASE( "GetDelta and GetRepeatFraction", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -225,7 +225,7 @@ TEST_CASE( "Check_Direction_and_Repeat_Fractions", "[libopenshot][keyframe]" ) } -TEST_CASE( "Get_Closest_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "GetClosestPoint", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -253,7 +253,7 @@ TEST_CASE( "Get_Closest_Point", "[libopenshot][keyframe]" ) } -TEST_CASE( "Get_Previous_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "GetPreviousPoint", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -272,7 +272,7 @@ TEST_CASE( "Get_Previous_Point", "[libopenshot][keyframe]" ) } -TEST_CASE( "Get_Max_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "GetMaxPoint", "[libopenshot][keyframe]" ) { // Create a keyframe curve Keyframe kf; @@ -297,7 +297,7 @@ TEST_CASE( "Get_Max_Point", "[libopenshot][keyframe]" ) CHECK(kf.GetMaxPoint().co.Y == 2.0); } -TEST_CASE( "Scale_Keyframe", "[libopenshot][keyframe]" ) +TEST_CASE( "Keyframe scaling", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -339,7 +339,7 @@ TEST_CASE( "Scale_Keyframe", "[libopenshot][keyframe]" ) } -TEST_CASE( "Flip_Keyframe", "[libopenshot][keyframe]" ) +TEST_CASE( "flip Keyframe", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -373,7 +373,7 @@ TEST_CASE( "Flip_Keyframe", "[libopenshot][keyframe]" ) CHECK(kf.GetValue(100) == Approx(10.0f).margin(0.01)); } -TEST_CASE( "Remove_Duplicate_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "remove duplicate Point", "[libopenshot][keyframe]" ) { // Create a keyframe curve with 2 points Keyframe kf; @@ -386,7 +386,7 @@ TEST_CASE( "Remove_Duplicate_Point", "[libopenshot][keyframe]" ) CHECK(kf.GetPoint(0).co.Y == Approx(2.0).margin(0.01)); } -TEST_CASE( "Large_Number_Values", "[libopenshot][keyframe]" ) +TEST_CASE( "large number values", "[libopenshot][keyframe]" ) { // Large value int64_t const large_value = 30 * 60 * 90; @@ -402,7 +402,7 @@ TEST_CASE( "Large_Number_Values", "[libopenshot][keyframe]" ) CHECK(kf.GetPoint(1).co.Y == Approx(100.0).margin(0.01)); } -TEST_CASE( "Remove_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "remove Point", "[libopenshot][keyframe]" ) { Keyframe kf; kf.AddPoint(openshot::Point(Coordinate(1, 1), CONSTANT)); @@ -415,7 +415,7 @@ TEST_CASE( "Remove_Point", "[libopenshot][keyframe]" ) CHECK_THROWS_AS(kf.RemovePoint(100), OutOfBoundsPoint); } -TEST_CASE( "Constant_Interpolation_First_Segment", "[libopenshot][keyframe]" ) +TEST_CASE( "Constant interp, first segment", "[libopenshot][keyframe]" ) { Keyframe kf; kf.AddPoint(Point(Coordinate(1, 1), CONSTANT)); @@ -428,7 +428,7 @@ TEST_CASE( "Constant_Interpolation_First_Segment", "[libopenshot][keyframe]" ) CHECK(kf.GetInt(4) == 100); } -TEST_CASE( "isIncreasing", "[libopenshot][keyframe]" ) +TEST_CASE( "IsIncreasing", "[libopenshot][keyframe]" ) { // Which cases need to be tested to keep same behaviour as // previously? @@ -477,7 +477,7 @@ TEST_CASE( "GetLength", "[libopenshot][keyframe]" ) CHECK(g.GetLength() == 201); } -TEST_CASE( "Use_Interpolation_of_Segment_End_Point", "[libopenshot][keyframe]" ) +TEST_CASE( "use segment end point interpolation", "[libopenshot][keyframe]" ) { Keyframe f; f.AddPoint(1,0, CONSTANT); @@ -485,7 +485,7 @@ TEST_CASE( "Use_Interpolation_of_Segment_End_Point", "[libopenshot][keyframe]" ) CHECK(f.GetValue(50) == Approx(75.9).margin(0.1)); } -TEST_CASE( "Handle_Large_Segment", "[libopenshot][keyframe]" ) +TEST_CASE( "handle large segment", "[libopenshot][keyframe]" ) { Keyframe kf; kf.AddPoint(1, 0, CONSTANT); @@ -498,7 +498,7 @@ TEST_CASE( "Handle_Large_Segment", "[libopenshot][keyframe]" ) CHECK((double)fr.num / fr.den == Approx(0.5).margin(0.01)); } -TEST_CASE( "Point_Vector_Constructor", "[libopenshot][keyframe]" ) +TEST_CASE( "std::vector constructor", "[libopenshot][keyframe]" ) { std::vector points{Point(1, 10), Point(5, 20), Point(10, 30)}; Keyframe k1(points); diff --git a/tests/Point.cpp b/tests/Point.cpp index 45f493e0..ec208698 100644 --- a/tests/Point.cpp +++ b/tests/Point.cpp @@ -36,7 +36,7 @@ #include "Coordinate.h" #include "Json.h" -TEST_CASE( "Default_Constructor", "[libopenshot][point]" ) +TEST_CASE( "default constructor", "[libopenshot][point]" ) { openshot::Point p; @@ -50,7 +50,7 @@ TEST_CASE( "Default_Constructor", "[libopenshot][point]" ) CHECK(p.interpolation == openshot::InterpolationType::BEZIER); CHECK(p.handle_type == openshot::HandleType::AUTO); } -TEST_CASE( "XY_Constructor", "[libopenshot][point]" ) +TEST_CASE( "XY constructor", "[libopenshot][point]" ) { // Create a point with X and Y values openshot::Point p1(2,9); @@ -60,7 +60,7 @@ TEST_CASE( "XY_Constructor", "[libopenshot][point]" ) CHECK(p1.interpolation == openshot::InterpolationType::BEZIER); } -TEST_CASE( "Pair_Constructor", "[libopenshot][point]" ) +TEST_CASE( "std::pair constructor", "[libopenshot][point]" ) { // Create a point from a std::pair std::pair coordinates(22, 5); @@ -70,7 +70,7 @@ TEST_CASE( "Pair_Constructor", "[libopenshot][point]" ) CHECK(p1.co.Y == Approx(5.0f).margin(0.00001)); } -TEST_CASE( "Constructor_With_Coordinate", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate", "[libopenshot][point]" ) { // Create a point with a coordinate openshot::Coordinate c1(3,7); @@ -81,7 +81,7 @@ TEST_CASE( "Constructor_With_Coordinate", "[libopenshot][point]" ) CHECK(p1.interpolation == openshot::InterpolationType::BEZIER); } -TEST_CASE( "Constructor_With_Coordinate_And_LINEAR_Interpolation", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate, LINEAR", "[libopenshot][point]" ) { // Create a point with a coordinate and interpolation openshot::Coordinate c1(3,9); @@ -93,7 +93,7 @@ TEST_CASE( "Constructor_With_Coordinate_And_LINEAR_Interpolation", "[libopenshot CHECK(p1.interpolation == openshot::InterpolationType::LINEAR); } -TEST_CASE( "Constructor_With_Coordinate_And_BEZIER_Interpolation", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate, BEZIER", "[libopenshot][point]" ) { // Create a point with a coordinate and interpolation openshot::Coordinate c1(3,9); @@ -105,7 +105,7 @@ TEST_CASE( "Constructor_With_Coordinate_And_BEZIER_Interpolation", "[libopenshot CHECK(p1.interpolation == openshot::InterpolationType::BEZIER); } -TEST_CASE( "Constructor_With_Coordinate_And_CONSTANT_Interpolation", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate, CONSTANT", "[libopenshot][point]" ) { // Create a point with a coordinate and interpolation openshot::Coordinate c1(2,8); @@ -117,7 +117,7 @@ TEST_CASE( "Constructor_With_Coordinate_And_CONSTANT_Interpolation", "[libopensh CHECK(p1.interpolation == openshot::InterpolationType::CONSTANT); } -TEST_CASE( "Constructor_With_Coordinate_And_BEZIER_And_AUTO_Handle", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate, BEZIER+AUTO", "[libopenshot][point]" ) { // Create a point with a coordinate and interpolation openshot::Coordinate c1(3,9); @@ -131,7 +131,7 @@ TEST_CASE( "Constructor_With_Coordinate_And_BEZIER_And_AUTO_Handle", "[libopensh CHECK(p1.handle_type == openshot::HandleType::AUTO); } -TEST_CASE( "Constructor_With_Coordinate_And_BEZIER_And_MANUAL_Handle", "[libopenshot][point]" ) +TEST_CASE( "constructor from Coordinate, BEZIER+MANUAL", "[libopenshot][point]" ) { // Create a point with a coordinate and interpolation openshot::Coordinate c1(3,9);