Adds cmake build support.

This commit is contained in:
Tom Hicks
2025-04-09 14:30:09 -07:00
parent a4109d2f49
commit 99f586975c
30 changed files with 2018 additions and 50 deletions

71
examples/README.md Normal file
View File

@@ -0,0 +1,71 @@
# TinyTest Examples
This directory contains examples demonstrating how to use TinyTest in different build environments.
## Available Examples
### 1. Standalone Example
Located in the `standalone` directory, this example demonstrates:
- How to use TinyTest in a standalone project with CMake's FetchContent
- No pre-installation required - TinyTest is automatically downloaded and built
- Testing multiple functions: arithmetic, string manipulation, prime checking
- Collecting and reporting test results
[View the Standalone Example](./standalone/)
### 2. Preinstalled Example
Located in the `preinstalled` directory, this example demonstrates:
- How to use TinyTest when it's installed on the system
- Using CMake's find_package to locate the TinyTest installation
- Testing a simple calculator application with exception handling
- The build script automatically installs TinyTest if it's not found
[View the Preinstalled Example](./preinstalled/)
### 3. Sample Project
Located in the `sample_project` directory, this example demonstrates:
- A minimal example that tests a single function
- Complete build scripts for both Windows and Linux/macOS
- Clear structure for a small TinyTest project
[View the Sample Project](./sample_project/)
## Building the Examples
Each example includes its own build scripts and instructions. See the README.md file in each example directory for specific details.
### Quick Start
```bash
# For the standalone example
cd standalone
chmod +x build.sh # On Linux/macOS
./build.sh # On Linux/macOS
build.bat # On Windows
# For the preinstalled example
cd preinstalled
chmod +x build.sh # On Linux/macOS
./build.sh # On Linux/macOS
build.bat # On Windows
# For the sample project
cd sample_project
chmod +x build.sh # On Linux/macOS
./build.sh # On Linux/macOS
build.bat # On Windows
```
## Choosing the Right Approach
- **Standalone (FetchContent)**: Best for projects where you want to ensure everyone has the same version of TinyTest without requiring a separate installation step.
- **Preinstalled (find_package)**: Best for larger projects or environments where TinyTest is a common dependency shared across multiple projects.
- **Sample Project**: Best for learning the basics of TinyTest with minimal complexity.

View File

@@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.14)
project(TinyTestPreinstalledExample VERSION 1.0.0 LANGUAGES CXX)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Find TinyTest package
find_package(TinyTest REQUIRED)
# Create the example executable
add_executable(calculator_test
main.cpp
)
# Link against the installed TinyTest library
target_link_libraries(calculator_test
PRIVATE
TinyTest::tinytest
)
# Enable CTest
include(CTest)
enable_testing()
add_test(NAME calculator_test COMMAND calculator_test)

View File

@@ -0,0 +1,78 @@
# TinyTest Preinstalled Example
This example demonstrates how to use TinyTest when it is installed on the system, integrating it through the CMake `find_package` mechanism.
## What This Example Demonstrates
- How to use a preinstalled TinyTest library with `find_package`
- How to create and run test suites for a simple calculator application
- How to test both regular function behavior and exception handling
- How to combine and report test results
## Prerequisites
- CMake 3.14 or higher
- C++17 compatible compiler
- TinyTest installed (the build script will install it if needed)
## Building and Running
### On Linux/macOS
```bash
# Make the build script executable
chmod +x build.sh
# Run the build script
./build.sh
```
### On Windows
```batch
build.bat
```
## How It Works
1. The build script:
- Checks if TinyTest is installed. If not, it builds and installs it
- Creates a build directory
- Configures the project with CMake, pointing to the TinyTest installation
- Builds the project
- Runs the tests with CTest
2. The CMake configuration:
- Finds TinyTest with `find_package(TinyTest REQUIRED)`
- Links the calculator test executable against `TinyTest::tinytest`
- Registers the test with CTest
3. The test code:
- Defines simple calculator functions
- Creates test suites for each function
- Executes the test suites and collects results
- Tests exception handling for division by zero
- Prints a summary of the results
## Code Structure
- `main.cpp`: Contains the calculator functions and tests
- `CMakeLists.txt`: Configures the build system to use the installed TinyTest
- `build.sh`/`build.bat`: Scripts to install TinyTest if needed, and build and run the example
## Understanding the Integration
The key part of the integration is in the CMakeLists.txt file:
```cmake
# Find TinyTest package
find_package(TinyTest REQUIRED)
# Link against the installed TinyTest library
target_link_libraries(calculator_test
PRIVATE
TinyTest::tinytest
)
```
This approach requires TinyTest to be installed on the system, either manually or through a package manager. The build script in this example will install TinyTest automatically if it's not found.

