Spec-Zone.ru › Nim

Testament

Исходный код Редактировать

Testament — это расширенный автоматический инструмент для запуска юнит-тестов в Nim, используется для разработки самого Nim, предлагает изоляцию процессов для ваших тестов, может генерировать статистику по тестовым случаям, поддерживает несколько целей (C, C++, ObjectiveC, JavaScript и т.д.), имитирует сухие запуски, имеет логирование, может генерировать HTML-отчёты, пропускать тесты из файла и многое другое, поэтому может быть полезно для запуска даже самых сложных тестов.

Расположение файлов тестов

По умолчанию Testament ищет файлы тестов по "./tests/category/*.nim". Вы можете переопределить этот шаблон glob с помощью pattern <glob>. Путь к текущей рабочей директории можно изменить, используя --directory:"folder/subfolder/".

Testament использует компилятор nim на PATH. Вы можете изменить это с помощью --nim:"folder/subfolder/nim". Запуск тестов JavaScript с помощью --targets:"js" требует работающей NodeJS на PATH.

Команды

p|pat|pattern <glob> запустить все тесты, соответствующие заданному шаблону all запустить все тесты внутри категорийных папок c|cat|category <category> запустить все тесты определенной категории r|run <test> запустить отдельный файл теста html сгенерировать testresults.html из базы данных

Параметры

--print
вывести результаты в консоль
--verbose
вывести команды (компиляция и запуск тестов)
--simulate
показать, какие тесты будут запущены, но не запускать их (для отладки)
--failing
отобразить только проваленные/пропущенные тесты
--targets:"c cpp js objc" run tests for specified targets (default: c)
--nim:path
использовать определенный исполняемый файл nim (по умолчанию: $PATH/nim)
--directory:dir
Перейти в директорию dir перед чтением тестов или выполнением любых других действий.
--colors:on|off
Включить/отключить цветной вывод сообщений.
--backendLogging:on|off
Отключить или включить логирование бэкенда. По умолчанию включено.
--megatest:on|off
Включить или отключить megatest. По умолчанию включено.
--valgrind:on|off
Включить или отключить поддержку valgrind. По умолчанию включено.
--skipFrom:file
Прочитать тесты для пропуска из file — по одному тесту в строке, комментарии # игнорируются

Запуск одного теста

Это минимальный пример для понимания основ, не очень полезный для производства, но легко понять:

$ mkdir -p tests/category
$ echo "assert 42 == 42" > tests/category/test0.nim
$ testament run tests/category/test0.nim
PASS: tests/category/test0.nim c                           ( 0.2 sec)
$ testament r tests/category/test0
PASS: tests/category/test0.nim C                           ( 0.2 sec)

Запуск всех тестов из директории

Это запустит все тесты в корневой директории tests/. ПРИМЕЧАНИЕ: эти тесты пропущены testament all.

$ testament pattern "tests/*.nim"

Чтобы искать тесты глубже в директории, используйте

$ testament pattern "tests/**/*.nim"    # one level deeper
$ testament pattern "tests/**/**/*.nim" # two levels deeper

HTML-отчёты

Генерировать HTML-отчёты testresults.html из юнит-тестов, необходимо запустить хотя бы 1 тест перед генерацией отчёта:

$ testament html

Написание юнит-тестов

Пример "шаблона" для редактирования и написания юнит-теста Testament:

discard """
  
  # What actions to expect completion on.
  # Options:
  #   "compile": expect successful compilation
  #   "run": expect successful compilation and execution
  #   "reject": expect failed compilation. The "reject" action can catch
  #             {.error.} pragmas but not {.fatal.} pragmas because
  #             {.error.} calls are expected to originate from the test-file,
  #             and can explicitly be specified using the "file", "line" and
  #             "column" options.
  #             {.fatal.} pragmas guarantee that compilation will be aborted.
  action: "run"
  
  # For testing failed compilations you can specify the expected origin of the
  # compilation error.
  # With the "file", "line" and "column" options you can define the file,
  # line and column that a compilation-error should have originated from.
  # Use only with action: "reject" as it expects a failed compilation.
  # Requires errormsg or msg to be defined.
  # file: ""
  # line: ""
  # column: ""
  
  # The exit code that the test is expected to return. Typically, the default
  # value of 0 is fine. Note that if the test will be run by valgrind, then
  # the test will exit with either a code of 0 on success or 1 on failure.
  exitcode: 0
  
  # Provide an `output` string to assert that the test prints to standard out
  # exactly the expected string. Provide an `outputsub` string to assert that
  # the string given here is a substring of the standard out output of the
  # test (the output includes both the compiler and test execution output).
  output: ""
  outputsub: ""
  
  # Whether to sort the compiler output lines before comparing them to the
  # expected output.
  sortoutput: true
  
  # Provide a `nimout` string to assert that the compiler during compilation
  # prints the defined lines to the standard out.
  # The lines must match in order, but there may be more lines that appear
  # before, after, or in between them.
  nimout: '''
a very long,
multi-line
string'''
  
  # This is the Standard Input the test should take, if any.
  input: ""
  
  # Error message the test should print, if any.
  errormsg: ""
  
  # Can be run in batch mode, or not.
  batchable: true
  
  # Can be run Joined with other tests to run all together, or not.
  joinable: true
  
  # On Linux 64-bit machines, whether to use Valgrind to check for bad memory
  # accesses or memory leaks. On other architectures, the test will be run
  # as-is, without Valgrind.
  # Options:
  #   true: run the test with Valgrind
  #   false: run the without Valgrind
  #   "leaks": run the test with Valgrind, but do not check for memory leaks
  valgrind: false   # Can use Valgrind to check for memory leaks, or not (Linux 64Bit only).
  
  # Checks that the specified piece of C-code is within the generated C-code.
  ccodecheck: "'Assert error message'"
  
  # Command the test should use to run. If left out or an empty string is
  # provided, the command is taken to be:
  # "nim $target --hints:on -d:testing --nimblePath:build/deps/pkgs $options $file"
  # Subject to variable interpolation.
  cmd: "nim c -r $file"
  
  # Maximum generated temporary intermediate code file size for the test.
  maxcodesize: 666
  
  # Timeout seconds to run the test. Fractional values are supported.
  timeout: 1.5
  
  # Targets to run the test into (c, cpp, objc, js). Defaults to c.
  targets: "c js"
  
  # flags with which to run the test, delimited by `;`
  matrix: "; -d:release; -d:caseFoo -d:release"
  
  # Conditions that will skip this test. Use of multiple "disabled" clauses
  # is permitted.
  disabled: "bsd"   # Can disable OSes...
  disabled: "win"
  disabled: "32bit" # ...or architectures
  disabled: "i386"
  disabled: "azure" # ...or pipeline runners
  disabled: true    # ...or can disable the test entirely

"""
assert true
assert 42 == 42, "Assert error message"
  • Как видите, "Spec" — это просто discard """ """.
  • Spec имеет разумные значения по умолчанию, поэтому вам не нужно их все указывать, любая простая проверка (assert) сработает.
  • Это не весь спектр возможностей Testament, см. спецификацию Testament на GitHub, см. parseSpec().
  • Сам Nim использует Testament, поэтому есть много примеров тестов.
  • Имеет некоторую встроенную совместимость с CI, например, Azure Pipelines и т.д.

