JUnit5 ParameterizedTest - Differentiate CsvSource Parameter Sets - unit-testing

PROBLEM: The same test method is used for different data. Depending on input data, test method body should expect 'equals' or 'not equal' in asserts.
RESEARCH: #ParameterizedTest allows using #CsvSource as test method input data:
#ParameterizedTest
#CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
void testWithCsvSource(String first, int second) {
assertNotNull(first);
assertNotEquals(0, second);
}
This could be achieved by two opposite test methods, but their code would be much similar.
QUESTION: How to identify in the method body, which set of CsvSource input parameters is currently used?

You can create two test methods with different CsvSource and then delegate to a common test method.
#ParameterizedTest
#CsvSource({ "foo, 1", "bar, 2", "'baz, qux', 3" })
void testWithCsvSource(String first, int second) {
internalTest(first, second);
}
#ParameterizedTest
#CsvSource({ "foo2, 1", "bar2, 2", "'baz2, qux2', 3" })
void testWithCsvSource2(String first, int second) {
internalTest(first, second);
}
private void internalTest(String first, int second) {
assertNotNull(first);
assertNotEquals(0, second);
}

An optimal solution so far is adding index as first parameter for each set:
#ParameterizedTest
#CsvSource({
"0, foo, 11", // Expected to be valid.
"1, bar, 22", // Expected to be invalid.
"2, 'baz, qux', 33" }) // Expected to be invalid.
void testWithCsvSource(
int parametersIndex,
String first,
int second) {
Assertions.assertEquals(
second.validate(),
parametersIndex == 0); // Expected true for 0 index parameters only.
}

Related

Run a repeated test reporting as different tests

I'd like to unit test a function with a set of different inputs and expected outputs.
My function is irrelevant thus I'll instead use an example function which counts english words with the following candidate implementation :
int countEnglishWords( const std::string& text )
{
return 5;
};
The following would be the set of test data. The end of the data is marked by an element with the word "END".
struct TestData {
std::string text;
int englishWords;
};
struct TestData data[] = // Mark end with "END"
{
{ "The car is very fast", 5 },
{ "El coche es muy rapido", 0 },
{ "The rain in Spain stays mainly in the plain", 9},
{ "XXXXX OOOOO TTTT", 0},
{ "Yes Si No No", 3},
{ "I have a cheerful live", 5},
{ "END", 0}
};
I could easily write 6 test cases and I would get the result I want. But this is not maintainable, since any further test added to the test cases would not be tested, it would require another test case to be written, which would be just boiler plate. Thus I've written a single test case which loops through all the test data like this :
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
class cppUnit_test: public CppUnit::TestFixture
{
private:
CPPUNIT_TEST_SUITE (cppUnit_test);
CPPUNIT_TEST(myTest);
CPPUNIT_TEST_SUITE_END();
public:
void myTest();
};
void cppUnit_test::myTest()
{
TestData* p = data;
while ( p->text != "END")
{
std::stringstream ss;
ss << "Text=\"" << p->text << "\" Counted=" <<
countEnglishWords(p->text) << " Expected=" << p->englishWords;
CPPUNIT_ASSERT_MESSAGE( ss.str().c_str(),
countEnglishWords(p->text) == p->englishWords );
++p;
}
}
int main()
{
CPPUNIT_TEST_SUITE_REGISTRATION (cppUnit_test);
CppUnit::Test *suite =
CppUnit::TestFactoryRegistry::getRegistry().makeTest();
CppUnit::TextUi::TestRunner runner;
runner.addTest(suite);
runner.run();
return 0;
}
The problem is that the previous code runs through the 1st test fine and also detects the error in the 2nd test but after that it stops testing. And the report is :
!!!FAILURES!!!
Test Results:
Run: 1 Failures: 1 Errors: 0
While the result I'd like to get is :
!!!FAILURES!!!
Test Results:
Run: 6 Failures: 4 Errors: 0
As I already mentioned in the comment cppunit 1.14.0 can support your use case.
I you want to reference an external array the quickest way is to use CPPUNIT_TEST_PARAMETERIZED. This macro expects two parameters: first similar to CPPUNIT_TEST a test method and then as a second parameter an iteratable.
Based on your code it would look like:
CPPUNIT_TEST_PARAMETERIZED(myTest, aData);
Now we need to adapt your myTest function a little bit.
void cppUnit_test::myTest(const TestData& data)
{
std::stringstream ss;
ss << "Text=\"" << data.text << "\" Counted=" <<
countEnglishWords(data.text) << " Expected=" << data.englishWords;
bool b = countEnglishWords(data.text) == data.englishWords;
std::string a = ss.str();
CPPUNIT_ASSERT_MESSAGE( a,
b);
}
Finally as the framework needs a way to report which test failed it expects that it can print the parameter that is passed to the test function. In this case the easiest way is to add a simple operator<< overload.
std::ostream& operator<<(std::ostream& strm, const TestData& data)
{
strm << data.text;
return strm;
}
If you combine these pieces you should quickly get a generic solution that will allow you to add as much data to your data array as you want without adapting the test code.
CPPUNIT_TEST_SUITE(TestSuite);
CPPUNIT_TEST_PARAMETERIZED(testMethod, {1, 2, 3, 4});
CPPUNIT_TEST_SUITE_END();
void testMethod(int /*val*/)
{
}

