Closed claytonketner closed 5 years ago
Dear Clayton,
After reading this interesting post, I'd like to ask you if you can upload your 'godmode' helpers so that we can benefit feom them. Personally I had the same kind of issue's with I/O based vars so I am definitly interested in the twchnique you used. Anyway, thank you in advance!
@Aliazzzz I threw up https://github.com/tcunit/TcUnit/pull/46 - pretty simple, just cookie cutters of the same function. Oh how I wish TC was a little more flexible with dynamic typing...
This is great! I've too usually created the helper functions in the project itself to do "test-writes" on local variables in function blocks. Good initiative! I'll merge the pull request but I noticed it's done on an older version of the commit - so some unecessary files are changed and it's not possible from a pull request to do selection of files to be changed. I don't want to mess up the git commit history either, so could I ask you to do:
https://github.com/tcunit/TcUnit-Verifier/blob/master/README.md https://github.com/tcunit/TcUnit/blob/master/CONTRIBUTING.md
I've also added clarifications about which version of VS should be used.
Now regarding the library reference. I was not aware of that option. If I understand it correctly, it means that if we have a library A that uses TcUnit (for unit tests of function blocks in A), and then we have a program B that uses library A - if we in the project A set TcUnit to "Hide reference = True" then program B will not see that library A has a dependency to TcUnit - correct?
If that is so, you are correct that in it should be mentioned in the documentation of TcUnit as seeing the reference to TcUnit is only interesting in the context of opening the library A - not program B. Anyway, thanks for pointing this out to me!
Hi Clayton,
Having seen the pull request and intended purpose this sure has some validity as helpers. On the other hand I personally think the naming schem of these helpers is very ambiguous(!) My suggestion is to refrain from using 'ANY' in the function and substitute it for e.g. 'PROTECTED'. So 'WRITE_ANY_BOOL' becomes 'WRITE_PROTECTED_BOOL' .
Clayton, my plan is to release version 1.0 of TcUnit this weekend. Do you think you'll have time to finish the PR before that? If no, it's not a biggie!
I'll make sure to update the documentation anyways! :)
So 'WRITE_ANY_BOOL' becomes 'WRITE_PROTECTED_BOOL' .
Sure I can change that. ~I'll also add *Not*
assertion methods while I'm at it, which is another thing that I wanted to add (e.g. AssertNotEquals_UINT
)~ Actually I guess that wouldn't give you any more info than AssertFalse(var1 = var2)
I'll merge the pull request but I noticed it's done on an older version of the commit
I'm not sure what you mean. I updated my fork to your master before I did anything, and I'm not seeing any weird files being changed. Github says "This branch has no conflicts with the base branch"
I would still like to have tests in the TcUnit-Verifier for them
I can give that a shot.
...if we in the project A set TcUnit to "Hide reference = True" then program B will not see that library A has a dependency to TcUnit - correct?
Yep!
Nice!
https://github.com/tcunit/TcUnit-Verifier/pull/9 I'm not 100% sure if what I did was fully correct.
I've merged these commits into the main branch. Renamed all INPUT-variables in all WRITEPROTECTED* functions to use same naming standard as rest of TcUnit.
Removed return value of BOOL for all WRITEPROTECTED* functions as they were not used and were always set to FALSE.
Thanks for your contribution!
For whatever it's worth, I just wanted to mention that I'm constantly using this function now, and it's really great :-) It comes really in handy when you want to write unit tests for function blocks doing the handling of I/O terminals, when you use a lot of %Q and %I-variables that you want to write to.
Glad it could be of good use to someone else too! I also use it tons in my tests as well.
@claytonketner Coming back to this again... I just wanted to let you know I've created a FAQ for TcUnit (as the amount of users grow, and same questions are coming back again and again). Both of the two suggestions you've added in this issue have been added to the FAQ: https://tcunit.org/frequently-asked-questions/
Hope you don't mind I copy&pasted most of your text :-)
@sagatowski no problem at all - glad I could have helped! 😄 And thank you for your continued support of this project!
Just leaving this comment here for a suggestion to an alternative solution.
I recently tried to use WRITE_PROTECTED
for the first time, but I think this is way to verbose. Especially if you need to set a variable multiple times. Instead of using the WRITE_PROTECTED
I usually just extend my original function block FB_ToTest
to make a FB_ToTest_Tester
which has properties which can set the VAR
/%I
/%Q
variables.
Then you can simply do
fbToTest.InternalVariable := 5;
instead of:
TcUnit.WRITE_PROTECTED_INT(
Ptr := ADR(fbToTest.InternalVariable),
Value := 5
);
After writing many complicated tests for my company's codebase (phew), I think TcUnit could use a couple of these helper functions. In a number of scenarios, twincat won't let you write directly to certain variables:
VAR
)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. If you try to write to these protected variables like:
You'll get a compiler error saying
'someProtectedVariable' is no input of 'MY_FB'
.In my experience, this is most important for writing to I/O variables and for disabling timers (by setting
PT
to zero). This issue can be worked around by using pointers. In my PLC projects, I've added helper functions likeWRITE_ANY_INT
orWRITE_ANY_TIME
, which all do the same general thing:Using this function allows you to bypass the compiler warning (and the runtime has no issue executing it) so that you can make your code more "testable". Ex:
Having these helpers in TcUnit would also be nice because then I (read: others) wouldn't be able to access them in my projects that use the libraries being tested. Speaking of which...
Hide Reference
I noticed that your website and this repo don't mention the
Hide reference
option for referenced libraries (or at least I couldn't find it). This option lets you hide TcUnit from your other projects. For example:MyLibrary
, which has tests written in TcUnitMyProject
, which referencesMyLibrary
If you use
Hide reference
on TcUnit inMyLibrary
, then TcUnit won't show up in the imports list ofMyProject
. You can find it in the Properties tab:Thanks again for the continued work and upkeep on this library!