View File

@@ -0,0 +1,45 @@
@echo off
:: Build script for the preinstalled TinyTest example on Windows
:: Check if TinyTest is installed
if not exist "%USERPROFILE%\tinytest-install" (
echo TinyTest is not installed. Installing it now...
:: Store the current directory
set EXAMPLE_DIR=%CD%
:: Go to the root of the TinyTest project (assuming we're in examples/preinstalled)
cd ..\..
:: Build and install TinyTest
if not exist build-install mkdir build-install
cd build-install
cmake .. -DCMAKE_INSTALL_PREFIX=%USERPROFILE%\tinytest-install
cmake --build . --config Release
cmake --install . --config Release
:: Return to the example directory
cd %EXAMPLE_DIR%
echo TinyTest has been installed to %USERPROFILE%\tinytest-install
)
echo Building the preinstalled TinyTest example
:: Create build directory
if not exist build mkdir build
cd build
:: Configure the project with the path to the installed TinyTest
echo Configuring the project...
cmake .. -DCMAKE_PREFIX_PATH=%USERPROFILE%\tinytest-install
:: Build the project
echo Building the project...
cmake --build . --config Release
:: Run the tests
echo Running the tests...
ctest -C Release --output-on-failure
echo Preinstalled example has been built and tested successfully!

48
examples/preinstalled/build.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
# Build script for the preinstalled TinyTest example
# Exit on error
set -e
# Check if TinyTest is installed
if [ ! -d "$HOME/tinytest-install" ]; then
echo "TinyTest is not installed. Installing it now..."
# Store the current directory
EXAMPLE_DIR=$(pwd)
# Go to the root of the TinyTest project (assuming we're in examples/preinstalled)
cd ../../
# Build and install TinyTest
mkdir -p build-install
cd build-install
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/tinytest-install
cmake --build .
cmake --install .
# Return to the example directory
cd $EXAMPLE_DIR
echo "TinyTest has been installed to $HOME/tinytest-install"
fi
echo "Building the preinstalled TinyTest example"
# Create build directory
mkdir -p build
cd build
# Configure the project with the path to the installed TinyTest
echo "Configuring the project..."
cmake .. -DCMAKE_PREFIX_PATH=$HOME/tinytest-install
# Build the project
echo "Building the project..."
cmake --build .
# Run the tests
echo "Running the tests..."
ctest --output-on-failure
echo "Preinstalled example has been built and tested successfully!"

View File

@@ -0,0 +1,116 @@
#include <iostream>
#include <string>
#include <tinytest/tinytest.h>
// Function to test - simple calculator functions
double add(double a, double b) {
return a + b;
}
double subtract(double a, double b) {
return a - b;
}
double multiply(double a, double b) {
return a * b;
}
double divide(double a, double b) {
if (b == 0) {
throw std::invalid_argument("Division by zero");
}
return a / b;
}
int main() {
// Create and execute test suites
auto addSuite = TinyTest::MakeTestSuite(
"Addition",
add,
{
TinyTest::MakeTest("should correctly add positive numbers",
5.0,
std::make_tuple(2.0, 3.0)),
TinyTest::MakeTest("should handle negative numbers",
-1.0,
std::make_tuple(-4.0, 3.0)),
TinyTest::MakeTest("should handle zeros",
3.0,
std::make_tuple(3.0, 0.0))
}
);
auto subtractSuite = TinyTest::MakeTestSuite(
"Subtraction",
subtract,
{
TinyTest::MakeTest("should correctly subtract positive numbers",
2.0,
std::make_tuple(5.0, 3.0)),
TinyTest::MakeTest("should handle negative numbers",
-7.0,
std::make_tuple(-4.0, 3.0)),
TinyTest::MakeTest("should handle zeros",
3.0,
std::make_tuple(3.0, 0.0))
}
);
auto multiplySuite = TinyTest::MakeTestSuite(
"Multiplication",
multiply,
{
TinyTest::MakeTest("should correctly multiply positive numbers",
15.0,
std::make_tuple(5.0, 3.0)),
TinyTest::MakeTest("should handle negative numbers",
-12.0,
std::make_tuple(-4.0, 3.0)),
TinyTest::MakeTest("should handle zeros",
0.0,
std::make_tuple(3.0, 0.0))
}
);
auto divideSuite = TinyTest::MakeTestSuite(
"Division",
divide,
{
TinyTest::MakeTest("should correctly divide positive numbers",
2.0,
std::make_tuple(6.0, 3.0)),
TinyTest::MakeTest("should handle negative numbers",
-2.0,
std::make_tuple(-6.0, 3.0))
// Division by zero test will be handled separately
}
);
// Execute test suites and collect results
TinyTest::TestResults results;
results += TinyTest::ExecuteSuite(addSuite);
results += TinyTest::ExecuteSuite(subtractSuite);
results += TinyTest::ExecuteSuite(multiplySuite);
results += TinyTest::ExecuteSuite(divideSuite);
// Manually test the division by zero case
std::cout << "Testing division by zero exception handling:" << std::endl;
try {
divide(1.0, 0.0);
std::cout << " ❌FAILED: Division by zero did not throw an exception" << std::endl;
results.Fail("Division by zero did not throw an exception");
} catch (const std::invalid_argument&) {
std::cout << " ✅PASSED: Division by zero correctly threw an exception" << std::endl;
results.Pass();
} catch (...) {
std::cout << " ❌FAILED: Division by zero threw an unexpected exception type" << std::endl;
results.Fail("Division by zero threw an unexpected exception type");
}
// Print the summary
std::cout << "\nTest Results Summary:\n";
TinyTest::PrintResults(std::cout, results);
// Return non-zero exit code if there were failures or errors
return (results.Errors() > 0 || results.Failed() > 0) ? 1 : 0;
}

View File

@@ -0,0 +1,40 @@
cmake_minimum_required(VERSION 3.14)
project(TinyTestExample VERSION 1.0.0 LANGUAGES CXX)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# Debug: Print CMAKE_PREFIX_PATH before finding package
message(STATUS "CMAKE_PREFIX_PATH: ${CMAKE_PREFIX_PATH}")
# Find TinyTest package
find_package(TinyTest REQUIRED)
# Debug: Print variables after finding TinyTest
message(STATUS "TinyTest found: ${TinyTest_FOUND}")
message(STATUS "TinyTest include dirs: ${TINYTEST_INCLUDE_DIRS}")
message(STATUS "TinyTest libraries: ${TINYTEST_LIBRARIES}")
# Create an example executable that uses TinyTest
add_executable(example_test
main.cpp
)
# Configure include directories explicitly
target_include_directories(example_test
PRIVATE
${TINYTEST_INCLUDE_DIRS}
)
# Link against TinyTest
target_link_libraries(example_test
PRIVATE
TinyTest::tinytest
)
# Add a test using CTest
include(CTest)
enable_testing()
add_test(NAME example_test COMMAND example_test)

View File

@@ -0,0 +1,55 @@
# TinyTest Example Project
This is a sample project that demonstrates how to use TinyTest in a CMake project.
## Prerequisites
- CMake 3.14 or higher
- C++17 compatible compiler
- TinyTest installed (the build script will install it if needed)
## Building and Running
### On Linux/macOS
```bash
# Make the build script executable
chmod +x build.sh
# Run the build script
./build.sh
```
### On Windows
```batch
build.bat
```
## How it Works
1. The build script:
- Checks if TinyTest is installed. If not, it builds and installs it
- Creates a build directory
- Configures the project with CMake
- Builds the project
- Runs the tests with CTest
2. The CMake configuration:
- Finds TinyTest with `find_package(TinyTest REQUIRED)`
- Links the example test executable against `TinyTest::tinytest`
- Registers the test with CTest
3. The test code:
- Includes the TinyTest header
- Defines a test suite using TinyTest's API
- Runs the tests and reports results
## Understanding the Code
The main.cpp file demonstrates:
- How to define a function to test
- How to create test suites
- How to define tests with expected output
- How to execute test suites
- How to print and interpret test results

View File

@@ -0,0 +1,38 @@
@echo off
:: Build script for the sample project on Windows
:: Check if TinyTest is installed
if not exist "%USERPROFILE%\tinytest-install" (
echo TinyTest is not installed in %USERPROFILE%\tinytest-install. Installing it now...
:: Go to the root of the TinyTest project
cd ..\..\
:: Build and install TinyTest
if not exist build mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=%USERPROFILE%\tinytest-install
cmake --build . --config Release
cmake --install . --config Release
:: Return to the sample project directory
cd ..\examples\sample_project
echo TinyTest has been installed.
)
:: Create build directory
if not exist build mkdir build
cd build
:: Configure, build, and test the sample project
echo Configuring the project...
cmake .. -DCMAKE_PREFIX_PATH=%USERPROFILE%\tinytest-install
echo Building the project...
cmake --build . --config Release
echo Running the tests...
ctest -C Release --output-on-failure
echo Example project has been built and tested successfully!

View File

@@ -0,0 +1,59 @@
#!/bin/bash
# Build script for the sample project
# Exit on error
set -e
# Define installation paths to check
TINYTEST_INSTALL_PATHS=("$HOME/tinytest-install" "$HOME/tinytest-verify")
TINYTEST_INSTALLED=false
# Check if TinyTest is installed in any of the potential locations
for INSTALL_PATH in "${TINYTEST_INSTALL_PATHS[@]}"; do
if [ -d "$INSTALL_PATH" ]; then
echo "Found TinyTest installation at $INSTALL_PATH"
TINYTEST_PATH=$INSTALL_PATH
TINYTEST_INSTALLED=true
break
fi
done
# Install TinyTest if not found
if [ "$TINYTEST_INSTALLED" = false ]; then
echo "TinyTest is not installed. Installing it now..."
# Store current directory
EXAMPLE_DIR=$(pwd)
# Go to the root of the TinyTest project
cd ../../
# Build and install TinyTest
mkdir -p build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/tinytest-install
cmake --build .
cmake --install .
# Return to the sample project directory
cd $EXAMPLE_DIR
echo "TinyTest has been installed."
TINYTEST_PATH=$HOME/tinytest-install
fi
# Create build directory
mkdir -p build
cd build
# Configure, build, and test the sample project
echo "Configuring the project..."
cmake .. -DCMAKE_PREFIX_PATH=$TINYTEST_PATH
echo "Building the project..."
cmake --build .
echo "Running the tests..."
ctest --output-on-failure
echo "Example project has been built and tested successfully!"

View File

@@ -0,0 +1,46 @@
#include <iostream>
#include <string>
#include <vector>
#include <tinytest/tinytest.h>
// Function to test
std::string truncate(const std::string& text, int length) {
if (text.length() <= length) {
return text;
}
return text.substr(0, length) + "...";
}
int main() {
// Define test suites using TinyTest
auto truncate_tests = TinyTest::MakeTestSuite(
"TruncateFunction",
truncate,
{
TinyTest::MakeTest(
"should return the original text if it's shorter than the limit",
std::string("Hello"),
std::make_tuple(std::string("Hello"), 10)
),
TinyTest::MakeTest(
"should truncate the text with ellipsis if it's longer than the limit",
std::string("Hello..."),
std::make_tuple(std::string("Hello, World!"), 5)
),
TinyTest::MakeTest(
"should handle empty strings",
std::string(""),
std::make_tuple(std::string(""), 5)
)
}
);
// Execute test suite
auto results = TinyTest::ExecuteSuite(truncate_tests);
// Print results
TinyTest::PrintResults(std::cout, results);
// Return non-zero exit code if any tests failed
return (results.Failed() > 0 || results.Errors() > 0) ? 1 : 0;
}

View File

@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.14)
project(TinyTestStandaloneExample VERSION 1.0.0 LANGUAGES CXX)
# Set C++ standard
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# FetchContent for dependency management
include(FetchContent)
# Method 1: Use FetchContent to download TinyTest from GitHub
FetchContent_Declare(
tinytest
GIT_REPOSITORY https://github.com/headhunter45/TinyTest.git
GIT_TAG main # or a specific tag/commit
)
# Make TinyTest available
FetchContent_MakeAvailable(tinytest)
# Create the example executable
add_executable(tinytest_example
example.cpp
)
# Link against the TinyTest library
target_link_libraries(tinytest_example
PRIVATE
tinytest_lib
)
# Enable CTest
include(CTest)
enable_testing()
add_test(NAME example_test COMMAND tinytest_example)