ARDUINO LCD: Generate a navigation menu by reading an array

I'm trying to create the menu in a display linked to arduino by inserting the elements inside an array like the one below in pseudo-code (javascript).
var menu = {
title: 'main menu',
item: [{
txt: 'item1',
action: function() { // function that will be performed in case such an element is activated
// my code
}
},
{
txt: 'item2',
item: [{
txt: 'item4',
action: function() {
// my code
}
},
{
txt: 'item5',
action: function() {
// my code
}
}
],
action: function() {
// my code
}
},
{
txt: 'item3',
action: function() {
// my code
}
}
]
};
Later this array will be read by a recursive function that will print the menu on the liquid crystal display.
How can i do this to arduino?
Using javascript seems like an operation at anyone's reach, but can you do the same in C / C ++?
Thanks to everyone in advance for the help!
Create a struct with an string, pointer to a function and pointers to the next and previous struct
the string is the text that will be displayed for the option, the function is the function called if the user click the item, and the pointers give you the previous and next itens if the user go up or down
example:
in the header file:
const struct item
{
const char name[16];
void (*func)(void); // Pointer to the item function
const struct item * prev; // Pointer to the previous
const struct item * next; // Pointer to the next
};
in the c file:
const struct item item_ON =
{
" 1 On",
fcn_item_turn_on,
&item_OFF,
&item_PARTIAL
};
const struct item item_PARTIAL =
{
" 2 Partial",
fcn_item_partial,
&item_ON,
&item_OFF
};
const struct item item_OFF =
{
" 3 Off",
fcn_item_turn_off,
&item_PARTIAL,
&item_ON
};
then:
void menu_show()
{
putrsXLCD((rom char *)(*ptr_item).name); // or the LCD print function in your code
}
void menu_inc() {
ptr_item = (*ptr_item).prev;
menu_show();
}
void menu_dec() {
ptr_item = (*ptr_item).next;
menu_show();
}
void menu_fwd() {
(*ptr_item).func(); // execute item function
}
don't forget to initialize the ptr_item with the first item:
ptr_item = &item_ON;
From the looks of it you are trying to create a hierarchical menu system. (As the JSON Object is not an array, but more akin to a tree.)
C++ would probably be easier to implement in because of the STL, I'm not sure on your experience but I'll give a general layout. Design-wise anyways.
#include <functional>
#include <vector>
class MenuTreeNode {
std::string title;
std::vector<MenuTreeNode> children;
std::function<void(int)> action;
public:
MenuTreeNode(const std::string& title, std::function<void(int)> action = {});
// ^ Construct the node, with the action item being optional.
// {} is just an empty function block.
/*
** You can construct with a lambda function, which are pretty useful.
*/
void addChild(MenuTreeNode&& childNode); // append a node to the child array.
void displayStuff() {
// However you display stuff to Arduino...
for (auto& child : this->children) {
child.displayStuff();
}
this->action(); // Call the action.
}
};
I hope that gives you some guidance. The older answer in C is good however doesn't allow for child items that you have in your JSON struct. This might be easier to work with IMO.

