Getting Started with Unittest

First, compile a simple Cangjie function:

package example

func add(left: Int64, right: Int64) {
    return left + right
}

Save this function in an add.cj file and then write the test code for the function.

package example

@Test
func addTest() {
    @Expect(add(2, 3), 5)
}

The test includes the following components:

  • @Test macro, applied to the addTest function, indicating that it is a test function.
  • @Expect macro, used as an assertion to check whether the two input parameters are equal. In this example, the two parameters are the result add(2, 3) and expected value 5 of the add function.

Save the test function in an add_test.cj file and run it with the code function in add.cj.

cjc add.cj add_test.cj --test -o add_test
./add_test

Normally, you would get output similar to the following:

-------------------------------------------------------------------------------------------------
TP: default, time elapsed: 59363 ns, Result:
    TCS: TestCase_addTest, time elapsed: 32231 ns, RESULT:
    [ PASSED ] CASE: addTest (28473 ns)
    Summary: TOTAL: 1
    PASSED: 1, SKIPPED: 0, ERROR: 0
    FAILED: 0
--------------------------------------------------------------------------------------------------

At this point, we have completed the test setup and execution. Now, let's take a closer look at the cjc command used to build the test.

    code file to be tested
    ↓
cjc add.cj add_test.cj --test -o add_test
           ↑           ↑
           |           --test indicates that a binary file is generated in test mode
           test file

Note that running the cjc compiler directly is not recommended for complex projects. For large-scale projects, the cjpm package manager is recommended. Take testing a cjpm project as an example.

First, create a simple cjpm project that contains a package named example. The file structure of the project is as follows (with files from the cjc example):

- src
  |
  +- example
     |
     +- add.cj
     +- add_test.cj

The original files indicate that they belong to the example package. Therefore, you only need to run the following command to initialize the cjpm project:

cjpm init example example

The cjpm package manager has built-in support for running unit tests. Therefore, you can simply run:

cjpm test

This command runs all tests in packages of the project and generates output similar to the following:

--------------------------------------------------------------------------------------------------
TP: example/example, time elapsed: 60989 ns, Result:
    TCS: TestCase_addTest, time elapsed: 32804 ns, RESULT:
    [ PASSED ] CASE: addTest (29195 ns)
    Summary: TOTAL: 1
    PASSED: 1, SKIPPED: 0, ERROR: 0
    FAILED: 0
--------------------------------------------------------------------------------------------------

Note that you do not need to specify --test or any other special options. By default, cjpm uses filenames in the project to determine whether the files should be compiled in test mode or normal mode. In the example package, add_test.cj is the test file, with the filename ending with _test.cj. In normal builds, binary files or libraries do not include these test files.

The unit test framework APIs are already available in the unittest package of the std module, and the macros are in the unittest.testmacro package of the std module. Therefore, you do not need to explicitly import the them to the test files.

For more information about the basic concepts of the unittest framework, see Basic Concepts and Usage of Unittest.