Teste de ieșire și intrarea programului
Cele mai multe provocări testează o funcție: testul o importă, o apelează și verifică rezultatul. Începătorii care nu au învățat încă despre funcții au nevoie de ceva mai simplu. Testele de ieșire rulează întregul program al cursantului, îi oferă un text la intrarea standard și compară ce a afișat — la fel cum ar face un terminal.
Când să le folosești
"Afișează Hello World", "Citește un nume și salută-l", "Afișează numerele de la 1 la 10": orice cerință în care programul este soluția. Odată ce cursantul cunoaște funcțiile, preferă testele obișnuite.
Cum funcționează un test de ieșire
Fișierul de test apelează un mic utilitar (helper) pe care DojoCode îl plasează lângă surse în timp ce rulează testele. Utilitarul pornește fișierul principal, scrie textul furnizat la intrarea sa standard, așteaptă să se termine și returnează ce a afișat, cu spațiile și liniile noi de la sfârșit eliminate. Utilitarul există doar în timpul rulării unui test — nu îl crea niciodată tu însuți.
O provocare trece la teste de ieșire de îndată ce un fișier de test referențiază utilitarul. Nu se schimbă nimic pentru provocările care nu îl folosesc.
| Șablon | Import | Apel |
|---|---|---|
| Python | from challenge.dojo_io import run | run("Ana\n") |
| Node.js / Node TS | import { run } from 'dojo-io' | run('Ana\n') |
| PHP | — (DojoIO este global) | DojoIO::run("Ana\n") |
| Ruby | — (DojoIO este global) | DojoIO.run("Ana\n") |
| Java | — (DojoIO se află în pachetul challenge) | DojoIO.run("Ana\n") |
| C# | — (DojoIO se află în spațiul de nume Challenge) | DojoIO.Run("Ana\n") |
| Go | — (DojoRun se află în pachetul main) | DojoRun(t, "Ana\n") |
| Rust | use crate::dojo_io::run; | run("Ana\n") |
| C | #include "dojo_io.h" | dojo_run("Ana\n") |
| C++ | #include "dojo_io.hpp" | dojo_run("Ana\n") |
Argumentul este textul pe care programul îl citește de la intrarea standard, câte o linie pentru fiecare valoare ("3\n4\n" pentru două numere). Pentru programele care nu citesc nimic, transmite un șir gol; majoritatea utilitarelor îți permit și să omiți argumentul, dar Go, Rust și C îl cer.
Exemplu: Salută după nume
Cursantul citește un nume și afișează Hello, <name>!. Fișierul principal preîncărcat este un schelet cu cerința într-un comentariu, iar fișierul principal este soluția: nu există un fișier de soluție separat de importat.
name = input()
print(f"Hello, {name}!")from pytest import mark as m
from challenge.dojo_io import run
@m.describe("Greet by name")
class TestGreetByName:
@m.it("greets Ana")
def test_greets_ana(self):
assert run("Ana\n") == "Hello, Ana!"
@m.it("greets Mihai Popescu")
def test_greets_mihai_popescu(self):
assert run("Mihai Popescu\n") == "Hello, Mihai Popescu!"package challenge;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class GreetByNameTest {
@Test
@DisplayName("greets Ana")
void greetsAna() {
assertEquals("Hello, Ana!", DojoIO.run("Ana\n"));
}
}#include <criterion/criterion.h>
#include "dojo_io.h"
Test(greet_by_name, greets_ana, .description = "greets Ana") {
cr_assert_str_eq(dojo_run("Ana\n"), "Hello, Ana!");
}Folosește mai multe intrări pentru fiecare comportament și păstrează unele doar în suita completă de teste, astfel încât o linie hardcoded precum print("Hello, Ana!") să nu poată trece.
Reguli pentru programele care citesc intrare
- Nu afișa un mesaj de introducere (prompt). Tot ce scrie programul la ieșirea standard face parte din comparație, așa că
Console.Write("Name: ")înainte deReadLine()face ca testul să se aștepte laName: Hello, Ana!. Singura excepție este Python: utilitarul ascunde textul transmis cătreinput("Name: "), astfel că programele Python pot afișa prompturi. - Citește linii întregi și elimină spațiile de la margini:
input(),gets.chomp,scanner.nextLine(),fgets+strcspn,std::getline,read_line+trim. Paginile de șabloane arată sintaxa idiomatică pentru fiecare limbaj. - Fiecare valoare pe propria linie. Spune-i cursantului formatul exact în descriere („prima linie conține numele”) și furnizează intrările în teste în același mod.
- Fără intrare, programul primește sfârșit de fișier (end-of-file), nu se blochează:
input()aruncăEOFError,getsreturneazănil,ReadLine()returneazănull. Un program care nu citește nimic nu este afectat.
Run versus Test
Test furnizează programului orice îi transmite testul utilitarului. Run execută doar fișierul principal, într-un terminal interactiv: cursantul vede promptul și tastează răspunsul, ca într-un terminal real, iar programul poate rula cel mult 5 minute în total, dar este oprit după 2 minute în care nu se întâmplă nimic (nicio ieșire și nicio intrare). Nu este nimic de configurat — fiecare șablon bazat pe terminal rulează în acest mod.
În editor, instrumentul run_code al asistentului AI nu poate tasta într-un terminal; în schimb, transmite intrarea ca argument stdin (câte o linie pentru fiecare valoare), astfel încât să poată încerca în continuare un program care citește intrare pentru tine.
Pentru provocările Python cu previzualizarea în browser activată, input() din previzualizare deschide în schimb propriul dialog al browserului; vezi șablonul Python.
Verificări de structură
Testele de ieșire pot verifica, de asemenea, cum este scris programul atunci când cerința impune o structură („folosește o buclă for”, „nu folosi while”). Același utilitar expune uses("for"), count("if"), defines("average") (o funcție), declares("total") (o variabilă) și altele similare. Acestea indică doar că o structură există, nu și că face ceea ce trebuie, așa că asociază-le întotdeauna cu teste de ieșire.