Arduino compile error while using reference to a struct in another struct

I'm on prgramming a menu for an 16x2 LCD for a small arduino project.
I'm nearly finished, but i do not understand the last small issue.
The following (simplified) code generates the problem:
int var1=0;
int var2=0;
typedef struct {
unsigned int item_value;
char item_name[17];
} Select_Item;
typedef struct {
char item_name[17];
int* variable;
Select_Item* list;
} Menu_Item;
Select_Item sel_one = { 0, "Selection 1" };
Select_Item sel_two = { 1, "Selection 2" };
Select_Item* sel_list[2] = { &sel_one, &sel_two };
Menu_Item menu_item1 = { "Item 1", &var1, NULL };
Menu_Item menu_item2 = { "Item 2", &var2, &sel_list };
Menu_Item* menu_list[2] = { &menu_item1, &menu_item2 };
It ends up with the following error:
sketch_feb08a.ino:24:53: error: cannot convert 'Select_Item* (*)[2]' to 'Select_Item*' in initialization
In the code i'm accessing the values from the variables and show it in the display and once edited i can write it back to the variable. That was not the problem as long as i had just numbers to show/edit.
Now for ease of use i wanted to add some kind of option menu, where the user can choose from the options. The item_name should be displayed, instead of the raw value, but of course the item_value should be used behind the scene.
That is why i introduced the Select_Item struct.
I don't understand the error message. What's wrong here?
I think what you're trying to do is something like this:
int var1=0;
int var2=0;
typedef struct {
unsigned int item_value;
char item_name[17];
} Select_Item;
typedef struct {
char item_name[17];
int* variable;
Select_Item* list;
} Menu_Item;
Select_Item sel_one = { 0, "Selection 1" };
Select_Item sel_two = { 1, "Selection 2" };
Select_Item sel_three = {2, "Selection 3" };
Select_Item sel_four = {3, "Selection 4" };
Select_Item* sel_list_1[] = { &sel_one, &sel_two };
Select_Item* sel_list_2[] = { &sel_three, &sel_four };
Menu_Item menu_item1 = { "Item 1", &var1, sel_list_1[0] }; // Note the syntax here
Menu_Item menu_item2 = { "Item 2", &var2, sel_list_2[0] }; // Note the syntax here
Menu_Item* menu_list[2] = { &menu_item1, &menu_item2 };
// Added for testing
int main()
{
printf("Menu item '%s'\n", menu_list[0]->item_name);
printf(" %d - %s\n", menu_list[0]->list[0].item_value, menu_list[0]->list[0].item_name);
printf(" %d - %s\n", menu_list[0]->list[1].item_value, menu_list[0]->list[1].item_name);
printf("Menu item '%s'\n", menu_list[1]->item_name);
printf(" %d - %s\n", menu_list[1]->list[0].item_value, menu_list[1]->list[0].item_name);
printf(" %d - %s\n", menu_list[1]->list[1].item_value, menu_list[1]->list[1].item_name);
return 0;
}
Note the syntax for the initialization of menu_item1 and menu_item2.
I added main() just so I could test this with a normal C compiler (since I don't have an Arduino with an LCD handy). The output from my testing looks like this:
Menu Item 'Item 1'
0 - Selection 1
1 - Selection 2
Menu Item 'Item 2'
3 - Selection 3
4 - Selection 4
And I think that's what you're trying to achieve with your data structures. You'll just need to adapt this to your Arduino code and use these data structures to manage the menu selections on your LCD.

Boost multi_index_container partial index search based on results of partial_index_search

To illustrate my question, I copied below code from the "Phonebook" example of Boost help doc.
struct phonebook_entry
{
std::string family_name;
std::string given_name;
std::string ssn;
std::string phone_number;
}
And I can do a partial search as below
// search for Dorothea White's number
phonebook::iterator it=pb.find(boost::make_tuple("White","Dorothea"));
However, if I need to count the number of people who's family name is "White", then go on to find how many "White"'s have "Dorothea"' as their given name, then what's the best way to do it?
I think I can do two partial queries, with pb.find(boost::make_tuple("White") and pb.find(boost::make_tuple("White","Dorothea"). But I am concerned whether this will cause a performance issue? Since the second query has no knowledge of the first query and just search the whole container.
Does Boost provide something like below:
std::pair<iterator,iterator> partialResults=pb.equal_range("White");
std::pair<iterator, iterator> partialOfPartial=pb.equal_range("Dorothea", partialResults);
Or is there any smarter way to do this? Not only from convenience point of view, but for performance.
Because the phonebook has a composite key, it is sorted on given names within last names. So you can call the regular std::equal_range on the first search result to match a dummy phonebook_entry that has only "Dorothy" defined:
int main()
{
phonebook pb; // no initializer_list support for multi_index_container yet
pb.insert({ "White", "Dorothy", "1" });
pb.insert({ "Black", "Dorothy", "2" });
pb.insert({ "White", "John", "3" });
pb.insert({ "Black", "John", "4" });
pb.insert({ "White", "Dorothy", "5" });
auto const w = pb.equal_range("White");
auto const d = phonebook_entry{"", "Dorothy", ""};
auto const wd = std::equal_range(w.first, w.second, d, [](phonebook_entry const& lhs, phonebook_entry const& rhs) {
return lhs.given_name < rhs.given_name;
});
std::for_each(wd.first, wd.second, [](phonebook_entry const& pbe) {
std::cout << pbe.phone_number << "\n";
});
}
Live example that will print for "White, Dorothy" the phone numbers 1 and 5.

Parameterized JUnit tests with non-primitive parameters?

There is a nice possibility to run JUnit test with parameters where the same test method is executed multiple times with different data as described here: http://junit.org/apidocs/org/junit/runners/Parameterized.html
Unfortunately, it only seems possible to use primitive parameters or Strings, but not objects. Is there any workaround known for this?
The type of the data() method in the use of the #Parameters annotation is List<Object[]>, so you can put in any object.
To pass in, e.g., a Money object, your array to be converted to a list would be:
{ { new Money(26, "CHF") },
{ new Money(12, "USD") } }
The constructor of the test class should take a Money object as argument then.
recently i started zohhak project. it lets you write:
#TestWith({
"25 USD, 7",
"38 GBP, 2",
"null, 0"
})
public void testMethod(Money money, int anotherParameter) {
...
}
Using object is also possible using Junit #Parameters.
Example:-
#RunWith(Parameterized.class)
public class TestParameter {
#Parameter(value=0)
public int expected;
#Parameter(value=1)
public int first;
#Parameter(value=2)
public int second;
private Calculator myCalculator;
#Parameters(name = "Test : {index} : add({1}+{2})= Expecting {0}")//name will be shared among all tests
public static Collection addNumbers() {
return Arrays.asList(new Integer[][] { { 3, 2, 1 }, { 5, 2, 3 }, { 9, 8, 1 }, { 200, 50, 150 } });
}
#Test
public void testAddWithParameters() {
myCalculator = new Calculator();
System.out.println(first + " & " + second + " Expected = " + expected);
assertEquals(expected, myCalculator.Add(first, second));
}
}