Test Anything Protocol - TAP ですが、なんとなく C++ で実装してみました。
tap.hpp
#ifndef TAP_HPP_526c07e9e0a11dc15e7838c85f7e46780782392d
#define TAP_HPP_526c07e9e0a11dc15e7838c85f7e46780782392d
#include <string>
#include <iostream>
namespace tap {
size_t tests__ = 0;
size_t numof_tested__ = 0;
void tests(size_t n) {
tests__ = n;
std::cout << "1.." << n << std::endl;
}
void ok_notok__(bool is_ok, const std::string& name) {
std::cout << (is_ok ? "ok " : "not ok ") << ++numof_tested__ << " - " << name << std::endl;
}
template <typename T, typename U> void is__(const std::string& file, size_t line,
T got, U expected, const std::string& name = "") {
if (got != expected) {
ok_notok__(false, name);
std::cerr
<< "# Failed test '" << name << "'\n"
<< "# at " << file << " line " << line << ".\n"
<< "# got: '" << got << "'\n"
<< "# expected: '" << expected << "'" << std::endl;
} else {
ok_notok__(true, name);
}
}
template <typename T, typename U> void isnt__(const std::string& file, size_t line,
T got, U expected, const std::string& name = "") {
if (got == expected) {
ok_notok__(false, name);
std::cerr
<< "# Failed test '" << name << "'\n"
<< "# at " << file << " line " << line << ".\n"
<< "# '" << got << "'\n"
<< "# ne\n"
<< "# '" << expected << "'" << std::endl;
} else {
ok_notok__(true, name);
}
}
void fail__(const std::string& file, size_t line, const std::string& name) {
ok_notok__(false, name);
std::cerr
<< "# Failed test '" << name << "'\n"
<< "# at " << file << " line " << line << std::endl;
}
void diag__(const std::string& d) {
std::cerr << "# " << d << std::endl;
}
}
#define is(g, e, n) tap::is__(__FILE__, __LINE__, (g), (e), (n))
#define isnt(g, e, n) tap::isnt__(__FILE__, __LINE__, (g), (e), (n))
#define fail(n) tap::fail__(__FILE__, __LINE__, (n))
#define diag(d) tap::diag__((d))
#endif
こんな風に使います。
#include "tap.hpp"
#include <iostream>
#include <string>
using namespace std;
int main(void) {
tap::tests(6);
is(1, 3, "hoge");
string hoge = "hoge";
string geho = "hoge";
isnt(hoge, geho, "hoge");
isnt(0, 0, "hoge");
fail("asdf");
is(0, 0, "asf");
diag("asdf");
return 0;
}
実行すると…。
% g++ -Wall -Wextra test.cpp && ./a.out
1..6
not ok 1 - hoge
# Failed test 'hoge'
# at test.cpp line 10.
# got: '1'
# expected: '3'
not ok 2 - hoge
# Failed test 'hoge'
# at test.cpp line 13.
# 'hoge'
# ne
# 'hoge'
not ok 3 - hoge
# Failed test 'hoge'
# at test.cpp line 14.
# '0'
# ne
# '0'
not ok 4 - asdf
# Failed test 'asdf'
# at test.cpp line 15
ok 5 - asf
# asdf
a.t を用意して…。
#!/bin/sh
./a.out
% prove -v ./a.t
./a......
1..6
not ok 1 - hoge
not ok 2 - hoge
not ok 3 - hoge
not ok 4 - asdf
ok 5 - asf
# Failed test 'hoge'
# at test.cpp line 10.
# got: '1'
# expected: '3'
# Failed test 'hoge'
# at test.cpp line 13.
# 'hoge'
# ne
# 'hoge'
# Failed test 'hoge'
# at test.cpp line 14.
# '0'
# ne
# '0'
# Failed test 'asdf'
# at test.cpp line 15
# asdf
Failed 5/6 subtests
Test Summary Report
-------------------
./a.t (Wstat: 0 Tests: 5 Failed: 4)
Failed tests: 1-4
Parse errors: Bad plan. You planned 6 tests but ran 5.
Files=1, Tests=5, 0 wallclock secs ( 0.03 usr + 0.01 sys = 0.04 CPU)
Result: FAIL
[1] 3716 exit 1 prove -v ./a.t
こうなる。
freeHG にあげときました。BSL1.0 です。utils: Manifest
テストに失敗したときの戻り値を…には、まだ対応していません。