View File

@@ -0,0 +1,75 @@
# TinyTest Standalone Example
This example demonstrates how to use TinyTest in a standalone project using CMake's FetchContent to automatically download and build TinyTest.
## What This Example Demonstrates
- How to use CMake's FetchContent to automatically download TinyTest
- How to create test suites for different types of functions
- How to define test cases with expected results
- How to execute tests and collect the results
## Prerequisites
- CMake 3.14 or higher
- C++17 compatible compiler
- Git (for FetchContent to download TinyTest)
## Building and Running
### On Linux/macOS
```bash
# Make the build script executable
chmod +x build.sh
# Run the build script
./build.sh
```
### On Windows
```batch
build.bat
```
## How It Works
1. CMake is configured to use FetchContent to download TinyTest
2. The example executable is linked against the TinyTest library
3. CTest is enabled to run the tests
4. Several functions are defined and tested:
- `add`: Adds two integers
- `concatenate`: Concatenates two strings
- `isPrime`: Checks if a number is prime
- `vectorSum`: Calculates the sum of a vector of integers
## Code Structure
- `example.cpp`: Contains the functions to test and test suites
- `CMakeLists.txt`: Configures the build system with FetchContent
- `build.sh`/`build.bat`: Scripts to build and run the example
## Understanding the Integration
The key part of the integration is in the CMakeLists.txt file:
```cmake
# Use FetchContent to download TinyTest
FetchContent_Declare(
tinytest
GIT_REPOSITORY https://github.com/headhunter45/TinyTest.git
GIT_TAG main
)
# Make TinyTest available
FetchContent_MakeAvailable(tinytest)
# Link against the TinyTest library
target_link_libraries(tinytest_example
PRIVATE
tinytest_lib
)
```
This approach automatically downloads, builds, and links against TinyTest without requiring a separate installation step.

