/// Puts a result into the database. /// /// \pre The result has not been put yet. /// \post The result is stored into the database with a new identifier. /// /// \param result The result to put. /// \param test_case_id The test case this result corresponds to. /// \param start_time The time when the test started to run. /// \param end_time The time when the test finished running. /// /// \return The identifier of the inserted result. /// /// \throw error If there is any problem when talking to the database. int64_t store::write_transaction::put_result(const model::test_result& result, const int64_t test_case_id, const datetime::timestamp& start_time, const datetime::timestamp& end_time) { try { sqlite::statement stmt = _pimpl->_db.create_statement( "INSERT INTO test_results (test_case_id, result_type, " " result_reason, start_time, " " end_time) " "VALUES (:test_case_id, :result_type, :result_reason, " " :start_time, :end_time)"); stmt.bind(":test_case_id", test_case_id); store::bind_test_result_type(stmt, ":result_type", result.type()); if (result.reason().empty()) stmt.bind(":result_reason", sqlite::null()); else stmt.bind(":result_reason", result.reason()); store::bind_timestamp(stmt, ":start_time", start_time); store::bind_timestamp(stmt, ":end_time", end_time); stmt.step_without_results(); const int64_t result_id = _pimpl->_db.last_insert_rowid(); return result_id; } catch (const sqlite::error& e) { throw error(e.what()); } }
/// Callback executed when a test results is found. /// /// \param iter Container for the test result's data. void drivers::report_junit_hooks::got_result(store::results_iterator& iter) { const model::test_result result = iter.result(); _output << F("<testcase classname=\"%s\" name=\"%s\" time=\"%s\">\n") % text::escape_xml(junit_classname(*iter.test_program())) % text::escape_xml(iter.test_case_name()) % junit_duration(iter.end_time() - iter.start_time()); std::string stderr_contents; switch (result.type()) { case model::test_result_failed: _output << F("<failure message=\"%s\"/>\n") % text::escape_xml(result.reason()); break; case model::test_result_expected_failure: stderr_contents += ("Expected failure result details\n" "-------------------------------\n" "\n" + result.reason() + "\n" "\n"); break; case model::test_result_passed: // Passed results have no status nodes. break; case model::test_result_skipped: _output << "<skipped/>\n"; stderr_contents += ("Skipped result details\n" "----------------------\n" "\n" + result.reason() + "\n" "\n"); break; default: _output << F("<error message=\"%s\"/>\n") % text::escape_xml(result.reason()); } const std::string stdout_contents = iter.stdout_contents(); if (!stdout_contents.empty()) { _output << F("<system-out>%s</system-out>\n") % text::escape_xml(stdout_contents); } { const model::test_case& test_case = iter.test_program()->find( iter.test_case_name()); stderr_contents += junit_metadata(test_case.get_metadata()); } stderr_contents += junit_timing(iter.start_time(), iter.end_time()); { stderr_contents += junit_stderr_header; const std::string real_stderr_contents = iter.stderr_contents(); if (real_stderr_contents.empty()) { stderr_contents += "<EMPTY>\n"; } else { stderr_contents += real_stderr_contents; } } _output << "<system-err>" << text::escape_xml(stderr_contents) << "</system-err>\n"; _output << "</testcase>\n"; }