I've been using Boost.Test so far but am now looking into using BDD with Catch instead, but I have some trouble figuring out a nice way of handling exceptions. Say I've got a test like this:
SCENARIO("connection handling", "[network]") {
boost::asio::io_service io;
GIVEN("a connection that should fail") {
connection::ptr conn = connection::create(new fake_provider<connection_refused>(io));
WHEN("trying to connect") {
conn->connect("localhost", 1);
THEN("connection was refused") {
some stuff to verify exception code
REQUIRE(conn->connected() == false);
}
}
}
}
Now I'm wondering how to handle the fact that connect() will throw an exception in a nice way. I figure I could save and store the exception in a try-catch and verify under THEN, but that doesn't seem very nice. In my Boost.Test testcases I did this:
bool error_is_connection_refused(boost::system::system_error ex) {
return ex.code() == boost::system::errc::connection_refused;
}
BOOST_AUTO_TEST_CASE(connect)
{
connection::ptr conn_refuse = connection::create(new fake_provider<connection_refused>(*io_ptr));
BOOST_REQUIRE_EXCEPTION(conn_refuse->connect("localhost", 1),
boost::system::system_error,
error_is_connection_refused);
BOOST_REQUIRE_EQUAL(conn_refuse->connected(), false);
}
But that doesn't seem very BDD. How do people usually handle exception throwing code when using BDD testing?
I'm a bit late to this as I've only just noticed the catch-unit-test tag :-)
Currently you can do:
REQUIRE_THROWS( <expr> );
or to test for a specific exception type:
REQUIRE_THROWS_AS( <type>, <expr> );
If you want to verify the contents of the exception message... there's not currently a way to do that without catching it yourself. That's a feature I've considered adding, though.
This is how to verify exception content as suggested by philsquared
#include <stdexcept>
#include "catch.hpp"
void my_func(double v)
{
// ...
}
TEST_CASE("wrong params", "[tag]") {
SECTION("wrong rate") {
try {
my_func(1.1); // must be in range [0..1]
REQUIRE_FALSE("must raise issue about rate");
}
catch(const std::invalid_argument& e) {
std::string str (e.what());
std::string str2 ("rate");
REQUIRE_FALSE(str.find(str2) == std::string::npos);
}
}
}
Related
I thought I would do a little digging about cataching exceptions.
According to this question (C++ catching all exceptions) one of the answers states:
[catch(...)] will catch all C++ exceptions, but it should be considered bad design.
At the moment I have used this approach:
CPTSDatabase::~CPTSDatabase()
{
try
{
CloseDatabase();
}
catch(...)
{
}
}
void CPTSDatabase::CloseDatabase()
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
I thought that this was the correct way because when I trace into CDatabase::Close() it does something similar:
// Disconnect connection
void CDatabase::Close()
{
ASSERT_VALID(this);
// Close any open recordsets
AfxLockGlobals(CRIT_ODBC);
TRY
{
while (!m_listRecordsets.IsEmpty())
{
CRecordset* pSet = (CRecordset*)m_listRecordsets.GetHead();
pSet->Close(); // will implicitly remove from list
pSet->m_pDatabase = NULL;
}
}
CATCH_ALL(e)
{
AfxUnlockGlobals(CRIT_ODBC);
THROW_LAST();
}
END_CATCH_ALL
AfxUnlockGlobals(CRIT_ODBC);
if (m_hdbc != SQL_NULL_HDBC)
{
RETCODE nRetCode;
AFX_SQL_SYNC(::SQLDisconnect(m_hdbc));
AFX_SQL_SYNC(::SQLFreeConnect(m_hdbc));
m_hdbc = SQL_NULL_HDBC;
_AFX_DB_STATE* pDbState = _afxDbState;
AfxLockGlobals(CRIT_ODBC);
ASSERT(pDbState->m_nAllocatedConnections != 0);
pDbState->m_nAllocatedConnections--;
AfxUnlockGlobals(CRIT_ODBC);
}
}
And the CDatabase::Close documentation does not even state anything about exceptions being thrown.
The linked answer does state:
You can use c++11's new current_exception mechanism.
It is not clear if we can use this approach given the CDatabase class we are using.
Since CDatabase::Close() is using THROW_LAST to throw CDBException, you have to use catch (CDBException* e). Even if you are not handling it, you still have to Delete the error. You might as well do this when CDatabase methods are called directly:
void CPTSDatabase::CloseDatabase()
{
try
{
if (m_dbDatabase.IsOpen())
m_dbDatabase.Close();
}
catch (CDBException* e)
{
//TRACE(L"DB error: " + e->m_strError);
e->Delete();
}
}
Or use
CPTSDatabase::~CPTSDatabase()
{
try { CloseDatabase(); }
catch (CDBException* e) { e->Delete(); }
catch(...) {}
}
Because in this code it's not clear where the exceptions are coming from. catch(...) {} will deal with other exceptions. In general catch(...) {} is not recommended because it doesn't give useful information, it just says "something went wrong..."
Use Standard Library exceptions only if you are adding throw in your own code, or when using std functions. Example:
try { std::stoi("wrong argument"); }
catch (const std::exception& e) { TRACE("%s\n", e.what()); }
try { throw 123; }
catch (int i) { TRACE("%d\n", i); }
I have the following code which returns ERROR in many lines:
bool func()
{
if (acondition)
{
return 0;
}
return 1;
}
int cmdfun()
{
other_funcs;
if (func()) return ERROR#NUMBER;
other_funcs;
if (func()) return ERROR#NUMBER;
}
But I found its becoming longer and longer. How can I encapsulate return ERROR#NUMBER into func() also? Or any way to encapsulate if (func()) return ERROR; into another independent function?
You can't really achieve this using return on its own.
But you could throw an exception in func which will bubble up the call stack, in the way you seem to want program control to:
struct myexception{}; /*ToDo - inherit from std::exception?*/
bool func()
{
if (acondition){
return 0; /*normal behaviour, perhaps make `func` void if not needed?*/
}
throw myexception();
}
cmdfun then takes the form:
int cmdfun()
{
other_funcs;
func();
other_funcs;
func();
/* don't forget to return something*/
}
Finally, make sure you catch the exception in the caller to cmdfun.
As I said it is not an exception and cannot be handled by std::exception, it is just an error message and ERROR#NUMBER is just another macro. And I cannot access to the caller to cmdfun(). So unable to adopt the first answer. But after asked someone else, it is possible to encapsulate returns and save time when typing them, though it's not recommended, but in this particular case, I can use macro. A complete example is given below:
#include <iostream>
using namespace std;
#define CHECK_VEC(acondition)\
if(checkcondition(acondition)) return -1;
bool checkcondition(bool acondition)
{
if (acondition) return 1;
return 0;
}
int fun_called_by_main()
{
int a = 5 + 4;
bool acondition = a;
CHECK_VEC(acondition);
return 1;
}
int main()
{
int a = fun_called_by_main();
cout << a << endl;
cin.get();
return 0;
}
If I understood corectly your question, you are asking for an 'error reporter' for your own errors. There are 2 solutions for 2 separate cases:
Case 1 - you still want to use a return statement to make an 'error reporter':
To do this, you'll have to make another function or just learn how to use goto. However, you don't need to - your function returns a boolean(bool) - which means you only have 2 possible results: 0 (False) and 1 (True)
bool func()
{
if (acondition)
{
return (bool)0; // False (no error)
}
return (bool)1; // True (error)
// Note: I used (bool)0 and (bool)1 because it is
// more correct because your returning type is bool.
}
void errorcase(bool trueorfalse)
{
switch(trueorfalse)
{
case False:
... // your code (func() returned 0)
break;
default:
... // your code (func() returned 1)
break;
// Note that you will not need to check if an error occurred every time.
}
return;
}
int cmdfun()
{
... // your code
errorcase(func());
... // again - your code
return 0; // I suppouse that you will return 0...
}
But I think that the second case is more interesting (unfortunetly it is also preety hard to understand as a beginner and the first solution might be a lot easier for you):
Case 2 - you decided to do it somehow else - that's by learning throw and catch - I won't repeat the answer because it is already given: #Bathsheba answered preety good...
How can I print "Error" while the JTextfield is empty
save.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
String sn =jX1.getText();
if (sn==null){
System.out.println("Error");
System.out.println("T");
}
Thanks
Try using a fail-safe method. Also Expanding on the comments, you should be logging data, in a better format. Java hosts a huge array of different way to log certain data. look here
As for your error handling, try-catch-finally. This isn't tested code. Let me know if you run into any issues, documentation on try-catch and other statements here or here
public static void main(String[] args) {
while (String sn == null)
try {
String sn = JX1.getText();
} catch (Exception ex) {
System.out.println("Exception thrown!");
} finally {
if (sn != null) {
System.out.println("Closing PrintWriter");
sn.close();
} else {
System.out.println("PrintWriter not open");
}
}
I am writing up some tests for a C++ program and I would like to check that my program throws certain types of exceptions when given certain inputs. I have seen that this is doable using external libraries such as googletest, but I would like to know how this was implemented.
I would like to separate the test data from the test code as much as possible. In particular, I would like something like this:
void RunTests(InputList inputs) {
for (int i = 0; i < inputs.length; i++) {
if (FunctionIAmTesting(inputs[i].value) has the expected exception behavior) {
// Pass
} else {
// Fail
}
}
}
InputList inputs = InputList({
Input(5), // no exception when 5 is an input
Input<MyExceptionClass>(0), // MyExceptionClass thrown when 0 is an input
Input<MyOtherExceptionClass>(-1) // MyOtherExceptionClass thrown when -1 is an input
});
RunTests(inputs);
If you know what the type of exception you are looking for then you can target an exception of that type in the catch () statement.
try {
// Test code.
// Unexpected success
std::cerr << "Expected a RelevantException to be thrown." << std::endl;
}
catch (RelevantException& e)
{
// Expected exception, continue.
}
catch (...) // Catch all
{
// Unexpected exception
std::cerr << "Unexpected exception encountered, expected "
"RelevantException." << std::endl;
}
A several years back I wrote some simple library for "mocking" objects. And my goal was to check everything related to function calls. In the tests I wrote something like that:
MyMockedObject my;
mock::expect(my, "foo").in(10).out(20).returns(30);
mock::expect(my, "bar").throws(logic_error("bar failed"));
int v;
// test that my::baz() invokes my.foo(10, v)
// then my.bar which fails with the exception
my.baz();
Your task seems to be a little bit easier. All that you need is a way how to describe your expectations and some hack in the test runner to verify them at the end of a test (accordingly to the input). Your expectations are exceptions, just construct them somehow and associate with the input. In your example you did a half part of your work.
typedef std::map<Input, Exception> Expectations;
typedef std::pair<Input, Exception> Expectation;
// somewhere before the tests
expectations.insert(make_pair(Input(5)), NoThrowAnything);
expectations.insert(make_pair(Input(0)), MyException("some message"));
expectations.insert(make_pair(Input(-1)), MyOtherException("another message"));
void run_test(const Expectation& expect)
{
try {
// run the real test here based on Input (expect.first)
check_expectation(expect);
} catch (const Exception& ex) {
check_expectation(expect, ex);
}
}
void run_all_tests(const Expectations& expects)
{
for (e : expects) {
try {
run_test(e);
} catch (const ExpectationException ex) {
// failed expectation
}
}
}
void check_expectation(const Expectation& expect)
{
if (expect.second != NoThrowAnything) {
throw ExpectationFailure(expect);
}
}
void check_expectation(const Expectation& expect, const Exception& ex)
{
if (expect.second != ex) {
throw ExpectationMismatch(expect, ex);
}
}
My program waits for user input, and when appropriate, will process it. I need to check the user input to make sure it fulfils certain criteria, and if it doesn't fulfil all of those criteria it will be rejected.
Pseudo-code is something like:
if (fulfills_condition_1)
{
if (fulfills_condition_2)
{
if (fulfills_condition_3)
{
/*process message*/
}
else
cout << error_message_3; //where error_message_1 is a string detailing error
}
else
cout << error_message_2; //where error_message_2 is a string detailing error
}
else
cout << error_message_1; //where error_message_3 is a string detailing error
There is the possibility that the number of these conditions could increase, and I was wondering if there was a neater way to represent this using a switch or something like that instead of lots of cascading if statements.
I know there is the possibility of using
if (fulfills_condition_1 && fulfills_condition_2 && fulfills_condition_3)
/*process message*/
else
error_message; //"this message is not formatted properly"
but this is less useful than the first, and does not say where the issue is.
The conditions can roughly be arranged in increasing importance i.e. checking for condition_1 is more important than checking for condition_3, so the if statements do work - but is there a better way in general for doing this?
How about
if (!fulfills_condition_1) throw BadInput(error_message_1);
if (!fulfills_condition_2) throw BadInput(error_message_2);
if (!fulfills_condition_3) throw BadInput(error_message_3);
/* process message */
Then your exception handler can report the error message, and retry or abort as appropriate.
If what bothers you are the cascading ifs, you could go for one of the following:
Using a boolean:
bool is_valid = true;
string error = "";
if (!condition_one) {
error = "my error";
is_valid = false;
}
if (is_valid && !condition_two) {
...
}
...
if (!is_valid) {
cout << error;
} else {
// Do something with valid input
}
Using exceptions:
try {
if (!condition_one) {
throw runtime_error("my error");
}
if (!condition_two) {
...
}
...
} catch (...) {
// Handle your exception here
}
I suggest you can use "early return" technique:
if (!fulfills_condition_1)
// error msg here.
return;
// fulfills_condition1 holds here.
if (!fulfills_condition_2)
// error msg here.
return;
// Both conditon1 and condition2 hold here.
if (!fulfills_condition_3)
// error msg here.
return.
If this was going to be reused in a few places, I would make a DSL:
Validator inputType1Validator =
Validator.should(fulfill_condition_1, error_message_1)
.and(fulfill_condition_2, error_message_2)
.and(fulfill_condition_3, error_message_3)
inputType1Validator.check(input);