As the title suggests, I was wondering how one goes about testing FBs that have IO variables declared inside of the function block it-self. I am using TcUnit to write tests for a motion library that I made. Right now the only solution I see is to create the outputs from within the test block and link it to the test FB's input that I can't write to from outside. Another option is to use pointers, but I am really not a fan of that, though it might be the only "proper" way to go about this.
Solution using IO linking
Program:
PROGRAM INTERNAL PRG_TESTS
VAR
fbTest : FB_Test;
END_VAR
Test FB:
FUNCTION_BLOCK FB_Test EXTENDS FB_TestSuite
VAR
CantBeModifiedInput AT %I* : WORD;
HackToModifyTheInput AT %Q* : WORD;
END_VAR
TestMethod();
Test method:
METHOD TestMethod
TEST('test');
HackToModifyTheInput := 10;
AssertTrue(CantBeModifiedInput = 10, 'Exepected value to be 10.');
TEST_FINISHED();
This however makes it so that only manual tests can be run, this can't be done automatically on a build server - or can it? I am not at the point of automated tests yet, but it is something to consider for the future.
Solution using direct memory access:
METHOD TestMethod
VAR
testWord : WORD := 10;
END_VAR
//HackToModifyTheInput := 10;
TEST('test');
MEMCPY(
destAddr := ADR(CantBeModifiedInput),
srcAddr := ADR(testWord),
n := SIZEOF(WORD));
AssertTrue(CantBeModifiedInput = 10, 'Exepected value to be 10.');
TEST_FINISHED();
How should I tackle this issue? I really don't want to use inputs and outputs to the fb instead of direct I/O creation from within the block. I feel like the memory manipulation might be the only proper way to be honest.

From the TcUnit FAQ.
In a number of scenarios, TwinCAT won't let you write directly to certain variables:
AT %I*orAT %Q*)Writing to these variables wouldn't make sense and should be prevented in the normal PLC code, so having special privileges during testing is a must. To support these cases, TcUnit provides helper functions like
WRITE_PROTECTED_BOOL(),WRITE_PROTECTED_INT()(and so forth) for setting these type of variables. For an example of how to use these, let's assume you have a test:Where the
FB_Beckhoff_EL1008holds a variable:Now you might want to write a value to the first channel of the
iChannelInputlike:Whereas afterwards you can make an assertion as usual:
Required TcUnit version: 1.0 or later