Getting an "undefined reference to" error while attempting to perform unit testing

Hello, I’ve been on a journey attempting to test my code just to see if it works. in this scenario I am just trying to make a class the store the data for an IR sensor and I just can’t seem to get it to compile the way I want it to.

There are 3 files in question, IRSensor.h, IRSensor.cpp, and test.cpp. Here are the contents of each.
IRSensor.h

#ifndef IRSENSOR_H
#define IRSENSOR_H

class IRSensor {
private:
    int leftIRSensor;
    int middleIRSensor;
    int rightIRSensor;

public:
    IRSensor();
    int getLeftIRSensor();
    int getMiddleIRSensor();
    int getRightIRSensor();
    void setLeftIRSensor(int sensorValue);
    void setMiddleIRSensor(int sensorValue);
    void setRightIRSensor(int sensorValue);

};

int leftIRSensor;
int middleIRSensor;
int rightIRSensor;

#endif

IRSensor.cpp

#include "Sensors/IRSensor.h"

int leftIRSensor;
int middleIRSensor;
int rightIRSensor;

IRSensor::IRSensor() {
    leftIRSensor = 0;
    middleIRSensor = 0;
    rightIRSensor = 0;
}

int IRSensor::getLeftIRSensor() {
    return leftIRSensor;
}

int IRSensor::getMiddleIRSensor() {
    return middleIRSensor;
}

int IRSensor::getRightIRSensor() {
    return rightIRSensor;
}

void IRSensor::setLeftIRSensor(int sensorValue) {
    leftIRSensor = sensorValue;
}

void IRSensor::setMiddleIRSensor(int sensorValue) {
    middleIRSensor = sensorValue;
}

void IRSensor::setRightIRSensor(int sensorValue) {
    rightIRSensor = sensorValue;
}

test.cpp

#include "unity.h"
#include "Sensors/IRSensor.h"
#include <stdbool.h>

IRSensor irSensor = IRSensor();

void setUp(void) {
    // set stuff up here
}

void tearDown(void) {
    // clean stuff up here
}

void test_function_should_doBlahAndBlah(void) {
    TEST_ASSERT_TRUE(true);
}

void test_IRSensor_set(void) {
    irSensor.setLeftIRSensor(0);
    TEST_ASSERT_EQUAL_INT(0, irSensor.getLeftIRSensor());
    irSensor.setRightIRSensor(100);
    TEST_ASSERT_EQUAL_INT(100, irSensor.getRightIRSensor());
    irSensor.setMiddleIRSensor(1000);
    TEST_ASSERT_EQUAL_INT(1000, irSensor.getMiddleIRSensor());
}

// not needed when using generate_test_runner.rb
int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_function_should_doBlahAndBlah);
    RUN_TEST(test_IRSensor_set);
    return UNITY_END();
}

This is the command and output

PS C:\Users\xridd\OneDrive\Documents\PlatformIO\Projects\Teddi> pio test -e native                          
Verbosity level can be increased via `-v, -vv, or -vvv` option
Collected 1 tests

Processing test_tester in native environment
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
Building...
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0x2d): undefined reference to `IRSensor::setLeftIRSensor(int)'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0x3c): undefined reference to `IRSensor::getLeftIRSensor()'
cpp:(.text+0x3c): undefined reference to `IRSensor::getLeftIRSensor()'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0x73): undefined reference to `IRSensor::setRightIRSensor(int)'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0x82): undefined reference to `IRSensor::getRightIRSensor()'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0xb9): undefined reference to `IRSensor::setMiddleIRSensor(int)'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0xc8): undefined reference to `IRSensor::getMiddleIRSensor()'
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: .pio\build\native\test\test_tester\test.o:test.cpp:(.text+0x14f): undefined reference to `IRSensor::IRSensor()'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\native\program.exe] Error 1
Building stage has failed, see errors above. Use `pio test -vvv` option to enable verbose output.

Interestingly enough, I was able to make it compile and run the tests when I moved all of the implementation of IRSensor.h into the header file directly. However, I believe this is against best practice and would like to keep implementation in the .cpp file.

also, here is my project structure in case it helps

I appreciate any help I can get on this problem, Thanks.


Edited by @sivar2311: Changed from blockquote to preformatted text for better readability

I’m not really familiar with unit testing.

If I interpret Test Hierarchy — PlatformIO v6.1 documentation correctly, your IRSensor.cpp will be ignored which leads to the error.

Make your life easier by using the lib directory as described in the documentation.
Then the test will run without errors.

Project Structure:
image

IRSensor.h

#ifndef IRSENSOR_H
#define IRSENSOR_H

class IRSensor {
private:
    int leftIRSensor;
    int middleIRSensor;
    int rightIRSensor;

public:
    IRSensor();
    int getLeftIRSensor();
    int getMiddleIRSensor();
    int getRightIRSensor();
    void setLeftIRSensor(int sensorValue);
    void setMiddleIRSensor(int sensorValue);
    void setRightIRSensor(int sensorValue);

};

// Your code have issues here! 
// Remove the following lines:

// int leftIRSensor;
// int middleIRSensor;
// int rightIRSensor;

#endif

IRSensor.cpp

#include "IRSensor.h"

// Your code have issues here! 
// Remove the following lines:

// int leftIRSensor;
// int middleIRSensor;
// int rightIRSensor;

IRSensor::IRSensor() {
    leftIRSensor = 0;
    middleIRSensor = 0;
    rightIRSensor = 0;
}

int IRSensor::getLeftIRSensor() {
    return leftIRSensor;
}

int IRSensor::getMiddleIRSensor() {
    return middleIRSensor;
}

int IRSensor::getRightIRSensor() {
    return rightIRSensor;
}

void IRSensor::setLeftIRSensor(int sensorValue) {
    leftIRSensor = sensorValue;
}

void IRSensor::setMiddleIRSensor(int sensorValue) {
    middleIRSensor = sensorValue;
}

void IRSensor::setRightIRSensor(int sensorValue) {
    rightIRSensor = sensorValue;
}

test.cpp

#include <unity.h>
#include <IRSensor.h>
#include <stdbool.h>

IRSensor irSensor;

void setUp(void) {
    // set stuff up here
}

void tearDown(void) {
    // clean stuff up here
}

void test_function_should_doBlahAndBlah(void) {
    TEST_ASSERT_TRUE(true);
}

void test_IRSensor_set(void) {
    irSensor.setLeftIRSensor(0);
    TEST_ASSERT_EQUAL_INT(0, irSensor.getLeftIRSensor());
    irSensor.setRightIRSensor(100);
    TEST_ASSERT_EQUAL_INT(100, irSensor.getRightIRSensor());
    irSensor.setMiddleIRSensor(1000);
    TEST_ASSERT_EQUAL_INT(1000, irSensor.getMiddleIRSensor());
}

// not needed when using generate_test_runner.rb
int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_function_should_doBlahAndBlah);
    RUN_TEST(test_IRSensor_set);
    return UNITY_END();
}

I hope this helps you.

2 Likes

Main project source files are not built by default. See test_build_src — PlatformIO latest documentation

2 Likes