View File

@@ -0,0 +1,22 @@
@echo off
:: Build script for the standalone TinyTest example on Windows
echo Building TinyTest standalone example
:: Create build directory
if not exist build mkdir build
cd build
:: Configure the project
echo Configuring the project...
cmake ..
:: Build the project
echo Building the project...
cmake --build . --config Release
:: Run the tests
echo Running the tests...
ctest -C Release --output-on-failure
echo Standalone example has been built and tested successfully!

25
examples/standalone/build.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# Build script for the standalone TinyTest example
# Exit on error
set -e
echo "Building TinyTest standalone example"
# Create build directory
mkdir -p build
cd build
# Configure the project
echo "Configuring the project..."
cmake ..
# Build the project
echo "Building the project..."
cmake --build .
# Run the tests
echo "Running the tests..."
ctest --output-on-failure
echo "Standalone example has been built and tested successfully!"

View File

@@ -0,0 +1,129 @@
#include <iostream>
#include <string>
#include <vector>
#include "tinytest.h"
// Function to test: Simple add function
int add(int a, int b) {
return a + b;
}
// Function to test: Concatenate strings
std::string concatenate(const std::string& a, const std::string& b) {
return a + b;
}
// Function to test: Check if a number is prime
bool isPrime(int n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0 || n % 3 == 0) return false;
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) return false;
}
return true;
}
// Function to test: Vector sum
int vectorSum(const std::vector<int>& vec) {
int sum = 0;
for (int v : vec) {
sum += v;
}
return sum;
}
int main() {
// Create test suites using TinyTest
// Test suite for add function
auto addSuite = TinyTest::MakeTestSuite(
"AddFunction", // Suite name
add, // Function to test
{ // Test cases - each defined using MakeTest
TinyTest::MakeTest("should add two positive numbers",
5, // Expected result
std::make_tuple(2, 3)), // Input parameters
TinyTest::MakeTest("should add a positive and negative number",
-1,
std::make_tuple(2, -3)),
TinyTest::MakeTest("should add two negative numbers",
-5,
std::make_tuple(-2, -3))
}
);
// Test suite for concatenate function
auto concatSuite = TinyTest::MakeTestSuite(
"ConcatenateFunction",
concatenate,
{
TinyTest::MakeTest("should concatenate two strings",
std::string("HelloWorld"),
std::make_tuple(std::string("Hello"), std::string("World"))),
TinyTest::MakeTest("should concatenate with empty string",
std::string("Hello"),
std::make_tuple(std::string("Hello"), std::string("")))
}
);
// Test suite for isPrime function
auto primeSuite = TinyTest::MakeTestSuite(
"IsPrimeFunction",
isPrime,
{
TinyTest::MakeTest("should identify 2 as prime",
true,
std::make_tuple(2)),
TinyTest::MakeTest("should identify 4 as not prime",
false,
std::make_tuple(4)),
TinyTest::MakeTest("should identify 17 as prime",
true,
std::make_tuple(17)),
TinyTest::MakeTest("should identify negative numbers as not prime",
false,
std::make_tuple(-7))
}
);
// Test suite for vectorSum function with a custom compare function
auto sumSuite = TinyTest::MakeTestSuite(
"VectorSumFunction",
vectorSum,
{
TinyTest::MakeTest("should sum empty vector to 0",
0,
std::make_tuple(std::vector<int>{})),
TinyTest::MakeTest("should sum single element vector",
5,
std::make_tuple(std::vector<int>{5})),
TinyTest::MakeTest("should sum multiple elements",
10,
std::make_tuple(std::vector<int>{1, 2, 3, 4}))
}
);
// Execute all test suites and get the results
TinyTest::TestResults results;
results += TinyTest::ExecuteSuite(addSuite);
results += TinyTest::ExecuteSuite(concatSuite);
results += TinyTest::ExecuteSuite(primeSuite);
results += TinyTest::ExecuteSuite(sumSuite);
// Print the summary of results
std::cout << "\nTest Results Summary:\n";
TinyTest::PrintResults(std::cout, results);
// Return non-zero exit code if there were failures or errors
return (results.Errors() > 0 || results.Failed() > 0) ? 1 : 0;
}