Qst Documentation¶
Qst is a firmware test automation suite for embedded devices. It uses the QML language to describe and implement test cases. QML is mainly a declarative programming language, but it can be enriched with Javascript.
Usage¶
This document explains most features of Qst and shows how to use them. It is a complete walk-through and will take about 15 minutes.
- Running a simple test case
- Adding probe components
- Extending and re-using components
- Attaching signal handlers
- Using constraints for continuous evaluation
- Structuring projects
- Working with profiles
- Storing temporary files
- Tagging test cases for data-driven tests
- Specifying dependencies between test cases
Qst makes use of the QML language, a declarative language mixed with Javascript. The language is very intuitive, but you might want to have a look at the QML language reference or keep it open in a separate browser tab.
We will use the terms item and component a lot. An item refers to a data type whereas component usually refers to a specific instance of an item.
Running a simple test case¶
Let us now get our hands dirty and have a look at a trivial test case. Every
test case is defined by a Testcase
component and is characterized by at least
2 things:
The name must be unique across the whole project and must be a plain string. The
run()
function may have arbitrary execution length and contain blocking and
non-blocking function calls. The Testcase
component is put into a file of an
arbitrary name and in its simplest form it would look as follows:
import qst 1.0
Testcase {
name: "simple-passing-test"
function run() {
/* ... */
}
}
The above test case does not do anything useful. It specifies a name and
contains an empty run()
function. This is equal to a test case without any
failure, so it will simply pass. We will now execute simple-passing-test.qml
by typing the following command in a terminal:
$ qst run --file simple-passing-test.qml
PASS, simple-passing-test,,,
Qst prints a line of comma-separated values containing the test
result
and the name
of the test case. We will discuss the remaining commas in a
second.
Now let’s make the test case fail. For that purpose, Qst offers a couple of
helper services of which Qst
with its verification
functions Qst::compare()
and Qst::verify()
is the most
important one:
1 2 3 4 5 6 7 8 9 | import qst 1.0
Testcase {
name: "simple-failing-test"
function run() {
Qst.verify(false)
}
}
|
We execute the test, using a slightly shorter command line than above:
$ qst run -f simple-failing-test.qml
FAIL, simple-failing-test, simple-failing-test, simple-failing-test.qml:7, verify() failed
Qst outputs test results in a comma-separated line with the following elements:
result
of the test case,name
of the test case,- name of the current active component (on fail only),
- file location of the failure (on fail only),
- error message (on fail only)
We know the result
and the name
already from the simple-passing-test.qml example. The other
elements are only shown when a test case does not pass. In our very simple
example, the test case is the only active component. More complex test cases
might form a component tree structure, hence the 3rd column. The current
location is the caller position of a verification function. The message in
the last column comes from the failing verification function and is either set
by hand or automatically created.
Now we know how to set up a test case and how to run it. Still, it doesn’t do anything useful. We need to connect it to the outside world and fill it with life.
Adding probe components¶
Probes connect Qst to the environment, for instance to the file system and other programs on the computer or even to external hardware. Probes are not a special language construct, but pure QML components with properties, methods, signals and slots.
A versatile probe item is the ProcessProbe
. It can invoke programs
on the local computer and monitor their execution. A very simple test case that
runs GNU Make on a Makefile in the current folder would look like this:
import qst 1.0
Testcase {
name: "makefile-test-simple"
ProcessProbe {
id: make
program : "/usr/bin/make"
workingDirectory: path
arguments: [
"-f", path + "/Makefile",
"all"
]
}
function run() {
make.start()
make.waitForFinished(10)
Qst.compare(make.exitCode, 0,
"Build did not succeed: " + make.readAllStandardError())
}
}
This example demonstrates the following new elements:
- It instantiates a nested component of the type
ProcessProbe
and assigns custom values to its properties. - The nested process probe is assigned an id attribute so that it can be referenced.
- The global
path
context property is used which always points the physical directory of the current file.
Various other probe items exist. For a complete list, have a look at the reference documentation.
Extending and re-using components¶
The above test case makefile-test-simple.qml is not re-usable in this form because all parameters are hard-coded. Consider a project with a bunch of makefiles. It would be cumbersome to re-write the whole test case for each makefile. Instead, we can turn the test case into a re-usable component by defining additional properties:
import qst 1.0
Testcase {
property string makefile : path + "/Makefile"
property string target: "all"
property int timeout : 10
ProcessProbe {
id: make
program : (Qst.hostOs === "windows") ? "gmake.exe" : "make"
workingDirectory: path
arguments: [
"-f", makefile,
target
]
}
function run() {
make.start()
make.waitForFinished(timeout)
Qst.compare(make.exitCode, 0,
"Build did not succeed: " + make.readAllStandardError())
}
}
When saving it to a file MakefileTestcase.qml, it is automatically available
as component type MakefileTestcase
in other qml files located in the same
directory. Based upon MakefileTestcase.qml, we can now create multiple
test case files in the following form:
import qst 1.0
MakefileTestcase {
name: "test-app-build"
makefile: path + "/app.mak"
}
import qst 1.0
MakefileTestcase {
name: "test-lib-build"
makefile: path + "/lib.mak"
}
Later we will learn a way to define multiple test case in one document.
Custom properties are also helpful in large test cases. Instead of hard-coding parameters everywhere in-line, it is better to to put them upfront to make the test case more readable. This applies to all components in general and is common practise in QML.
Attaching signal handlers¶
In many probes and test cases we might observe onXXX: {...}
constructs, for
instance:
Testcase {
/* ... */
onCreated: {
// prepare external resources
}
}
Signal handlers are always written in the form on<CapitalizedSignal>. Signals and signal handlers are a core concept of the QML language and fall in 1 of 3 categories:
- explicitly defined signals,
like
ProcessProbe::finished()
, - implicitly defined property change signals,
- attached signals added by other components.
Signal handlers may contain arbitrary JavaScript code, but they have run-to- completion semantics and must never do blocking calls. You may follow above links to read more about this topic. Let us now have a look, how we can utilize signal handlers in a Qst project.
Our MakefileTestcase.qml file from above can only do one thing: invoke GNU
make. But what if a test case is more complex and needs to invoke additional
programs? In this case, it would be more benefitial to extend
ProcessProbe
instead of Testcase
:
import qst 1.0
ProcessProbe {
property string makefile : path + "/Makefile"
property string target: "all"
property int jobs: 1
program : (Qst.hostOs === "windows") ? "gmake.exe" : "make"
arguments: [
"-f", makefile,
"-j", jobs,
target
]
workingDirectory: path
// Explicitly defined by ProcessProbe
onFinished: {
Qst.compare(exitCode, 0, readAllStandardError())
}
// Implicitly defined property change signal
onJobsChanged: {
Qst.verify(jobs <= 4, "The maximum number of jobs is 4.")
}
// Attached by Testcase
Testcase.onFinished: {
if (state === ProcessProbe.Running) {
terminate()
Qst.verify(false, "Make was still running.")
}
}
}
The MakeProbe.qml component can now be included even multiple times like this:
import qst 1.0
Testcase {
name: "test-multi-build"
MakeProbe {
id: app
name: "make-app"
makefile: path + "/app.mak"
jobs: 5
}
MakeProbe {
id: lib
name: "make-lib"
makefile: path + "/lib.mak"
jobs: 5
}
function run() {
app.start()
app.waitForFinished(20)
lib.start()
lib.waitForFinished(20)
}
}
As we can see in MakeProbe.qml, implicit and explicit signal handlers must
be defined in the scope of the signal’s owner component. For instance,
onJobsChanged
would not work outside MakeProbe
. In cases where we
need to handle a signal of a component that is not defined in the current
component, we can use SignalProbe
as shown in the
ExtendedTestcase.qml example. It is also possible to use the
Connections item from the QtQml package.
Using constraints for continuous evaluation¶
In the MakeProbe.qml example we have learned how signal handlers can be
used for on-going verification. We do not have to think about them in the
run()
function, they work silently in the background.
Constraints follow the same principle, but are a bit more formalized and
declarative. They make the test case fail immediately when they are violated.
Constraints are usually connected to signals like the
DurationConstraint
or bound to properties like the
ValueRangeConstraint
.
Take the following test case as an example:
import qst 1.0
Testcase {
property int responseTime: 0
onResponseTimeChanged: {
Qst.verify((responseTime >= 4) && (responseTime =< 8),
"responseTime (" + responseTime
+ ") is not in the expected range.")
}
function run() {
// ...
}
}
The property responseTime
could be validated by the help of an implicit
property changed signal handler and Qst
verification functions. But
we could also use a constraint and improve the readability of the test case:
import qst 1.0
Testcase {
property int responseTime: 0
ValueRangeConstraint {
value: responseTime
minValue: 4
maxValue: 8
}
function run() {
// ...
}
}
Structuring projects¶
Until now we have only discussed single test cases whereas a real project would
contain many of them. Qst provides the Project
item for this purpose. A
Project
component can reference all test cases and serves as the main file of
the project:
Project {
name: "referencing-project"
references: [
"testcase-file-1.qml",
"testcase-file-2.qml",
/* ... */
]
}
It is also possible to put multiple Testcase
components into a the same
file by enclosing them in a Project
component. This is especially useful
when parametrizing and instantiating a generic test case multiple times:
Testcase {
property int speed
function run() {
Qst.info("Speed is set to " + speed)
}
}
Project {
name: "inline-project"
SpecialTestcase { name: "tc-1"; speed: 10 }
SpecialTestcase { name: "tc-2"; speed: 42000 }
/* ... */
}
The Project
component is automatically attached to any referenced file
and can be accessed as project
context property:
Project {
property string host: "http://secr.et"
references: [
"test-case-1.qml",
/* ... */
]
}
Testcase {
name: "test-case-1"
function run() {
Qst.info(name + " is using " + project.host)
}
}
Although the project
property is shared across the whole project,
test cases are not supposed to write to the project’s properties.
Working with profiles¶
Qst projects may be developed and executed by multiple developers on different computers. One usual problem in such setups are differing installation paths, serial numbers, ports, etc. . Putting machine-dependent values into project files would only complicate version control and collaboration:
Testcase {
property string port: "COM77" // ttyUSB3 on another computer
/* ... */
}
Profiles solve that problem by collecting machine-dependent properties in a JSON file that remains on the developer’s computer:
{
"port": "COM77",
}
{
"port": "ttyUSB3",
}
The profile name is determined by the file name and selected as command line option when executing a test project:
$ qst run --file mytest.qml --profile uart-testing
Profile values can be accessed from anywhere in the project as
profile
:
Testcase {
property string port: profile.port
}
Qst tries to load the he selected profile first from the project directory and
if it could not be found, it searches in the »profiles« folder inside the Qst
configuration directory. Additional profile search paths can be specified with
--profile-directory
or -P
respectively:
$ qst run --f mytest.qml -p uart-testing -P /path/to/profiles
The latter option might be given multiple times.
Storing temporary files¶
Qst uses a working directory to store intermediate files during test execution. The directory is automatically created in the current folder and by default it has the format .<project-name>-<profile-name>-<hash>. Each test case will have a sub-folder with its name in the project working directory.
Let us assume a test project that:
- builds a firmware image,
- downloads it to the hardware,
- executes various tests on the hardware.
The directory layout of this imagined example project would look like:
.myproject-myprofile-e413c0f7
├── testcase-build
│ ├── object-1.o
│ ├── object-2.o
│ └── firmware.hex
├── testcase-flash
├── testcase-some-feature
└── testcase-other-feature
└── log.txt
For the run
command, the working directory can be overridden by the
--working-directory
command-line option. When run
is
executed multiple times and the working directory already exists, each
test case sub-folder is wiped out before the Testcase::created()
signal is emitted.
Tagging test cases for data-driven tests¶
In MakefileTestcase.qml and SpecialTestcase.qml we have already seen
two ways to re-use and parameterize Testcase
components. This can be
cumbersome for larger amount of data. It might also be annoying to give each
test case a different name while only some input parameters change, but not the
test case itself.
Especially for data-driven testing, Qst provides the Matrix
item. A
matrix spans a n-dimensional parameter space that is then applied to a one or
more test cases. Each data sample is called a tag and the combination of a
tag and a Testcase
is called a job.
The following example project defines a matrix with two dimensions, each containing a parameter array of length 2:
import qst 1.0
Project {
Matrix {
Dimension {
animal: [
"cat",
"dog"
]
}
Dimension {
does: [
"moans",
"bites"
]
}
testcases: [ "tagged-test" ]
}
Testcase {
name: "tagged-test"
property string animal
property string does
function run() {
Qst.info("The " + animal + " " + does + ".")
}
}
Testcase {
name: "normal-test"
function run() {}
}
}
Thus, the matrix expands to 4 different tag combinations:
dog bites | dog moans |
cat bites | cat moans |
When executing above project, the command line output looks as follows:
$ qst run -f matrix-project.qml
PASS, normal-test,,,
INFO, tagged-test 1ms2r6i [ cat moans ], , /matrix-project.qml:27, The cat moans.
PASS, tagged-test 1ms2r6i [ cat moans ],,,
INFO, tagged-test 17tca19 [ dog bites ], , /matrix-project.qml:27, The dog bites.
PASS, tagged-test 17tca19 [ dog bites ],,,
INFO, tagged-test 0ni1i5d [ cat bites ], , /matrix-project.qml:27, The cat bites.
PASS, tagged-test 0ni1i5d [ cat bites ],,,
INFO, tagged-test 07cs7hy [ dog moans ], , /matrix-project.qml:27, The dog moans.
PASS, tagged-test 07cs7hy [ dog moans ],,,
Specifying dependencies between test cases¶
The default execution order of test cases is undefined in Qst. But in practise,
a test case B
might require the completion of another test case A
. Such
dependencies can be expressed with the Depends
item as shown in the
following code snippet:
import qst 1.0
Project {
Testcase {
name: "A"
function run() {}
}
// Has to wait until A completes.
Testcase {
name: "B"
Depends { name: "A" }
function run() {}
}
}
Of course the test cases A
and B
can be defined in different files and
each test case can have multiple dependencies.
Sometimes it might also be desired to access data from a preceding test. By the
help of the Exports
item, a test case can specify which data is to
be forward to dependent test cases. This is not possible otherwise because test
cases are isolated from each other do not share any memory.
Hardware probes¶
Qst can be connected to hardware in order to perform measurements or to control the device under test.
Texas Instruments Launchpad¶
The launchpad probe firmware converts a launchpad into a cheap real-time IO interface. Available are all pins on the board except the LEDs at DIO6 and DIO7 which are occupied by the probe firmware.
The probe firmware binaries are located in <QST_INSTALL_DIR>/share/qst/firmware and may be written to the hardware using Uniflash.
Supported launchpads:
Related probe items:
Related service items:
Reference¶
General
Command-line interface¶
Qst provides multiple command-line commands. They can be invoked as qst <command name>. The following commands are available:
run¶
Executes a test case or a test project and outputs the results.
Synopsis¶
qst run [options]
Description¶
The run
command executes a Qst .qml file containing a
Testcase
or a Project
component. The file is specified
by the -f
option.
Options¶
-
-d
,
--working-directory
<path>
¶ Use <path> as working directory during test case execution. If the directory does not exist, it is being created. By default, a directory with the name .<project-name>-<profile-name>-<hash> is created in the current path.
-
-f
,
--file
<file>
¶ Use <file> as project file. If <file> is a directory and contains a single file ending in .qml, that file will be used. If this option is not given at all, the behavior is the same as for
--file ./
.
-
-h
,
--help
¶
Displays this help.
-
-I
,
--import
<path>
¶ Add <path> as a directory where the engine searches for installed modules in a URL-based directory structure.
The path may be a local file system directory, a Qt Resource path (:/imports), a Qt Resource url (qrc:/imports) or a URL.
Language reference¶
Qst makes use of the QML language, a declarative language mixed with Javascript. The official QML language reference eplains all core concepts in detail. In difference to a regular QML interpreter, Qst analyses the the documents before it executes them and makes additions to the QML runtime environment. It expects a certain structure and enforces some rules. The purpose of this document is, to eplain all differences.
Context properties¶
The following properties are automatically attached by the Qst QML engine to every loaded documented unless unless otherwise stated.
-
Project
project
¶ Reference to the global project object. When running a document with a
Testcase
component, an empty project item is created.
-
Testcase
test
¶ Reference to the owner test case. This property is available in
Testcase
components and in other stand-alone component definitions such as shown in the MakeProbe.qml example. It is not available in documents containing aProject
component.
QML data types¶
QML types for properties used in this reference documentation. Basic QML types are also explained in the QML language reference.
-
bool
¶ Boolean value. Can be either
true
orfalse
.
-
double
¶ 64 bit (double precision) floating point number.
-
int
¶ 32 bit signed whole number.
-
type
list
¶ List of QML objects. See also http://doc.qt.io/qt-5/qml-list.html
-
type
signal
¶ A reference to a signal attribute of a component. It is not a dedicated data type, but rather stored as
var
.signal
objects provide aconnect()
anddisconnect()
method to connect to a destination function. They are also functors and can be called like a function in order to invoke connected signal handlers.
-
type
string
¶ Free form text string. See also http://doc.qt.io/qt-5/qml-string.html
-
type
stringlist
¶ An array of strings. See also http://doc.qt.io/qt-5/qml-var.html
-
type
var
¶ Generic property type. Can hold any data type, but usually used for objects and arrays. See also http://doc.qt.io/qt-5/qml-var.html
Component Item¶
-
class
Component
¶ Base type for various dynamic items such as probes.
Locations: | Component , Testcase |
---|---|
Nested items: | Component ,
QtObject |
Inherited by: | ProcessProbe , PinProbe , SignalProbe ,
UniflashProbe |
Properties: | name |
Detailed Description¶
Component
is used as a base type for all kinds of dynamic items in test
cases such as probes and other helpers. Component
items may define their own
properties, methods, signals and signal handlers. All probe items are based upon
Component
.
Use this item whenever you want to implement re-usable components for the use in
Testcase
items.
Properties¶
-
string
name
¶ Default: typename-number Name of the component. When not set, Qst will deduce the final typename and add a counter so that the component is assigned a unique name. For instance, when implementing MyProbe.qml based on
Component
, the default name for probe items will be myprobe-x where x is a counter value.This value does currently only have an effect in error messages.
Depends Item¶
-
class
Depends
¶ Describes dependencies between
Testcase
items.
Locations: | Testcase |
---|---|
Properties: | alias , name |
Detailed Description¶
The Depends
defines a dependency on another test case specified by
name
. In its simplest form, it specifies only a precedence relation
as for instance in the following example:
import qst 1.0
Project {
Testcase {
name: "A"
function run() {}
}
// Has to wait until A completes.
Testcase {
name: "B"
Depends { name: "A" }
function run() {}
}
}
Accessing properties of dependencies¶
In the above example, test case B may want to access results and properties of
A. The Depends item attaches a reference of selected properties from A to
B. These properties are available in B through the
Testcase::dependencies
property as shown in the following example:
import qst 1.0
Project {
Testcase {
name: "A"
Exports {
id: exports
property string result
}
function run() {
exports.result = "excellent"
}
}
Testcase {
name: "B"
Depends {
name: "A"
}
function run() {
Qst.info("A was " + dependencies.A[0].result)
}
}
}
After completion of A, Qst copies the properties of the Exports
item over to B. Test case B can access them through the
dependencies
property. Only
basic QML types are considered for exporting
which avoids side effects.
Dependencies and tags¶
When being assigned to a Matrix
item, a testcase may be expanded to
multiple jobs. The Depends item allows to control which job instances of one
test case A
match which job instances of a test case B
. It comes in two
matching flavours. Consider the following Matrix
project:
import qst 1.0
Project {
Matrix {
Dimension {
board: [ "board-1", "board-2" ]
}
Dimension {
config: [ "debug", "release" ]
}
testcases: [
"A",
"implicit"
]
}
references: [
"explicit.qml",
"implicit.qml"
]
Testcase {
name: "A"
id: a
property string board
property string config
Exports {
id: exports
property string firmwarePath
}
function run() {
exports.firmwarePath = board + "-" + config + ".elf"
}
}
}
The project in depends-project-with-matrix.qml consists of 3 test cases, 2 of
which depend on a test case A
. The referenced test cases will be explained
in the following sub-sections.
Explicit matching¶
The Depends item specifies all tag keys of the depending test case. This matching type is always unambiguous and is especially useful when a non-tagged test case depends only on certain jobs of a tagged one. Example:
A
¶import qst 1.0
Testcase {
name: "explicit"
id: b
Depends {
name: "A"
board: [
"board-1",
"board-2"
]
config: "debug"
}
function run() {
var paths = dependencies.A.reduce(function(acc, value) {
acc += value.firmwarePath + " "
return acc
}, "")
Qst.info("depends on " + paths)
}
}
$ qst run -f depends-project-with-matrix.qml | grep -e explicit -e " A "
PASS, A 0000000 [ board-1 debug ],,,
PASS, A 0000001 [ board-2 debug ],,,
PASS, A 0000002 [ board-1 release ],,,
PASS, A 0000003 [ board-2 release ],,,
INFO, explicit, , explicit.qml:21, depends on board-1-debug.elf board-2-debug.elf
PASS, explicit,,,
Implicit matching¶
The Depends item specifies none of the tags of a depending test case. In this case, the matching behavior depends on whether the test case and the dependency are tagged or not. Non-tagged example:
implicit
(not tagged) depends on
all instances of A
(tagged).¶import qst 1.0
Testcase {
name: "implicit"
id: b
property string board
property string config
Depends {
name: "A"
}
function run() {
var paths = dependencies.A.reduce(function(acc, value) {
acc += value.firmwarePath + " "
return acc
}, "")
Qst.info("depends on " + paths)
}
}
$ qst run -f depends-project-with-matrix.qml | grep -e implicit -e " A "
PASS, A 0000000 [ board-1 debug ],,,
PASS, A 0000001 [ board-2 debug ],,,
PASS, A 0000002 [ board-1 release ],,,
PASS, A 0000003 [ board-2 release ],,,
INFO, implicit 0000004 [ board-1 debug ],, implicit.qml:19, depends on board-1-debug.elf
PASS, implicit 0000004 [ board-1 debug ],,,
INFO, implicit 0000005 [ board-2 debug ],, implicit.qml:19, depends on board-2-debug.elf
PASS, implicit 0000005 [ board-2 debug ],,,
INFO, implicit 0000006 [ board-1 release ],, implicit.qml:19, depends on board-1-release.elf
PASS, implicit 0000006 [ board-1 release ],,,
INFO, implicit 0000007 [ board-2 release ],, implicit.qml:19, depends on board-2-release.elf
PASS, implicit 0000007 [ board-2 release ],,,
B (not tagged) depends on A (not tagged): | |
---|---|
There is only a single instance of A and B . |
|
B (not tagged) depends on A (tagged): | |
There is only a single instance of B and
it matches all instances of A . |
|
B (tagged) depends on A (not tagged): | |
Every job instance of B matches the
same single instance of A . |
|
B (tagged) depends on A (tagged): | |
Every job instance of B matches all jobs
of A that have at least the same tags as
B . If A and B are in the same matrix,
then the resulting relationship is usually 1:1. |
Properties¶
-
string
alias
¶ The
name
may not be valid JavaScript identifier or multiple Depends items may reference the sameTestcase::name
. In this case, alias specifies the identifier under which exported values can be accessed through theTestcase::dependencies
property.This property must be a plain string and a valid JavaScipt identifer.
-
string
name
¶ The name of the depending test case. It must match with an existing
Testcase::name
.This property must be a plain string and cannot be empty.
Dimension Item¶
-
class
Dimension
¶ Defines a value span within a
Matrix
.
Locations: | Matrix |
---|
Detailed Description¶
The Dimension
item defines a span of one or more property values. It can
only exist in a Matrix
context. The size of a Dimension
is
determined by its values. The item does not have any predefined properties and
it is not intended to declare new properties using the property
keyword.
Instead, it is enough to write a property name and assign values to it.
The property name must be present in all test cases that the
Matrix
is applied to. If the test case does not have a property
with that name, an error is thrown.
The values must be supplied either in an array with a defined length or as a trivial type.
Single array¶
A typical Dimension
component defines a single property in array format:
Matrix {
testcases: "*"
Dimension {
mcu: [
"cc1312R1",
"cc1352R1",
"cc1352P1",
]
}
}
Multiple arrays¶
It is also possible to define multiple arrays in one dimension as long as they have equal length. The values are read as tuples, for instance:
Dimension {
mcu: [
"cc1312R1",
"cc1352R1",
"cc1352P1",
]
board: [
"CC1312R1_LAUNCHXL",
"CC1352R1_LAUNCHXL",
"CC1352P1_LAUNCHXL"
]
}
results in the tag pairs:
Testcase { mcu: "cc1312R1"; board: "CC1312R1_LAUNCHXL"
Testcase { mcu: "cc1352R1"; board: "CC1352R1_LAUNCHXL"
Testcase { mcu: "cc1352P1"; board: "CC1352P1_LAUNCHXL"
Arrays and trivial values¶
For convenience it is possible to shrink arrays with identical values as long as
the Dimension
contains an array that determines its length:
Dimension {
mcu: [
"cc1312R1",
"cc1352R1",
"cc1352P1",
]
family: "cc13x2" // cloned 3 times
}
The above Dimension
results in:
Testcase { mcu: "cc1312R1"; family: "cc13x2" }
Testcase { mcu: "cc1352R1"; family: "cc13x2" }
Testcase { mcu: "cc1352P1"; family: "cc13x2" }
References and complex expressions¶
References to other properties are allowed as well as referencing the whole array:
Matrix {
id: matrix
testcases: "*"
property var animals: {
var values = []
values.push("cat")
values.push("dog")
return values
}
property string color: "white"
Dimension {
animal: matrix.animals
}
Dimension {
attribute: [
"brown",
matrix.color
]
}
}
It is currently only possible to evaluate JavaScript expressions by referencing other properties. The following example does not work:
// Not supported
Dimension {
animals: {
var values = []
values.push("cat")
values.push("dog")
return values
}
}
DurationConstraint Item¶
-
class
DurationConstraint
¶ Checks the time between two signal occurrences.
Inherits: | Component |
---|---|
Properties: | beginOn , duration , enabled
endOn , evaluateOnFinished ,
evaluateOnValidation , maxDuration ,
minDuration . timedOut , valid |
Methods: | begin() , end() |
Detailed Description¶
DurationConstraint
measures the time between two signals
beginOn
and endOn
. The methods begin()
or end()
may be used as an alternative if no signals are available.
The expected duration is configured with minDuration
and
maxDuration
.
The constraint has two stages: validation and evaluation. Validation happens
immediately after the endOn
signal has fired. In the same moment,
the duration
property is updated and shows the measured duration.
Whether the duration is within the expected range, can be seen at the property
valid
.
During the evaluation stage, it is decided whether the test case is aborted.
Evaluation can either happen immediately after validation
(evaluateOnValidation
is true
) or just before the
Testcase::finished()
event (evaluateOnFinished
is
true
). The enabled
property switches measurement completely on
and off.
Example for measuring the duration between two signals:
import qst 1.0
Testcase {
ProcessProbe {
id: process
command: "sleep"
arguments: [ 3 ]
}
DurationConstraint {
id: constraint
minDuration: 2.9
maxDuration: 3.1
beginOn: process.started
endOn: process.finished
}
function run() {
process.start()
Qst.wait(4000)
}
Example for monitoring a sequence of actions:
import qst 1.0
Testcase {
DurationConstraint {
id: constraint
minDuration: 5
maxDuration: 10
}
function run() {
constraint.begin()
// Now do something very time consuming...
Qst.wait(20); // will be aborted because constraint
// is violated after 10 ms.
}
Properties¶
-
signal
beginOn
¶ Default: undefined Starts a measurement action. This property must either be QML signal or an object that defines a
connect()
method with a signal handler as parameter. When updating this property, the old signal will be disconnected.
-
bool
enabled
¶ Default: true
When
false
, the signalsbeginOn
andendOn
do not have any effect and the constraint is neither validated nor evaluated.
-
signal
endOn
¶ Default: undefined Ends a measurement cycle and triggers validation. This property must either be QML signal or an object that defines a
connect()
method with a signal handler as parameter. When updating this property, the old signal will be disconnected.
-
bool
evaluateOnFinished
¶ Default: false If
true
, the constraint will be evaluated by Qst just beforeTestcase::finished()
.See also
evaluateOnValidation
-
bool
evaluateOnValidation
¶ Default: true If
true
, the test case will fail immediately when validation fails. Iffalse
, then the constraint will not be evaluated immediately. Instead, it will be evaluated onTestcase::finished()
.See also
evaluateOnFinished
-
double
maxDuration
¶ Default: 0.0 Specifies the maximum allowed time between
beginOn
andendOn
. The value must be greater or equalminDuration
.See also
minDuration
-
double
minDuration
¶ Default: 0.0 Specifies the minimum allowed time between
beginOn
andendOn
. The value must be less or equalmaxDuration
.See also
maxDuration
Exports Item¶
-
class
Exports
¶ Forwards data to dependent
Testcase
items.
Locations: | Testcase |
---|
Detailed Description¶
The Exports item helps the surrounding test case to forward results and additional data to dependent test cases. It requires a Depends item on the other side to access the forwarded results. Together, the Exports and the Depends item form a dataflow graph. The Exports item does not have any built-in properties. Here is an example:
import qst 1.0
Project {
Testcase {
name: "A"
Exports {
id: exports
property string result
}
function run() {
exports.result = "excellent"
}
}
Testcase {
name: "B"
Depends {
name: "A"
}
function run() {
Qst.info("A was " + dependencies.A[0].result)
}
}
}
After completion of A, Qst copies the properties of the Exports
item over to B. Test case B can access them through the
dependencies
property. Only
basic QML types are considered for exporting
which avoids side effects.
Matrix Item¶
-
class
Matrix
¶ Replicates
Testcase
components with different property values.
Locations: | Project , Testcase , document root |
---|---|
Nested items: | Dimension |
Properties: | testcases |
Detailed Description¶
The Matrix
item allows to implement data-driven tests and to separate
implementation from input data. It spans a space of values based on one or more
Dimension
items. The resulting value combinations are called tags. Each tag
may be applied to one or more test cases depending on the
testcases
property.
import qst 1.0
Project {
Matrix {
Dimension {
animal: [
"cat",
"dog"
]
}
Dimension {
does: [
"moans",
"bites"
]
}
testcases: [ "tagged-test" ]
}
Testcase {
name: "tagged-test"
property string animal
property string does
function run() {
Qst.info("The " + animal + " " + does + ".")
}
}
Testcase {
name: "normal-test"
function run() {}
}
}
The Matrix
component in matrix-project.qml has two dimensions, each
containing an array of length 2. Thus, the matrix expands to 4 different tag
combinations:
dog bites | dog moans |
cat bites | cat moans |
Matrix execution¶
A tagged test case is re-executed for each tag and every execution entity is called a job. The job order is generally undefined. Tagging has consequences on the test case’s execution:
- The test case name in the command line output is followed by the tag data and a hash of the tag data.
- The test case’s working directory name is expanded with the hash.
Above matrix-project.qml example results in the following output on command line:
$ qst run -f matrix-project.qml
PASS, normal-test,,,
INFO, tagged-test 1ms2r6i [ cat moans ], , /matrix-project.qml:27, The cat moans.
PASS, tagged-test 1ms2r6i [ cat moans ],,,
INFO, tagged-test 17tca19 [ dog bites ], , /matrix-project.qml:27, The dog bites.
PASS, tagged-test 17tca19 [ dog bites ],,,
INFO, tagged-test 0ni1i5d [ cat bites ], , /matrix-project.qml:27, The cat bites.
PASS, tagged-test 0ni1i5d [ cat bites ],,,
INFO, tagged-test 07cs7hy [ dog moans ], , /matrix-project.qml:27, The dog moans.
PASS, tagged-test 07cs7hy [ dog moans ],,,
Matrix in Project
and in Testcase
¶
A Matrix
can be defined on two levels: on project level and on test case
level. When defined in project scope, the testcases
property
specifies, to which test cases the Matrix
applies. When defined inside a
Testcase
item, the Matrix
implicitly applies to the surrounding
test case only.
import qst 1.0
Project {
Matrix { ... }
Testcase { ... }
Testcase { ... }
Testcase { ... }
Testcase { ... }
}
import qst 1.0
Testcase {
Matrix { ... }
}
Multiple matrices and overlap¶
It is possible to define multiple Matrix
components both on
Project
and Testcase
level and it is even allowed for
different matrices to attach their tags to the same test cases. However, the
resulting tag combinations must be distinct and must not shadow each other so
that every job can be clearly identified by the combination of test case name
and tags.
Testcase { color: "red" }
would map to 3 different jobs.¶// Matrices shadow each other.
Matrix {
testcases: "*"
Dimension {
color: [ "red", "blue" ]
}
}
Matrix {
testcases: "*"
Dimension {
color: [ "red", "blue" ]
}
Dimension {
speed: [ "fast", "slow" ]
}
}
// Matrices are compatible.
Matrix {
testcases: "*"
Dimension {
color: [ "orange", "green" ]
}
}
Matrix {
testcases: "*"
Dimension {
color: [ "red", "blue" ]
}
Dimension {
speed: [ "fast", "slow" ]
}
}
Properties¶
-
stringlist
testcases
¶ Default: empty list A list of test case names that the matrix is applied to. Entries may contain exact names as well as the wildcard characters
*
(match any string) and?
(match any character). Duplicate entries are ignored.Example:
testcases : [ "sometest", // Matches only "sometest" "test-*", // Matches any testcase starting with "test-" "tc-??", // Matches any testcase starting with "tc-" followed // by 2 letters. ]
This property is not writable when
Matrix
is defined inside aTestcase
component as the matrix then implicitly applies to the surrounding test case only.
PinProbe Item¶
-
class
PinProbe
¶ Represents a digital IO pin on the launchpad probe board.
Inherits: | Component |
---|---|
Enumerations: | PullMode , Type , Value |
Properties: | ioid , port , pullMode ,
type , value |
Detailed Description¶
A PinProbe component represents an IO pin on the launchpad probe board. It can be used to physically interface Qst to a Device Under Test (DUT) and stimulate/analyse digital hardware signals.
Each PinProbe item can be configured either as input or output. Additional
pull-up or pull-down resistors may be activated for inputs. The output state is
set by writing to the output
property and events on the probe wire can be
observed by attaching a signal handler to the valueChanged()
signal.
Example:
import qst 1.0
// Assuming a DUT with an LED and a button and two wires of a
// launchpad probe board attached.
// On a falling edge of the button IO, the LED shall be turned on.
Testcase {
name: "test-app"
property string port: "ttyACM3"
PinProbe {
id: button
port: test.port
type: PinProbe.Write
value: PinProbe.High
}
PinProbe {
id: led
port: test.port
type: PinProbe.Read
onValueChanged: {
Qst.info("The LED value is now " + led.value);
}
}
function run() {
Qst.wait(50);
Qst.compare(led.value, PinProbe.Low, "LED should be off but is on");
// Stimulate button press
button.value = PinProbe.Low;
Qst.wait(5);
Qst.compare(led.value, PinProbe.High, "LED should be on but is off");
}
}
PinProbe currently only emits the valueChanged()
signal. All other
properties are assumed to be constant during application life time.
Enumerations¶
-
enum
Type
¶ Configures the pin direction.
-
enumerator
Read
¶ Configures the pin as input.
-
enumerator
Write
¶ Configures the pin as output.
-
enumerator
Properties¶
-
int
ioid
¶ Default: 0 Specifies the IO identifier on the probe board. The range is usually 0..31, but not all IOs might be available.
-
string
port
¶ Default: empty The serial port identifier of the probe board. On Windows, this is usually
COMx
while on Linux systemsttyACMx
orttyUSBx
is commonly used.See also
Xds::portFromSerial()
-
PullMode
pullMode
¶ Default: PullMode::PullDisabled
Configures the pin access direction. When configured to
Type::Read
, the pin probe will detect negative and positive edges on the pin.
-
Type
type
¶ Default: Type::Read
Configures the pin access direction. When configured to
Type::Read
, the pin probe will detect negative and positive edges on the pin.
-
Value
value
¶ Default: Value::Undefined
The current state of the pin. The property can be read from and written to. A write has no effect when the pin is configured as
Type::Read
. Although defined as an enumerator, values are implicitly converted to integers and booleans.
ProcessProbe Item¶
-
class
ProcessProbe
¶ Starts and watches processes.
Inherits: | Component |
---|---|
Enumerations: | ProcessError . State |
Properties: | arguments , exitCode , program
state , workingDirectory |
Methods: | readAllStandardError() , readAllStandardOutput()
start() , terminate() , waitForFinished()
waitForStarted() |
Signals: | errorOccurred() , started() , finished() |
Detailed Description¶
ProcessProbe
can invoke external applications and communicate with them. It
mirrors the API of QProcess.
The process to run is defined by the program
property. Arguments
are provided as a string list in the arguments
property.
Example:
import qst 1.0
Testcase {
ProcessProbe {
id: make
program : (Qst.hostOs === "windows") ? "gmake.exe" : "make"
arguments: [
"-j",
"8"
]
}
function run() {
make.start();
make.waitForFinished(1701);
Qst.compare(make.exitCode, 0, "Make did not succeed");
}
}
Enumerations¶
-
enum
ProcessError
¶ Error events during process execution. Further information may be obtained with
errorString()
.-
enumerator
Crashed
¶ The process crashed some time after starting successfully.
-
enumerator
FailedToStart
¶ The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.
-
enumerator
ReadError
¶ An error occurred when attempting to read from the process. For example, the process may not be running.
-
enumerator
Timedout
¶ The last waitFor…() function timed out. The state of
ProcessProbe
is unchanged, and you can try calling waitFor…() again.
-
enumerator
WriteError
¶ An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.
-
enumerator
UnknownError
¶ An unknown error occurred.
-
enumerator
Properties¶
-
stringlist
arguments
¶ Process arguments in list format. Unlike on a shell, spaces do not separate arguments and thus, each argument must be a separate list entry. Escaping is required for arguments containing spaces.:
// Wrong arguments: [ "--file My\ File.txt " ] // Correct arguments: [ "--file", "My File.txt" ]
-
integer
exitCode
¶ The exit code of the last process that finished. This property is read-only.
Methods¶
-
string
readAllStandardError
()¶ This function returns all data available from the standard error of the process.
-
string
readAllStandardOutput
()¶ This function returns all data available from the standard output of the process.
-
void
start
()¶ Starts the process set by
program
with the arguments given byarguments
. This function returns immediately.
-
void
terminate
()¶ Attempts to terminate the process.
-
bool
waitForFinished
(int milliseconds)¶ Blocks until the process has finished and the
finished()
signal has been emitted, or until milliseconds have passed.Returns
true
if the process finished; otherwise returnsfalse
(if the operation timed out, if an error occurred, or if this process is already finished).If milliseconds is -1, this function will not time out.
Signals¶
-
void
errorOccurred
(ProcessError error)¶ An error has occurred during execution. A human-readable version of the error may be obtained with
errorString()
.
-
void
finished
()¶ This signal is emitted when the process finishes.
exitCode
is the exit code of the process (only valid for normal exits). After the process has finished, the buffers in QProcess are still intact. You can still read any data that the process may have written before it finished.
-
void
started
()¶ This signal is emitted by
ProcessProbe
when the process has started, andstate
isState::Running
.
Project Item¶
Locations: | document root |
---|---|
Nested items: | Matrix , Testcase |
Properties: | name , references ,
workingDirectory |
Detailed Description¶
A Project
item represents a collection of of test cases. Test cases can be
defined in two ways:
in-line
Usually used for a bunch of trivial test cases with only few lines or if complex test cases are instantiated multiple times with slightly different configuration.
The test cases are executed in undefined order.
Example in-line project:
Project { name: "inline-project" Testcase { name: "trivial-1" function run() { // Qst.verify(...) } } // Assuming that ComplexTestcase.qml exists in the current // directory ComplexTestcase { name: "complex-1"; config: "something" } ComplexTestcase { name: "complex-2"; config: "something-else" } }as references
Usually used in non-trivial projects. Test cases are defined in their own files and then referenced by the main project file. Any property
prop
attached to the project item is available in sub-items asproject.prop
.The execution order is defined by their occurrence order in the
references
item.Example references project:
Project { name: "referencing-project" property string someProperty: "sometext" // someProperty is available in all test cases as // project.someProperty references: [ "testcase1.qml", "testcase2.qml" ] }
Properties¶
-
stringlist
references
¶ Default: empty list A list of files containing test cases. Test cases are executed in the specified order. Paths are relative to the project file unless an absolute path is provided:
references : [ "testcase-1.qml", // Path relative to the project file "/path/to/testcase-2.qml" // Absolute file path ]
SignalProbe Item¶
-
class
SignalProbe
¶ Watches signals from other items.
Inherits: | Component |
---|---|
Properties: | condition , count , signal |
Methods: | clear() , connect() |
Signals: | triggered() |
Detailed Description¶
SignalProbe
can be used to watch signals of other items. A typical use-case
is a counter for asynchronous events:
import qst 1.0
import QtQml 2.0 as QtQml
Testcase {
QtQml.Timer {
id : timer
interval: 5
periodic: true
}
SignalProbe {
id: probe
signal: timer.triggered
}
function run() {
Qst.compare(probe.count, 0, "Timer triggered too early");
timer.start();
Qst.wait(50);
timer.stop();
Qst.verify(probe.count >= 10, "Timer triggered only "
+ probe.count + " times");
}
The following example shows, how SignalProbe
can be used, to attach to a
signal that is not directly accessible:
import qst 1.0
Testcase {
property var pinProbe : PinProbe {
// properties
// ...
// Can attach directly to the valueChanged() signal.
onValueChanged: {
Qst.info("pin value is " + pinProbe.value)
}
}
}
import qst 1.0
BaseTestcase {
// Cannot attach directly to pinProbe's valueChanged() signal.
// Use SignalProbe instead.
SignalProbe {
signal: pinProbe.valueChanged
onTriggered: {
Qst.info("pin value is " + pinProbe.value)
}
}
}
Properties¶
-
bool
condition
¶ Default: true A guard for
signal
. Whentrue
, incoming signals increment the counter and emittriggered()
. Whenfalse
, the incoming signal is ignored.
-
Signal
signal
¶ A signal of another item to attach to during the creation stage.
Methods¶
-
void
connect
(signalHandler)¶ Connects the
triggered()
signal to a signalHandler of another item. This makesSignalProbe
look like a QML signal for the other item.Example:
DurationConstraint { from: SignalProbe { signal: someItem.someSignal } to: someOtherSignal }
In this example,
DurationConstraint
tries to connectSignalProbe
to itself by callingconnect()
. It doesn’t know thatSignalProbe
is an item and not a plain QML signal.
Testcase Item¶
-
class
Testcase
¶ Implements a test action.
Locations: | Project , document root |
---|---|
Nested items: | Component , Depends , Exports ,
Matrix |
Enumerations: | Result |
Properties: | dependencies , elapsedTime , name ,
result , workingDirectory |
Methods: | run() , |
Signals: | created() , destruction() , finished() ,
started() |
Detailed Description¶
A Testcase component combines probes, constraints and other QML components
into a single test case. It is executed as one atomic entity. Every test case
must have a unique name throughout the project and must implement a
run()
method.
Example:
import qst 1.0
Testcase {
name: "test-myprocess"
ProcessProbe {
id: process
command: "/usr/bin/echo"
arguments: [
"Hello World"
]
}
function run() {
process.start();
process.waitForFinished(100);
Qst.compare(process.readAllStandardOutput(), "Hello World");
// Testcase will finish with result 'Pass'
}
}
Enumerations¶
Properties¶
-
var
dependencies
¶ When the test case contains a
Depends
items, this property makes exported values for every dependencyname
oralias
accessible. Data forwarded byExports
can be accessed in bindings and code. Dependencies are always attached in list form beause a test case might be represented by multiple jobs:simple-exports.qml¶Depends { name: "A" } function run() { Qst.info("A was " + dependencies.A[0].result) }
This property is read-only.
-
uint64
elapsedTime
¶ Time in milliseconds since the test case was started.
This property is updated on every read access and cannot be used as a binding.
-
string
name
¶ Identifier for this test case. This property must be a plain string and must be unique across the whole project.
The default value is an empty string.
-
Result
result
¶ The outcome of a test case run. The default value is
Result::Unfinished
.
-
const string
workingDirectory
¶ A unique directory where the current test case and child components may store files. The directory may be used for log files or as scratch pad and is always created on execution start.
The default value is
project.workingDirectory + "/" + name
and cannot be changed by the test case.
Methods¶
-
void
run
()¶ Contains the execution code and is called when the test case starts. It has to be implemented by the user. The
run()
method may contain several other blocking calls to methods and functions. It will return only for two reasons:- All statements have been executed.
result
will be set toResult::Pass
. - An error has occurred or a constraint has failed and
result
has been set toResult::Fail
. In that case, all remaining statements are aborted.
- All statements have been executed.
Signals¶
-
void
created
()¶ This signal is emitted after the
destruction()
signal of the previousTestcase
and beforestarted()
of the current one. It is the QML way of implementing a constructor and can be used to initialize resources.The signal is also attached to every
Component
asTestcase.created()
.
-
void
destruction
()¶ This signal is emitted before the
Testcase
component is physically destroyed and may be used to free up resources.The signal is also attached to every
Component
asTestcase.destruction()
.
-
void
finished
()¶ This signal is emitted after the
run()
function has returned and may be used for final evaluation or cleaning up. By that time,result
may not have been set, yet and thus, it is still allowed to call verification functions.The signal is also attached to every
Component
asTestcase.finished()
.
UniflashProbe Item¶
-
class
UniflashProbe
¶ Flash programmer interface for Texas Instruments MCUs.
Inherits: | Component |
---|---|
Properties: | device , file , installPath
programmer , serial |
Methods: | flash() , waitForFinished() |
Signals: | finished() |
Detailed Description¶
UniflashProbe
provides a convenient interface to Texas Instruments’
Uniflash. It can be used to read from and
write to MCUs via a JTAG programmer.
The current state is experimental. Only XDS110 is supported. Since Uniflash doesn’t have a meaningful command line interface, XML config files are hacked together.
Example:
import qst 1.0
import ti 1.0
Testcase {
UniflashProbe {
id: uniflash
installPath: "C:\ti\uniflash_4.2"
serial: Xds.availableSerials()[0]
device: "cc1352r1f3"
file: test.workingDirectory + "/myApp.out"
}
void run() {
uniflash.flash();
uniflash.waitForFinished(10000);
}
}
See also Xds
.
Properties¶
Methods¶
-
void
flash
()¶ Writes
file
to adevice
connected viaprogrammer
. Performs a board reset afterwards.The method returns immediately and the programming process executes in background. When done, the
finished()
signal is raised.
-
bool
waitForFinished
(int milliseconds)¶ Blocks until the current operation has finished and the
finished()
signal has been emitted, or until milliseconds have passed.Returns
true
if the process finished; otherwise returnsfalse
(if the operation timed out, if an error occurred, or if this process is already finished).If milliseconds is -1, this function will not time out.
ValueRangeConstraint Item¶
-
class
ValueRangeConstraint
¶ Checks whether a property is in a certain range.
Inherits: | Component |
---|---|
Properties: | enabled , evaluateOnFinished ,
evaluateOnValidation , maxValue
minValue , valid , value |
Detailed Description¶
ValueRangeConstraint
checks whether value
is within a range
given by minValue
and maxValue
.
The constraint has two stages: validation and evaluation. Validation happens
immediately after the value
property has changed. Whether
value
is within the expected range, can be seen at the property
valid
.
During the evaluation stage, it is decided whether the test case is aborted.
Evaluation can either happen immediately after validation
(evaluateOnValidation
is true
) or just before the
Testcase::finished()
event (evaluateOnFinished
is
true
). The enabled
property switches measurement completely on
and off.
Example for measuring the duration between two signals:
import qst 1.0
import QtQml 2.0 as QtQml
Testcase {
QtQml.Timer {
id: timer
repeat: true
interval: 123
onTriggered: adc.start
}
AdcProbe {
id: adc
ioid: 23
}
ValueRangeConstraint {
id: constraint
minValue: 100
maxValue: 300
value: adc.value
}
function run() {
timer.start
Qst.wait(4000)
}
Properties¶
-
bool
enabled
¶ Default: true
When
false
, thevalue
property does not have any effect and the constraint is neither validated nor evaluated.
-
bool
evaluateOnFinished
¶ Default: false If
true
, the constraint will be evaluated by Qst just beforeTestcase::finished()
.See also
evaluateOnValidation
-
bool
evaluateOnValidation
¶ Default: true If
true
, the test case will fail immediately when validation fails. Iffalse
, then the constraint will not be evaluated immediately. Instead, it will be evaluated onTestcase::finished()
.See also
evaluateOnFinished
File Service¶
-
class
File
¶ Provides access to the file system.
Methods: | exists() |
---|
Detailed Description¶
The File
service provides information about the file system and limited
access to file system operations.
Qst Service¶
-
class
Qst
¶ Drives test case execution and provides information about the environment.
Properties: | hostOs |
---|---|
Methods: | compare() , error() , info() ,
verify() , wait() |
Detailed Description¶
The Qst
service is an integral part of Qst. It contains methods for test
evaluation evaluation and provides information about test case execution and the
host environment.
Qst
is a singleton type and cannot be instantiated as a QML component.
Properties¶
Methods¶
-
void
compare
(variant actual, variant expected, string message)¶ Compares an actual value to an expected value. If actual and expected are identical, execution continues. If not, a failure is recorded in the test log and the test won’t be executed further. The string message is optional. If not set, a default message is created.
Both values may be of any basic QML basic type. Arrays are compared by their containing values. Objects are compared by each property.
When
compare()
fails during test case execution, the currentTestcase
aborts immediately, the result is set toTestcase::Result::Fail
and Qst proceeds with the next test case. When failing before the first test case starts, for instance in aProject
item, Qst exits and no test case will be executed at all.
-
void
error
(string message, string file, int line)¶ Throws an error with message and aborts the current test case.
The parameters file and line are optional. If omitted, Qst takes those from the top of the caller stack.
-
void
info
(variant message)¶ Prints message in the test log output. The parameter message can be anything that converts implicitly into a string.
-
void
verify
(bool condition, string message)¶ Checks whether the condition is true or not. If it is true, execution continues. If not, a failure is recorded in the test log and the test won’t be executed further.
When
verify()
fails during test case execution, the currentTestcase
aborts immediately, the result is set toTestcase::Result::Fail
and Qst proceeds with the next test case. When failing before the first test case starts, for instance in aProject
item, Qst exits and no test case will be executed at all.
-
void
wait
(int ms)¶ Waits for ms milliseconds. While waiting, events will be processed and the test stays responsive.
This function should be only used inside
Testcase::run()
. It is not recommended to call it in binding expressions.
TextFile Service¶
-
class
TextFile
¶ Allows to read from and write into text files.
Enumerations: | OpenMode |
---|---|
Methods: | TextFile::TextFile() , atEndOfFile() ,
close() , readAll() , readLine() ,
truncate() , write() , writeLine() |
Detailed Description¶
The TextFile
service provides convenient access to text files in Javascript
context. For instance, within Testcase::run()
:
function run() {
// ...
var file = new TextFile(test.workingDirectory + "/hello.txt",
TextFile.WriteOnly, "UTF-8");
file.write("Hello World");
file.close();
// ...
}
TextFile
is to be used in Javascript context only and cannot be instantiated
as a QML component.
Enumerations¶
-
enum
OpenMode
¶ Specified an access qualifier for the file. Options may be OR’ed togther:
new TextFile(path, TextFile.ReadWrite | TextFile.Append, "UTF-8");
-
enumerator
Append
¶ The file is opened for appending text. This is option may be combined with
WriteOnly
.
-
enumerator
ReadOnly
¶ Opens the file for read access only. Several instances may open the file in read-only mode at the same time.
-
enumerator
ReadWrite
¶ Opens the file for read and write access.
-
enumerator
WriteOnly
¶ Opens the file for write access only.
-
enumerator
Methods¶
-
TextFile
(string filePath, OpenMode mode, string codec)¶ Constructs a
TextFile
object and opens the file filePath with mode access permission and using a text codec specified by codec.The filePath must be an absolute path. Options for codec are the same as for QTextCodec, for instance “UTF-8”, “UTF-16”, “ISO 8859-1” and others.
The default value for mode is
OpenMode::ReadWrite
. The default value for codec is “UTF-8”.
-
bool
atEndOfFile
()¶ Returns
true
if no more data can be read from the file,false
otherwise.
-
void
close
()¶ Closes the file. It is recommended to always call this function as soon as you are finished with the file, in order to keep the number of in-flight file descriptors as low as possible.
-
string
readLine
()¶ Reads one line of text from the file and returns it. The returned string does not contain the newline characters.
-
void
truncate
()¶ Truncates the file. Sets the file size to zero and removes all content.
Xds Service¶
-
class
Xds
¶ Helper for XDS-based debugging interfaces.
Methods: | availableSerials() , portFromSerial() |
---|
Detailed Description¶
The Xds
service provides convenience functions for XDS-based debugging
interfaces. It can be used, for instance, to identify connected debuggers.
The following example assumes that there is only a single XDS debugger connected and deduces it’s serial port identifier.
import qst 1.0
import ti 1.0
Project {
property string launchpadPort: {
var serials = Xds.availableSerials();
Qst.compare(serials.length, 1,
"Either no or too many probe boards connected");
return Xds.portFromSerial(serials[0]);
}
}
Xds
is a singleton type and cannot be instantiated as a QML component.
Language items
Name | Description |
---|---|
Component | Base type for various dynamic items. |
Depends | Describes dependencies between Testcase items. |
Dimension | Defines a value span within a Matrix . |
Exports | Forwards data to dependent Testcase items. |
Matrix | Replicates Testcase components with different property values. |
Project | Container item for multiple Testcase items. |
Testcase | Implements a test action. |
Convenience items
Name | Description |
---|---|
DurationConstraint | Checks the time between two signal occurrences. |
PinProbe | Represents a digital IO pin on the launchpad probe board. |
SignalProbe | Watches signals from other items. |
ProcessProbe | Starts and watches processes. |
UniflashProbe | Flash programmer for Texas Instruments MCUs. |
ValueRangeConstraint | Checks whether a property is in a certain range. |
Services
Name | Description |
---|---|
File | Provides access to the file system. |
Qst | Helper functions for test execution. |
TextFile | Reads from and writes into text files. |
Xds | Represents XDS-based debugging interfaces. |