# 15.5 移植测试

现在，来讨论如何将测试从引用构建移植到CMake。

## 准备工作

如果移植的项目包含测试目标，或任何形式的自动化测试，以及测试脚本。第一步，运行传统的测试步骤，并记录所使用的命令。对于Vim项目，可以从`src/testdir/Makefile`开始。在`src/testdir/Makefile`和测试脚本中的一些对于测试的定义，我们将在`src/testdir/CMakeLists.txt`中进行相应的定义。所以，我们必须在`src/CMakeLists.txt`中引用它:

```
add_subdirectory(testdir)
```

处理`src/CMakeLists.txt`之前，我们还应该在主`CMakeLists.txt`中启用测试:

```
# enable the test target
enable_testing()

# process src/CMakeLists.txt in its own scope
add_subdirectory(src)
```

目前为止，使用`add_test`填充`src/testdir/CMakeLists.txt`之前，测试目标为空。在`add_test`中指定要运行的测试名称和命令。该命令可以用任何语言编写。CMake的关键部分是，如果测试成功，脚本返回零；如果测试失败，脚本返回非零。对于Vim，我们需要多步骤测试，这将在下一节中讨论。

## 实现多步测试

在`src/testdir/Makefile`的目标表明，Vim代码运行测试多步测试：

1. Vim脚本可执行测试流程，产生一个输出文件
2. 输出文件是与参考文件进行比，,如果这些文件相同，测试成功
3. 删除临时文件

由于`add_test`只能执行一个命令，因此无法以可移植的方式将其放到单个`add_test`中。一种解决方案是在Python脚本中定义测试步骤，并使用一些参数执行Python脚本。这里提供的另一种选择，也是跨平台的，在单独的CMake脚本中定义测试步骤，并使用`add_test`执行这个脚本。我们将在`src/testdir/test.cmake`中定义测试步骤:

```
function(execute_test _vim_executable _working_dir _test_script)
  # generates test.out
  execute_process(
    COMMAND ${_vim_executable} -f -u unix.vim -U NONE --noplugin --not-a-term -s dotest.in ${_test_script}.in
    WORKING_DIRECTORY ${_working_dir}
    )

  # compares test*.ok and test.out
  execute_process(
    COMMAND ${CMAKE_COMMAND} -E compare_files ${_test_script}.ok test.out
    WORKING_DIRECTORY ${_working_dir}
    RESULT_VARIABLE files_differ
    OUTPUT_QUIET
    ERROR_QUIET
    )

  # removes leftovers
  file(REMOVE ${_working_dir}/Xdotest)

  # we let the test fail if the files differ
  if(files_differ)
      message(SEND_ERROR "test ${_test_script} failed")
  endif()
endfunction()

execute_test(${VIM_EXECUTABLE} ${WORKING_DIR} ${TEST_SCRIPT})
```

同样，我们选择函数而不是宏，为的是使得变量不会超出函数作用域。它将调用`execute_test`函数，处理这个脚本。但是，我们必须确保`${VIM_EXECUTABLE}`、`${WORKING_DIR}`和`${TEST_SCRIPT}`是在外部定义。`src/testdir/CMakeLists.txt`中定义:

```
add_test(
  NAME
      test1
  COMMAND
    ${CMAKE_COMMAND} -D VIM_EXECUTABLE=$<TARGET_FILE:vim>
    -D WORKING_DIR=${CMAKE_CURRENT_LIST_DIR}
    -D TEST_SCRIPT=test1
    -P ${CMAKE_CURRENT_LIST_DIR}/test.cmake
  WORKING_DIRECTORY
      ${PROJECT_BINARY_DIR}
  )
```

Vim项目有很多测试，但是在这个例子中，我们只移植了一个(test1)。

## 测试建议

对于移植测试，我们可以给出至少两个建议。

1. 要确保测试并不总是报告成功，如果破坏了代码或修改了验证数据，请验证测试是否失败。
2. 添加测试的成本估算，以便在并行运行时，首先启动较长的测试，以最小化总测试时间。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chenxiaowei.gitbook.io/cmake-cookbook/15.0-chinese/15.5-chinese.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
