Quick Start
Welcome! If you are new to Touca, this is the right place to be! Our main objective here is to introduce Touca without taking too much of your time. We hope to make you excited enough to check out our hands-on tutorials next.

Revisiting Unit Testing

Let us imagine that we want to test a software workflow that reports whether a given number is prime.
Python
C++
TypeScript
Java
1
def is_prime(number: int):
Copied!
1
bool is_prime(const int number);
Copied!
1
function is_prime(number: number): boolean;
Copied!
1
public static boolean isPrime(final int number);
Copied!
We can use unit testing in which we hard-code a set of input numbers and list our expected return value for each input.
Python
C++
TypeScript
Java
1
from code_under_test import is_prime
2
3
def test_is_prime():
4
assert is_prime(-1) == False
5
assert is_prime(1) == False
6
assert is_prime(2) == True
7
assert is_prime(13) == True
Copied!
1
#include "catch2/catch.hpp"
2
#include "code_under_test.hpp"
3
4
TEST_CASE("is_prime")
5
{
6
CHECK(is_prime(-1) == false);
7
CHECK(is_prime(1) == false);
8
CHECK(is_prime(2) == true);
9
CHECK(is_prime(13) == true);
10
}
Copied!
1
import { is_prime } from "code_under_test";
2
3
test("test is_prime", () => {
4
expect(is_prime(-1)).toEqual(false);
5
expect(is_prime(1)).toEqual(false);
6
expect(is_prime(2)).toEqual(true);
7
expect(is_prime(13)).toEqual(true);
8
});
Copied!
1
import org.junit.jupiter.api.Test;
2
import static org.junit.jupiter.api.Assertions.assertFalse;
3
import static org.junit.jupiter.api.Assertions.assertTrue;
4
5
public final class PrimeTest {
6
7
@Test
8
public void isPrime() {
9
assertFalse(Prime.isPrime(-1));
10
assertFalse(Prime.isPrime(1));
11
assertTrue(Prime.isPrime(2));
12
assertTrue(Prime.isPrime(13));
13
}
14
}
Copied!
Unit testing is an effective method to gain confidence in the behavior of functions we are going to implement or have already implemented. But let us, for a moment, review some of the fundamentals of building and maintaining unit tests:
    For each input, we need to specify the corresponding expected output, as part
    of our test logic.
    As our software requirements evolve, we may need to go back and change our
    expected outputs.
    When we find other interesting inputs, we may need to go back and include them
    in our set of inputs.
In our example, the input and output of our code under test are a number and a boolean. If we were testing a video compression algorithm, they may have been video files. In that case:
    Describing the expected output for a given video file would be difficult.
    When we make changes to our compression algorithm, accurately reflecting those
    changes in our expected values would be time-consuming.
    We would need a large number of input video files to gain confidence that our
    algorithm works correctly.

Introducing Touca

Touca makes it easier to continuously test workflows of any complexity and with any number of test cases.
Python
C++
TypeScript
Java
1
import touca
2
3
@touca.Workflow
4
def is_prime_test(testcase: str):
5
touca.add_result("output", is_prime(int(testcase)))
6
7
if __name__ == "__main__":
8
touca.run()
Copied!
1
#include "touca/touca.hpp"
2
#include "touca/touca_main.hpp"
3
#include "code_under_test.hpp"
4
5
void touca::main(const std::string& testcase)
6
{
7
const auto number = std::stoul(testcase);
8
touca::add_result("output", is_prime(number));
9
}
Copied!
1
import { touca } from "@touca/node";
2
import { is_prime } from "./code_under_test";
3
4
touca.workflow("is_prime_test", (testcase: string) => {
5
touca.add_result("output", is_prime(Number.parseInt(testcase)));
6
});
7
8
touca.run();
Copied!
1
import io.touca.Touca;
2
3
public final class PrimeTest {
4
5
@Touca.Workflow
6
public void isPrime(final String testcase) {
7
final int number = Integer.parseInt(testcase);
8
Touca.addResult("output", Prime.isPrime(number));
9
}
10
11
public static void main(String[] args) {
12
Touca.run(PrimeTest.class, args);
13
}
14
}
Copied!
This code needs some explanation. Let us start by reviewing what is missing:
    We have fully decoupled our test inputs from our test logic. We refer to these
    inputs as "test cases". Our open-source SDKs retrieve the test cases from the
    command line, or a file, or a remote Touca server and feed them one by one to
    our code under test.
    We have removed the concept of expected values. With Touca, we only describe
    the actual behavior and performance of our code under test by capturing values
    of interesting variables and runtime of important functions, from anywhere
    within our code. Touca SDKs submit this description to a remote Touca server
    which compares it against the description for a trusted version of our code.
    The server visualizes any differences and reports them in near real-time.
We can run Touca tests with any number of inputs from the command line:
Python
C++
TypeScript
Java
1
python3 prime_app_test.py
2
--api-key <TOUCA_API_KEY>
3
--api-url <TOUCA_API_URL>
4
--revision v1.0
5
--testcase 13 17 51
Copied!
1
./prime_app_test
2
--api-key <TOUCA_API_KEY>
3
--api-url <TOUCA_API_URL>
4
--revision v1.0
5
--testcase 13 17 51
Copied!
1
node dist/is_prime_test.js
2
--api-key <TOUCA_API_KEY>
3
--api-url <TOUCA_API_URL>
4
--revision v1.0
5
--testcase 13 17 51
Copied!
1
gradle runExampleMinimal --args='--api-key <TOUCA_API_KEY> --api-url <TOUCA_API_URL> --revision v1.0 --testcase 13 17 51'
Copied!
Where TOUCA_API_KEY and TOUCA_API_URL can be obtained from the Touca server at app.touca.io. This command produces the following output:
1
Touca Test Framework
2
Suite: is_prime_test
3
Revision: v1.0
4
5
( 1 of 3 ) 13 (pass, 127 ms)
6
( 2 of 3 ) 17 (pass, 123 ms)
7
( 3 of 3 ) 51 (pass, 159 ms)
8
9
Processed 3 of 3 testcases
10
Test completed in 565 ms
Copied!
If and when we change the implementation of is_prime, we can rerun the test (passing a different version number) and submit the results for the new version to the Touca server. The server takes care of storing and comparing the results submitted between the two versions and reports the differences in near real-time.
The Touca server considers the test results submitted for the first version of our test, as our baseline: all subsequent versions submitted to the server would be compared against it. If, for any reason, requirements of our software change and we decide to change this baseline, we can do so by clicking a button right from the Touca server UI.
Touca Server

Value Proposition

Touca is very effective in addressing common problems in the following situations:
    When we need to test our workflow with a large number of inputs.
    When the output of our workflow is too complex, or too difficult to describe
    in our unit tests.
    When interesting information to check for regression is not exposed through
    the interface of our workflow.
The highlighted design features of Touca can help us test these workflows at any scale.
    Decoupling our test input from our test logic, can help us manage our long
    list of inputs without modifying the test logic. Managing that list on a
    remote server accessible to all members of our team, can help us add notes to
    each test case, explain why they are needed and track how their performance
    changes over time.
    Submitting our test results to a remote server, instead of storing them in
    files, can help us avoid the mundane tasks of managing and processing of those
    results. The Touca server retains test results and makes them accessible to
    all members of the team. It compares test results using their original data
    types and reports discovered differences in real-time to all interested
    members of our team. It allows us to audit how our software evolves over time
    and provides high-level information about our tests.
Last modified 25d ago