Встроенные подсказки, предупреждения и ошибки (примечания)

Проверка строки, столбца, типа и сообщения подсказок, предупреждений и ошибок может быть выполнена встроенно, как показано ниже:

{.warning: "warning!!"} #[tt.Warning
         ^ warning!! [User] ]#

Открывающая #[tt. отмечает строку сообщения. ^ отмечает столбец сообщения.

Встроенные сообщения можно комбинировать с nimout при nimoutFull равно false (по умолчанию). Это позволяет проверять ожидаемые сообщения из других модулей:

discard """
  nimout: "config.nims(1, 1) Hint: some hint message [User]"
"""
{.warning: "warning!!"} #[tt.Warning
         ^ warning!! [User] ]#

Несколько сообщений для одной строки можно проверить, разделив сообщения точкой с запятой:

discard """
  matrix: "--errorMax:0 --styleCheck:error"
"""

proc generic_proc*[T](a_a: int) = #[tt.Error
     ^ 'generic_proc' should be: 'genericProc'; tt.Error
                      ^ 'a_a' should be: 'aA' ]#
  discard

Используйте --errorMax:0 в matrix, или cmd: "nim check $file" при проверке нескольких сообщений типа 'Ошибка'.

Интерполяция переменных в сообщениях вывода

errormsg, nimout, и встроенные сообщения поддерживают следующие интерполяции переменных:

  • ${/} - разделитель директорий платформы
  • $file - имя файла (без директории) теста

Все остальные $ символы необходимо экранировать как $$.

Интерполяция переменных в команде

Параметр cmd поддерживает следующие интерполяции переменных:

  • $target - целевая платформа компиляции, например c.
  • $options - параметры компилятора.
  • $file - путь к файлу теста.
  • $filedir - директория файла теста.
discard """
  cmd: "nim $target --nimblePath:./nimbleDir/simplePkgs $options $file"
"""

Все остальные $ символы необходимо экранировать как $$.

Примеры юнит-тестов

Ожидается ошибка:

discard """
  errormsg: "undeclared identifier: 'not_defined'"
"""
assert not_defined == "not_defined", "not_defined is not defined"

Ожидается ошибка, сброшенная из другого файла:

# test.nim
discard """
  action: "reject"
  errorMsg: "I break"
  file: "breakPragma.nim"
"""
import ./breakPragma

proc x() {.justDo.} = discard

# breakPragma.nim
import std/macros

macro justDo*(procDef: typed): untyped =
  error("I break")
  return procDef

Ожидается сгенерированный C-код, содержащий заданный фрагмент кода:

discard """
  # Checks that the string "Assert error message" is in the generated
  # C code.
  ccodecheck: "'Assert error message'"
"""
assert 42 == 42, "Assert error message"

Код с ненулевым кодом выхода:

discard """
  exitcode: 1
"""
quit "Non-Zero exit code", 1

Проверка стандартного вывода:

discard """
  
  output: '''
0
1
2
3
4
5
'''

"""
for i in 0..5: echo i

Тесты JavaScript:

discard """
  targets: "js"
"""
when defined(js):
  import std/jsconsole
  console.log("My Frontend Project")

Тесты времени компиляции:

discard """
  action: "compile"
"""
static: assert 9 == 9, "Compile time assert"

Тесты без Spec:

assert 1 == 1

См. также:

  • Unittest

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/testament.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API