0

Currently, I've got a program which reads and extracts multiple pieces of data from a file, and i would like to ensure those values correctly match the expected values, I'm aware of how this should work in other programming languages such as python with lists and tuples etc, however i am unsure as to the best approach to use unit tests within C++ whilst keeping the code as minimal and efficient as possible. I've currently got multiple arrays all of which i wish to verify that they meet their expected values, so i can test the program with differing input files.

To describe this, in essence, i wish to verify the contents of e.g.

int arrayone [5] = { 11, 12, 13, 14, 15 };

are equal to { 11, 12, 13, 14, 15 }

and to complete the unit test successfully if the values are equal, and to fail if they are not equal or not in the same order. Thus, i am looking for the best method to approach this.

ashwood23
  • 83
  • 1
  • 8
  • 1
    Are you using any unit testing framework? (GoogleTest, Igloo, CppUnit)? Or you just want standard C++ answer? – Yksisarvinen Jan 17 '19 at 18:13
  • You do not need to test code such as `int arrayone [5] = { 11, 12, 13, 14, 15 };`, any more than you need to test `int x = 0;`. –  Jan 17 '19 at 18:15
  • Use `std::array` and operator == – uchar Jan 17 '19 at 18:15
  • 1
    Seems like a job for [`std::equal`](https://en.cppreference.com/w/cpp/algorithm/equal). Or you could use an [`std::array`](https://en.cppreference.com/w/cpp/container/array) instead. – François Andrieux Jan 17 '19 at 18:15
  • I'm aiming to try and do this using C++ without using other frameworks if at all possible. – ashwood23 Jan 17 '19 at 18:15
  • @ashwood23 are you trying to avoid the STL? Are you insisting upon using primitives? If so, are they guaranteed to be the same size? – Daniel Jan 17 '19 at 18:18
  • The best approach is to use the appropriate container (e.g. vector or array) and use its operator==() for comparison. – Kenny Ostrom Jan 17 '19 at 18:21

3 Answers3

6

Use a C++ std::array instead and you'll get the benefit from all the methods it exposes, like operator==:

#include <iostream>
#include <array>

int main() {
    std::array arrayone{ 11, 12, 13, 14, 15 };
    std::array facit{ 11, 12, 13, 14, 15 };

    if(arrayone==facit) {
        std::cout << "true\n";
    } else {
        std::cout << "false\n";
    }
}

Or for C++11 and C++14:

std::array<int, 5> arrayone{ 11, 12, 13, 14, 15 };
std::array<int, 5> facit{ 11, 12, 13, 14, 15 };
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
5

std::mismatch() will get the job done and provides more information than std::equal. This will work with pre-C++11 compilers if you change auto to std::pair<int*, int*>

#include <algorithm>

int expectedResult[5] = {11, 12, 13, 14, 15};
int* arr1end = arrayone + 5;

//I assume here that expectedResult is the same length as arrayone (5).
auto res = std::mismatch(arrayone, arr1end, expectedResult);
if(res.first != arr1end) {
    std::cout << "Arrays not matching at " << std::distance(arrayone, res.first) << ", expected: " << *res.second << ", got: " << *res.first;
}

Better version, provided that arrayone is an array type (it could decay to a pointer if you for example pass it as a function argument). It requires C++11 due to usage of auto and std::begin()

#include <algorithm>
#include <iterator>

int expectedResult[5] = {11, 12, 13, 14, 15};

auto res = std::mismatch(std::begin(arrayone), std:end(arrayone), std::begin(expectedResult));
if(res.first != std::end(arrayone)) {
    std::cout << "Arrays not matching at " << std::distance(arrayone, res.first) << ", expected: " << *res.second << ", got: " << *res.first;
}

This being said, I recommend you to choose one framework and work with it. These libraries are built explicitly for making unit testing easy and fast (i.e. above sequence is one liner in GoogleTest and is not prone to different array length errors).

I'd also advice you to not use plain C-style arrays. As mentioned by Ted Lyngmo, if you use standard containers you have a lot more options available (e.g. built-in opearator ==) and they also manage resources for you.

Yksisarvinen
  • 18,008
  • 2
  • 24
  • 52
  • 1
    Could this be improved with std::begin(arrayone), std::end(arrayone)? Just shooting from memory. Or use sizeof to compute the number of elements. – Kenny Ostrom Jan 17 '19 at 18:28
  • I like this answer because it uses modern features, but is still compatible with old code. (although OP said "best approach" so the all-modern answers are fair, too) – Kenny Ostrom Jan 17 '19 at 18:39
1

If you insist that you must not use the STL and use primitives, this pretty much is a C question since it's not using C++ features. If you can safely assume they'd of size n, the following should be ok.

Given two primitive integer arrays of size n, the general implementation would be

bool equal(int *arr1, int *arr2, int n) { 
    for (int i = 0; i < n; i++) {
        if arr1[i] != arr2[i] return false;
    }
    return true
}

In general though, std::array would be a better idea than the old C-style arrays, but my understanding of the question is unclear, if you can use the STL then the other solutions are superior.

Edit: In case it's unclear what some problems with the above solution are:

  • There's no pointer validation
  • If the arrays are different sizes, this won't work
  • If you want to validate non-int arrays you'll need another (admittedly) function
  • (Subjective) the output time is different based on how similar the two arrays are

If you want a bit of a better solution, using memcmp like suggested in the comments (this doesn't use libraries to the best of my knowledge):

For two arrays of type X, and size n, you could simple say

bool eql = !(memcmp(arr1, arr2, n*sizeof(X))
Daniel
  • 854
  • 7
  • 18
  • 2
    memcmp would be similar – Kenny Ostrom Jan 17 '19 at 18:32
  • @KennyOstrom you're right. In fact, memcmp is actually better for a variety of reasons. My particular solution isn't actually a great answer, but I figured it'd be a very simple and easy example on how to compare arrays. In case the original poster wants a memcmp implementation I added it above =) – Daniel Jan 17 '19 at 18:41