Skip to content

Commit bb35db2

Browse files
committed
Ran a markdown LINTer over the documentation.
1 parent 3ca07c5 commit bb35db2

7 files changed

Lines changed: 152 additions & 71 deletions

File tree

docs/faq.md

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ title: F.A.Q.
44
---
55

66
## Frequently asked questions
7+
78
Here you’ll find the most commonly asked questions and their answers.
89
If you don’t find what you are looking for here, you can look through the:
910

@@ -27,8 +28,8 @@ If you don’t find what you are looking for here, you can look through the:
2728

2829
---
2930

30-
3131
### 1. How can I run a test across multiple PLC cycles?
32+
3233
This can be accomplished by keeping the function block under test as an instance variable of the test suite rather than the test method.
3334
You can download an [example here](https://tcunit.org/temp/TimedTest_1x.zip).
3435
In this example, the `FB_ToBeTested` is instantiated under the test suite (`FB_ToBeTested_Test`), and can thus be controlled over multiple cycles.
@@ -37,9 +38,10 @@ Then all that’s necessary to do is to set the condition for when the assertion
3738
**Required TcUnit version:** 1.0 or later
3839

3940
### 2. How can I disable/ignore a test?
41+
4042
Add `DISABLED_` in front of the test name, for example:
4143

42-
```
44+
```StructuredText
4345
TEST('DISABLED_ThisTestWillBeIgnored');
4446
4547
AssertEquals(Expected := a,
@@ -48,9 +50,11 @@ AssertEquals(Expected := a,
4850
4951
TEST_FINISHED();
5052
```
53+
5154
**Required TcUnit version:** 1.0 or later
5255

53-
### 3. Is there a way to test %I* or %Q* variables?
56+
### 3. Is there a way to test `%I*` or `%Q*` variables?
57+
5458
In a number of scenarios, TwinCAT won't let you write directly to certain variables:
5559

5660
- Due to access restrictions (e.g. a variable in a FB's VAR)
@@ -59,29 +63,38 @@ In a number of scenarios, TwinCAT won't let you write directly to certain variab
5963
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.
6064
To support these cases, TcUnit provides helper functions like `WRITE_PROTECTED_BOOL()`, `WRITE_PROTECTED_INT()` (and so forth) for setting these type of variables.
6165
For an example of how to use these, let's assume you have a test:
62-
```
66+
67+
```StructuredText
6368
METHOD PRIVATE TestCommsOkChannelsLow
6469
VAR
6570
EL1008 : FB_Beckhoff_EL1008;
6671
END_VAR
6772
```
73+
6874
Where the `FB_Beckhoff_EL1008` holds a variable:
69-
```
75+
76+
```StructuredText
7077
iChannelInput AT %I* : ARRAY[1..8] OF BOOL;
7178
```
79+
7280
Now you might want to write a value to the first channel of the iChannelInput like:
73-
```
81+
82+
```StructuredText
7483
TcUnit.WRITE_PROTECTED_BOOL(Ptr := ADR(EL1008.iChannelInput[1]),
7584
Value := FALSE);
7685
```
86+
7787
Whereas afterwards you can make an assertion as usual:
78-
```
88+
89+
```StructuredText
7990
AssertFalse(Condition := EL1008.ChannelInput[1],
8091
Message := 'Channel is not false');
8192
```
93+
8294
**Required TcUnit version:** 1.0 or later
8395

8496
### 4. Is there a way to hide TcUnit in my libraries?
97+
8598
You can accomplish this by the [Hide reference](https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_plc_intro/18014402725266443.html&id=) option for referenced libraries.
8699
This option lets you hide TcUnit from your other projects.
87100
Let’s assume you’ve developed a library `MyLibrary`, which has tests written in TcUnit.
@@ -92,17 +105,17 @@ You can find it in the Properties tab:
92105

93106
![Hide reference](img/hide-reference.png)
94107

95-
96108
**Required TcUnit version:** 1.0 or later
97109

98110
### 5. How do I do assertions on the BIT datatype?
111+
99112
I want to do an assertion on two variables both declared with the `BIT`-datatype, but I have noticed that a `AssertEquals_BIT()` does not exist.
100113
What do I do?
101114

102115
The reason a `AssertEquals_BIT()` does not exist is that TwinCAT does not allow a BIT-datatype as a variable input.
103116
If you have data declared with the BIT-type, the easiest way to do an assertion on these is to do a `BIT_TO_BOOL()` conversion and use the `AssertEquals_BOOL()`.
104117

105-
```
118+
```StructuredText
106119
TEST('Testing_of_BIT_Type');
107120
108121
AssertEquals_BOOL(Expected := BIT_TO_BOO(VariableDeclaredAsBit_A),
@@ -115,6 +128,7 @@ TEST_FINISHED();
115128
**Required TcUnit version:** 1.0 or later
116129

117130
### 6. When I run more than 100 tests in a single test-suite I get the wrong results, why?
131+
118132
When TcUnit is running it allocates memory in the PLC to store the test results.
119133
The maximum number of tests for every test suite has been set to 100, which however is a configuration parameter for TcUnit and can be changed.
120134
Parameters for TcUnit (and in fact any library references) are stored in your project, which means that this change will be persistent for your project/library.
@@ -124,8 +138,8 @@ To change this max amount, to say for instance 200 tests per test suite, go to t
124138

125139
**Required TcUnit version:** 1.0 or later
126140

127-
128141
### 7. Is it possible to run test suites and/or tests in a sequence?
142+
129143
Yes.
130144
By default TcUnit runs all the test suites and tests in parallel, in other words all test suites and tests are run at the same time.
131145
Sometimes it is however desirable to run either the test suites or tests (or both) in a sequence, for example if you get exceed overruns while running tests.
@@ -134,7 +148,8 @@ Since TcUnit 1.2 it's possible to run test suites in sequence (one after another
134148
To execute test suites in a sequence, simply replace `TcUnit.RUN()` with `TcUnit.RUN_IN_SEQUENCE()` in your main body of the test program.
135149
This will execute the test suites in the order that they were declared.
136150
So for example if we have defined the following test suites and test program:
137-
```
151+
152+
```StructuredText
138153
PROGRAM PRG_TEST
139154
VAR
140155
fbDiagnosticMessageDiagnosticCodeParser_Test : FB_DiagnosticMessageDiagnosticCodeParser_Test;
@@ -143,14 +158,16 @@ VAR
143158
END_VAR
144159
-------------------------
145160
TcUnit.RUN_IN_SEQUENCE();
161+
146162
```
163+
147164
This will first execute all tests defined in `fbDiagnosticMessageDiagnosticCodeParser_Test`, once all tests are finished in that function block, TcUnit will execute all tests in `fbDiagnosticMessageFlagsParser_Test`, and when that is done it will execute all tests in `fbDiagnosticMessageParser_Test`.
148165

149166
It's also possible to execute individual tests in order by simply replacing `TEST('TestName')` with `TEST_ORDERED('TestName')`.
150167
This will execute the tests in the order that the `TEST_ORDERED()` is called for the various tests.
151168
`TEST_ORDERED()` returns a boolean to indicate whether the TcUnit framework will run the test, so in order to only execute the code when it's time for that particular test, it makes sense to check if `TEST_ORDERED()` returns true, and only then do the execution of the function blocks and assertions, for example like this:
152169

153-
```
170+
```StructuredText
154171
METHOD PRIVATE TestWithTimestampZeroTimeExpectCurrentTime
155172
VAR
156173
... (variable declaration used for the test)
@@ -166,14 +183,14 @@ IF TEST_ORDERED('TestWithTimestampZeroTimeExpectCurrentTime') THEN
166183
TEST_FINISHED();
167184
END_IF
168185
```
186+
169187
As usual, the `TEST_FINISHED()` will indicate that this test is finished, and the framework will go to the next test.
170188
Note that you don't need to create any state machine for calling the different `TEST_ORDERED()` tests.
171189
You can (and must!) call all `TEST_ORDERED()` at the same time.
172190
The framework will make sure to only care about the assertions of the test that is currently running.
173191

174192
This means the following combinations can be used:
175193

176-
177194
- `RUN()` with all tests as `TEST()` – means all tests suites and tests will run in parallel, this is the default behaviour.
178195
![TcUnit run option 1](img/tcunit_run_option1.png)
179196
- `RUN_IN_SEQUENCE()` with all tests as `TEST()` – means all test suites will run in sequence, but the tests in every test suite will run in parallel.
@@ -197,6 +214,7 @@ For a couple of TwinCAT projects that shows how to run both test suites in a seq
197214
**Required TcUnit version:** 1.2 or later
198215

199216
### 8. Why is it taking so long to get the results from TcUnit?
217+
200218
If you have many test suites and/or tests, it can take some time for TcUnit to print all those results.
201219
Since version 1.1 of TcUnit, much more data is printed to the ADS-logger as this data is used for the communication with TcUnit-Runner.
202220
If you know that you will only run your tests locally and without integration to a CI/CD tool using TcUnit-Runner, you can set the parameter `LogExtendedResults` to `FALSE` (it is default `TRUE`).
@@ -207,6 +225,7 @@ To change this parameter, go to the library references and select TcUnit, then g
207225
**Required TcUnit version:** 1.1 or later
208226

209227
### 9. Is it possible to have a time delay between the execution of the test suites?
228+
210229
Yes.
211230
You can set the parameter `TimeBetweenTestSuitesExecution` to whatever delay you want to have.
212231
To change this parameter, go to the library references and select TcUnit, then go to `GVLs``GVL_Param_TcUnit``TimeBetweenTestSuitesExecution`.
@@ -218,9 +237,11 @@ For example, in the below screenshot this is changed to 5 seconds.
218237
**Required TcUnit version:** 1.2 or later
219238

220239
### 10. If I call ADSLOGSTR(), my messages don't show up in the correct sequence. Why?
240+
221241
If I call `Tc2_System.ADSLOGSTR()` during execution of a test, my messages don't arrive in the expected order.
222242
Let's for example assume this very simple (always failing) test:
223-
```
243+
244+
```StructuredText
224245
TEST('Test1');
225246
FOR nCounter := 1 TO 5 BY 1 DO
226247
Tc2_System.ADSLOGSTR(msgCtrlMask := ADSLOG_MSGTYPE_HINT,
@@ -255,9 +276,11 @@ So if we replaced the call to `Tc2_System.ADSLOGSTR()` to `TCUNIT_ADSLOGSTR()` i
255276
**Required TcUnit version:** 1.2 or later
256277

257278
### 11. How do I test functions?
279+
258280
It's done almost identical as in the introduction user guide, but simply replace the instance of the function block that you want to test with the call to the function instead.
259281
Assume we have a function:
260-
```
282+
283+
```StructuredText
261284
FUNCTION F_Sum
262285
VAR_INPUT
263286
one : UINT;
@@ -266,8 +289,10 @@ END_VAR
266289
267290
F_Sum := one + two;
268291
```
292+
269293
Then the test would look like following:
270-
```
294+
295+
```StructuredText
271296
METHOD TwoPlusTwoEqualsFour
272297
VAR
273298
Result : UINT;
@@ -283,11 +308,14 @@ AssertEquals(Expected := ExpectedSum,
283308
Message := 'The calculation is not correct');
284309
285310
TEST_FINISHED();
311+
286312
```
313+
287314
**Required TcUnit version:** 1.0 or later
288315

289316
### 12. I have problems running TcUnit on a ARMv7 controller, why?
317+
290318
When running TcUnit with a controller using ARMv7 you can run into issues, such as breakpoints not working.
291319
This seems to be an issue with the limited memory of the controllers using an ARMv7 such as the CX8190 and CX9020. Please adjust the [parameters related to memory allocation](#6-when-i-run-more-than-100-tests-in-a-single-test-suite-i-get-the-wrong-results-why).
292320

293-
For more information on a set of working parameters, see [this issue on GitHub](https://github.com/tcunit/TcUnit/issues/148).
321+
For more information on a set of working parameters, see [this issue on GitHub](https://github.com/tcunit/TcUnit/issues/148).

docs/img/TcUnit16Of17Failed_2.png

5.03 KB
Loading

docs/img/TcUnitManyFails.png

55.3 KB
Loading

docs/index.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ layout: home
66
list_title: ' '
77
---
88

9+
# TcUnit
10+
911
![TcUnit logo](img/tcunit-logo.png)
1012

1113
TcUnit is an [xUnit](https://en.wikipedia.org/wiki/XUnit) type of framework specifically done for [Beckhoff’s TwinCAT 3](https://www.beckhoff.com/en-en/products/automation/twincat/) development environment.
@@ -17,18 +19,22 @@ Start by reading the [unit testing concepts](unit-testing-concepts.md) and then
1719
![TcUnit introduction](img/tcunit-general.png)
1820

1921
## Easy to use
22+
2023
The framework is easy to use.
2124
All that is needed is to download & install the library, and provide a reference to the TcUnit-library in your project, and you can start to write your test code.
2225
For a complete set of instructions, start with [the concepts](unit-testing-concepts.md), continue with [the user guide](introduction-user-guide.md) and finish with [the programming example](programming-example.md).
2326

2427
## One library
28+
2529
All functionality is provided by one single library.
2630
Add the library to your project and you are ready to go! You can either [download a precompiled](https://github.com/tcunit/TcUnit/releases) (ready to install) version of the library or [download the source code](https://www.github.com/tcunit/tcunit).
2731

2832
## MIT-license
33+
2934
The library and all the source code is licensed according to the MIT-license, which is one of the most relaxed software license terms.
3035
The software is completely free and you can use the software in any way you want, be it private or for commercial use as long as you include the MIT license terms with your software.
3136

3237
## Automated test runs
38+
3339
With the additional TcUnit-Runner software, it’s possible to do integrate all your TcUnit tests into a CI/CD software toolchain.
34-
With the aid of automation software such as [Jenkins](https://www.jenkins.io/) or [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/), you can have your tests being run automatically and collect test statistics every time something is changed in your software version control (such as Git or Subversion).
40+
With the aid of automation software such as [Jenkins](https://www.jenkins.io/) or [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/), you can have your tests being run automatically and collect test statistics every time something is changed in your software version control (such as Git or Subversion).

docs/introduction-user-guide.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ The purpose of this user guide is to be a short tutorial where we will go throug
1717
3. Create test suites and run the tests
1818

1919
## Download & install
20+
2021
The framework can either be downloaded as a [precompiled library](https://github.com/tcunit/TcUnit/releases), or you can download the [source code](https://www.github.com/TcUnit/TcUnit) and compile the library yourself.
2122

2223
### Install from library file
24+
2325
If you’ve downloaded the library, you should have a file called **TcUnit.library** in your computer.
2426
Start your TwinCAT XAE (Visual Studio).
2527
In the menu of Visual Studio select **PLC** and then **Library Repository...**
@@ -30,6 +32,7 @@ Click on **Install...**, locate the **TcUnit.library** file and double-click on
3032
Now it will install to your TwinCAT-folder, more specifically C:\TwinCAT\3.1\Components\Plc\Managed Libraries\www.tcunit.org\TcUnit\.
3133

3234
### Install from source
35+
3336
If you want to install it from source, make sure that you have a TwinCAT XAE installed.
3437
Next do a GIT-clone on the repository.
3538
Open the folder where you cloned the repo, and open the solution by double-clicking on the TcUnit.sln file in the root of the folder, which will open the project in your TwinCAT XAE environment.
@@ -43,6 +46,7 @@ This will install the library on your computer.
4346
Once the library is installed, the file that you saved on the desktop can be removed.
4447

4548
### Reference the library in project
49+
4650
In order to use TcUnit you need to add a reference to the library in your project.
4751
Open your TwinCAT project, and right-click on the **References** under the PLC-project and click on **Add library...**
4852

@@ -51,6 +55,7 @@ Open your TwinCAT project, and right-click on the **References** under the PLC-p
5155
Next go to the TcUnit-group, select TcUnit and click **OK**.
5256

5357
### Create test suites and run them
58+
5459
For every function block (or free function) that you have defined we want to create a test function block (test suite), which has the responsibility to:
5560

5661
- Instantiate the FB under test
@@ -78,7 +83,7 @@ Each test suite is responsible of testing one FB or function, and can have one o
7883
Let’s assume we want to create the simplest possible FB that takes two unsigned integers and sums them.
7984
We can create the header for the FB, but the actual implementation can (and should) wait after we’ve done the unit tests.
8085

81-
```
86+
```StructuredText
8287
FUNCTION_BLOCK FB_Sum
8388
VAR_INPUT
8489
one : UINT;
@@ -92,7 +97,7 @@ END_VAR
9297
Now let’s create the test suite for this.
9398
This FB needs to extend `TcUnit.FB_TestSuite`.
9499

95-
```
100+
```StructuredText
96101
FUNCTION_BLOCK FB_Sum_Test EXTENDS TcUnit.FB_TestSuite
97102
VAR
98103
END_VAR
@@ -108,7 +113,7 @@ For them well-named tests are invaluable.
108113
We’ll be creating two tests called `TwoPlusTwoEqualsFour` and `ZeroPlusZeroEqualsZero`.
109114
The `TwoPlusTwoEqualsFour` will look like this:
110115

111-
```
116+
```StructuredText
112117
METHOD TwoPlusTwoEqualsFour
113118
VAR
114119
Sum : FB_Sum;
@@ -136,7 +141,7 @@ This gives the flexibility to have tests that span over more than one PLC-cycle.
136141

137142
For `ZeroPlusZeroEqualsZero` it’s more or less the same code.
138143

139-
```
144+
```StructuredText
140145
METHOD ZeroPlusZeroEqualsZero
141146
VAR
142147
Sum : FB_Sum;
@@ -156,7 +161,8 @@ TEST_FINISHED();
156161
```
157162

158163
Next we need to update the body of the test suite (`FB_Sum_Test`) to make sure these two tests are being run.
159-
```
164+
165+
```StructuredText
160166
TwoPlusTwoEqualsFour();
161167
ZeroPlusZeroEqualsZero();
162168
```
@@ -168,7 +174,7 @@ Being part of the library project we only want a convenient way to test all the
168174
`PRG_TEST` needs to instantiate all the test suites, and only execute one line of code.
169175
In this case we only have one test suite.
170176

171-
```
177+
```StructuredText
172178
PROGRAM PRG_TEST
173179
VAR
174180
fbSum_Test : FB_Sum_Test; // This is our test suite
@@ -191,7 +197,7 @@ As we can see, the test `TwoPlusTwoEqualsFour` failed, which means that the one
191197
The reason this succeeds is that the default return value for an output-parameter is zero, and thus it means that even if we haven’t written the body of `FB_Sum` the test will succeed.
192198
Let’s finish by implementing the body of `FB_Sum`.
193199

194-
```
200+
```StructuredText
195201
FUNCTION_BLOCK FB_Sum
196202
VAR_INPUT
197203
one : UINT;
@@ -217,4 +223,4 @@ Obviously this is a very simple example and the purpose of this was to show how
217223
Simple functionality that does not require any state would be better suited to be implemented as a function, or in this case just using the "+" operator.
218224
For a real-world example see the [programming example](programming-example.md).
219225

220-
The source code for this example is [available on GitHub](https://github.com/tcunit/ExampleProjects/tree/master/SimpleExampleProject).
226+
The source code for this example is [available on GitHub](https://github.com/tcunit/ExampleProjects/tree/master/SimpleExampleProject).

0 commit comments

Comments
 (0)