cpp-testing / GUnit

GUnit - Google.Test/Google.Mock/Cucumber on steroids
263 stars 53 forks source link

Guideline on how to integrate this library? #15

Open paulreimer opened 6 years ago

paulreimer commented 6 years ago

I can find lots of code examples on how to use it (in example/) but there are no build system files (CMakeLists.txt) in those directories. Reading the top-level CMakeLists.txt, it sets up the test( file SCENARIO=) command, which seems like a good approach for the tests within this library:

/GUnit/
    example/*.cpp
    test/*.cpp

But more likely a typical app structure will be:

/app/
    test/*.cpp
    test/libs/GUnit/

(at least having the GUnit repo as a submodule somewhere in the app, and our test cpp files out-of-tree) So how should we source those test() commands from the GUnit CMakeLists.txt, or should we be copy/pasting them into our own files? Basically, what is your recommended way to use this in an existing project (and/or a new project, if that is different).

Also... my CI is running on Raspberry Pi's and previously using Catch2 + Trompeloeil (which are header-only). So you can imagine the process is pretty simple, barely even needing a Makefile. Now that I have to compile 80+ files (mostly gherkin-c, if I want support for Gherkin), it really slows down the overall test process. How much of the deps of this library can be compiled into a library? I know Google.Test likes to be compiled alongside the actual test sources so it has the correct compiler flags, does this still apply to the latest Google.Test, to GUnit, or the other libs?

If there was some way to replace all the GUnit submodules with a single library (at least to have that choice), that would be great. I'm not sure how the gherkin<->gtest integration works, but maybe some parts could be moved to an executable/runner?

kris-jusiak commented 6 years ago

You are right @paulreimer, there should be an easy integration with cmake. Thanks for the tips. I'll work on that. I'll keep this issue open as long as it won't be done.

paulreimer commented 6 years ago

Personally, I created a BUILD.gn file to use gn: https://github.com/paulreimer/GUnit/blob/add-gn-support/BUILD.gn

I'm probably doing lots of things incorrectly (this is the simplest thing that worked). Using submodules makes it difficult to add BUILD.gn files to all the deps, so I had to make it top-level only. If the deps were vendor'ed into your repo (not specifically asking for that, it might help in some ways but hurt in others), it would be easier to add them. (For now it is just a single BUILD.gn file referring multiple directories deep)

I use it something like this (with GUnit checked out as a submodule in the same directory):

test/BUILD.gn:

executable("test_runner") {
  testonly = true

  defines = [
  ]

  include_dirs = [
    "../cpp17_headers/include",
    "../delegate",
    ".",
  ]

  cflags_cc = [
    "-std=c++14",
  ]

  sources = [
    "test_runner.cpp",
    "foo_test.cpp",
    "bar_test.cpp",
    "../src/foo.cpp",
    "../src/bar.cpp",
  ]

  deps = [
    "//GUnit:GUnit",
  ]
}

(And I followed the guide here to make sure the app was setup correctly to invoke my toolchain, build paths, etc) https://chromium.googlesource.com/chromium/src/tools/gn/+/HEAD/docs/standalone.md

paulreimer commented 6 years ago

However if there was a library or executable approach that I could install (OS level, or just a one-time manual install), I would prefer that, probably, since it wouldn't need to compile as much during the test run.

MauganRa commented 6 years ago

Googles recommended way to include Google Test: https://github.com/google/googletest/blob/master/googletest/README.md

Applied to GUnit:

New file CMakeLists.txt.in:

cmake_minimum_required(VERSION 2.8.2)

project(gunit-download NONE)

include(ExternalProject)

ExternalProject_Add(GUnit
        GIT_REPOSITORY    https://github.com/cpp-testing/GUnit.git
        GIT_TAG           master
        SOURCE_DIR        "${CMAKE_BINARY_DIR}/gunit-src"
        BINARY_DIR        "${CMAKE_BINARY_DIR}/gunit-build"
        CONFIGURE_COMMAND ""
        BUILD_COMMAND     ""
        INSTALL_COMMAND   ""
        TEST_COMMAND      "")

Existing build's CMakeLists.txt:

configure_file(CMakeLists.txt.in ${CMAKE_BINARY_DIR}/GUnit-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/GUnit-download )
if(result)
  message(FATAL_ERROR "CMake step for gunit failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/GUnit-download )
if(result)
  message(FATAL_ERROR "Build step for gunit failed: ${result}")
endif()

# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/gunit-src
                 ${CMAKE_BINARY_DIR}/gunit-build
                 EXCLUDE_FROM_ALL)

If you want to use gherkin, you can check if the library exists and if it is missing force a compilation during the cmake execution:

execute_process(COMMAND make lib-static   
     RESULT_VARIABLE result
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/gunit-src/libs/gherkin-cpp )
  if(result)
     message(FATAL_ERROR "Failed to compile libgherkin-cpp.a: ${result}")
  endif()
mr13tech commented 5 years ago

Thank you @MauganRa ! The solution works perfectly. Only thing I wish to add is CMake include/link statements:

add_executable(your_app_name main.cpp )

target_include_directories(your_app_name PUBLIC ${GUnit_SOURCE_DIR}/include)
target_include_directories(your_app_name PUBLIC ${gtest_SOURCE_DIR}/include)
target_include_directories(your_app_name PUBLIC ${gmock_SOURCE_DIR}/include)

target_link_libraries(your_app_name gtest)
target_link_libraries(your_app_name gtest_main)
target_link_libraries(your_app_name gmock)