Тест-раннер має єдину відповідальність: узяти рішення, запустити всі тести й повернути уніфікований вивід. Усі взаємодії із сайтом Exercism відбуваються автоматично й не є частиною цієї специфікації.
two-fer)./tmp для тимчасових файлів (наприклад, для компіляції джерел).results.json у каталог вихідних даних.Тест-раннер отримує 100% CPU і 3 ГБ памʼяті на 20-секундне вікно для кожного рішення. Після 20 секунд процес зупиняється й повідомляє про перевищення часу.
Ми наполегливо радимо дотримуватися нашого документа з найкращими практиками продуктивності, щоб зменшити ймовірність перевищення часу.
У файлах results.json підтримуються такі поля:
ключ:
version, тип:number, наявність: обовʼязкова
версія: 1, 2, 3
Версія специфікації, якої дотримується цей файл:
1: для треків, чий тест-раннер не може надати інформацію про окремі тести.2: для треків, чий тест-раннер може виводити інформацію про окремі тести. Мінімальна обовʼязкова версія для треків із концептуальними вправами.3: для треків, чий тест-раннер може привʼязати окремі тести до завдання.ключ:
status, тип:string, наявність: обовʼязкова
версія: 1, 2, 3
Дійсними є такі загальні статуси:
pass: усі тести пройденоfail: принаймні один тест має статус fail або error
error: жоден тест не виконано (зазвичай це означає помилку компіляції або синтаксичну помилку)Статус error слід використовувати лише тоді, коли всі тести завершилися з помилкою.
Для компільованих мов це зазвичай наслідок того, що код не компілюється.
Для інтерпретованих мов це помилка часу виконання, наприклад синтаксична помилка, через яку файл не розбирається.
ключ:
message, тип:string, наявність: обовʼязкова, якщоstatus=error, або колиstatus=failіversion=1
версія: 1, 2, 3
Коли статус error (жоден тест не виконано правильно), слід надати ключ message верхнього рівня. Він має показати користувачеві помилку, що сталася. Оскільки це єдина інформація, яку користувач отримає про те, як налагодити свою проблему, вона має бути якомога зрозумілішою:
<solution-dir>/relative/path замість /full/path/to, бо там будуть некорисні дані, специфічні для ECRУ Ruby в разі синтаксичної помилки ми надаємо помилку часу виконання та стек викликів. Для компільованих мов слід надавати помилку компіляції.
Значення message верхнього рівня обмежене 65535 символами.
Якщо значення містить багатобайтові символи, фактична максимальна довжина менша.
Коли статус не error, або встановіть значення null, або взагалі пропустіть ключ.
ключ:
tests, тип:array, наявність: обовʼязкова, якщоstatus=failабоstatus=pass
версія: 2, 3
Це масив результатів тестів, описаних у розділі «Для кожного тесту» нижче.
Тести ПОВИННІ повертатися в тому порядку, у якому їх задано у файлі тестів. Для мов, які виконують тести у випадковому порядку, це може означати перевпорядкування результатів відповідно до порядку, заданого у файлі тестів.
Причина в тому, що учням показують лише першу невдачу, тому важливо, щоб це була саме та невдача. Оскільки тести у файлі тестів зазвичай упорядковані в стилі TDD, і оскільки для практичних вправ учні бачать файл тестів у редакторі, узгодження результатів із файлом тестів є критично важливим.
ключ:
name, тип:string, наявність: обовʼязкова
версія: 2, 3
Це назва тесту в зручному для читання форматі.
ключ:
test_code, тип:string, наявність: обовʼязкова, якщо вправа є концептуальною вправою
версія: 2, 3
Це поле ПОВИННЕ бути присутнім для концептуальних вправ і МАЄ бути присутнім для практичних вправ.
Ця різниця у вимогах випливає з того, що в концептуальних вправах учням не показують тести, тож розвʼязати вправу може бути неможливо без показаного test_code, тоді як для практичних вправ тести показано.
Це тіло команди, яку тестують. Наприклад, такий тест на Ruby:
def test_duplicate_items_uniqs_list
cart = ShoppingCart.new
cart.add(:STARIC)
cart.add(:MEDNEW)
cart.add(:MEDNEW)
assert_equal 'Newspaper, Rice', cart.items_list
end
має повернути таке значення test_code:
"cart = ShoppingCart.new
cart.add(:STARIC)
cart.add(:MEDNEW)
cart.add(:MEDNEW)
assert_equal 'Newspaper, Rice', cart.items_list"
(з переносами рядків, заміненими на \n, щоб JSON був валідним).
ключ:
status, тип:string, наявність: обовʼязкова
версія: 2, 3
Дійсними є такі статуси для кожного тесту:
pass: тест пройденоfail: тест не пройденоerror: тест завершився з помилкою, тобто не повернув значенняключ:
message, тип:string, наявність: обовʼязкова, якщоstatusмає значенняfailабоerror
версія: 2, 3
Ключ message для кожного тесту використовують, щоб повернути результати тесту зі status fail або error. Він має бути якомога зручнішим для читання. Усе, що тут написано, буде показано учневі, коли його тест не проходить. Якщо немає повідомлення про невдачу тесту чи повідомлення про помилку, або встановіть значення null, або взагалі пропустіть ключ. Тут також дозволено виводити вивід набору тестів. Значення message не обмежене за довжиною.
ключ:
output, тип:string, наявність: необовʼязкова
версія: 2, 3
Ключ output для кожного тесту слід використовувати, щоб зберігати й виводити все, що користувач навмисно виводить для тесту.
puts у Ruby, print у Python або Debug.WriteLine у C#), або надати метод, яким користувач може скористатися (наприклад, тест-раннер Ruby дає користувачеві глобально доступний метод debug, який той може використати й який має ті самі характеристики, що й стандартний метод puts).ключ:
task_id, тип:number, наявність: необовʼязкова
версія: 3
Привʼяжіть тест до конкретного завдання через ідентифікатор завдання, тобто число на початку заголовка завдання. Привʼязуйте тест до завдання лише тоді, коли його можна привʼязати рівно до одного завдання.
Наразі лише концептуальні вправи мають чітко визначені завдання, до яких можна привʼязати тести, але в майбутньому це може змінитися.
Наприклад, розгляньмо такий файл instructions.md:
# Instructions
You're going to write some code to help Lucian cook an exquisite lasagna from his favorite cook book.
## 1. Define the expected oven time in minutes
...
## 2. Calculate the remaining oven time in minutes
...
Ці інструкції визначають два завдання:
Тоді файл results.json міг би містити такий запис:
{
"name": "Expected oven time in minutes",
"status": "pass",
"task_id": 1,
"test_code": "Assert.Equal(40, Lasagna.ExpectedMinutesInOven());"
}
Тепер цей тест привʼязано до першого завдання: «Визначити очікуваний час у печі в хвилинах». Зауважте, що назва не мусить збігатися з описом завдання.
Треки можуть реалізувати це різними способами:
.meta/config.json вправи) і додавати цю інформацію до згенерованого файлу results.json.Ось приклади того, як може мати вигляд валідний файл results.json для різних версій:
{
"version": 1,
"status": "fail",
"message": "Failed: test_answer\nExpected: 42, actual: 3"
}
{
"version": 2,
"status": "fail",
"message": null,
"tests": [
{
"name": "Test that the thing works",
"status": "fail",
"message": "Expected 42 but got 123123",
"output": "Debugging information output by the user",
"test_code": "assert_equal 42, answerToTheUltimateQuestion()"
}
]
}
{
"version": 3,
"status": "fail",
"message": null,
"tests": [
{
"name": "Test that the thing works",
"status": "fail",
"message": "Expected 42 but got 123123",
"output": "Debugging information output by the user",
"test_code": "assert_equal 42, answerToTheUltimateQuestion()",
"task_id": 1
}
]
}
Коли рішення учня не проходить тест, має показуватися щось таке:
Test Code:
<test_code>
Test Result:
<message>
Коли рішення проходить тест, має показуватися щось таке:
Test Code:
<test_code>
Усі дороги ведуть до Риму, і жодного припису, як саме цього досягти, немає. Досі застосовували кілька підходів: