For CI, it's best to focus on unit tests and integration tests. They work on the lowest possible level, which means they're usually quick to execute and have the smallest requirements. Ideally, all unit tests should be self-contained (no external dependencies like a working database) and able to run in parallel. This way, when the problem appears on the level where unit tests are able to catch it, the offending code would be flagged in a matter of seconds.
There are some people who say that unit tests only make sense in interpreted languages or languages with dynamic typing. The argument goes that C++ already has testing built-in by means of the type system and the compiler checking for erroneous code. While it's true that type checking can catch some bugs that would require separate tests in dynamically typed languages, this shouldn't be used as an excuse not to write unit tests. After all, the purpose of unit tests isn't to verify that the...