SlideShare une entreprise Scribd logo
1  sur  51
QtTest
Unit Testing Framework
Justin Noel
Senior Consulting Engineer
ICS, Inc.
Qt is the Kitchen Sink Toolkit
• Qt comes with just about everything you need
• SQL, Sockets, XML, GUI, etc
• Often one of the challenges of using Qt is knowing all the
modules
• And what they do!
• This is ICS performs these webinars!
• Qt comes with it’s own Unit Testing Framework
• QtTest
Types of Testing
• Unit Testing
• Test one discrete area of the software
• Usually on a class basis. Think “Test Piston Rod”
• Tests can be written and performed as code is developed
• White box tests. Often written by developers
• “Does the software perform as the developer intended?”
• Functional Testing
• Tests subsystems of the whole software system
• Usually a group of classes. Think “Test Engine”
• Tests can be preformed once subsystem is wired together
• Tests interaction between specific groups of units
• “Does the software work together?”
Types of Testing
• System Testing
• End to end testing of the whole software system
• Sometimes includes actual hardware. Think “Test Car”.
• Tests are written late in project
• Because of the end to end nature.
• Black box tests. Often written by separate SQA team
• “Does the software do right thing?”
Test Frameworks for Qt
• QTest / QTest-QML
• Unit testing framework that comes with Qt
• Qt specific functionality
• Can test blind signals. Can simulate mouse and key events.
• Qt specific features can be used outside of QTest framework
• Google Test
• Unit testing framework from Google
• Unique ability to do “Isolated Testing” via Google Mock
• Requires “Inversion of Control” pattern
• Squish
• Playback / Record frame work for “end to end” system testing.
• Used for System Testing
Benefits of Unit Testing
• Test Early!
• Find errors while code is actively being developed
• Rather than long investigations during system testing
• Test Often!
• Run unit tests per commit. Or even pre-commit!
• Any failures must have been introduced by this 200 lines of code!
• Test for Regressions!
• Did new functionality or bug fixing break existing functionality?
• What tests failed?
• Did a code change re-introduce a bug?
• Every bug can have it’s own set of unit tests.
Design for Testability
• Your code must be testable!
• There are design techniques to help make your code more testable
• Try not to add functions to production code just for tests
• Subclassing for tests is acceptable (.ui file members)
• Isolation of units is your primary goal
• Can I test just this class?
• Without re-testing lower level classes?
• Also think about error conditions
• Some may be hard to produce in production environments
• Can I stimulate a bad MD5 error?
• Socket disconnects?
• Default switch cases?
Build Application as Libraries
• Building the bulk of your application as a set of libraries
increases testability
AppBackend.dll
App.exe
(main.cpp)
AppUi.dll
BackendTests.exe UiTests.exe
C++ Test Fixtures QML Test Fixtures
Layered Design
• A layered design is more testable
• Easy to isolate lower layers for testing
• Test Communications without Data, Presentation or Visualization
• No upwards dependencies
• Hard downward dependencies
Visualization Layer (QML)
Presentation Layer (QObjects)
Data Layer (Local Data Storage)
Communications Layer (TCP)
Calls
Down
Signals
Up
Break Downward Dependencies
• Dependency injection works well
• An Inversion of Control Pattern
• Classes take their dependencies as constructor arguments
• Classes do not construct any members themselves
• Loose coupling with signals and slots also works well
• Classes interface to each other via signals and slots only
• 3rd class wires say the UI classes to the Backend classes
• Lets you substitute a test fixture object for a dependency
object
• Instead of an actual production object.
Why is isolation important?
• Avoids testing the same code over and over
• You have already tested the data model
• Why do the UI tests need to also test the model?
• This will make your tests run very quickly
• If there is a failure in a low level class it won’t trigger errors in higher
level tests
• Avoid testing side effects
• Tests can be implementation agnostic
• DB, Files, Cloud. Shouldn’t matter for UI tests.
• Tests should only depend on interfaces, not behavior
EE Analogy: Motor Controller Test
Motor Controller
7408 AND
Momentary
Switch
Safety
Interlock
Motor
1
2
3
Stimulus: Apply PowerVerify: High or Low
QtTest is a unit testing framework
• QtTest comes with classes to build test fixtures for units
• Has some “special sauce” for Qt
• Test signals without needing to write slots (QSignalSpy)
• Simulate user events (MousePress, KeyPress, FocusIn, etc)
• QtTest is not an isolation framework
• You will have to make replacement classes for dependencies
yourself
• These are usually referred to as Mock Classes.
• Next month we will talk about Google Mock which is can help a lot
with isolation framework.
Creating a Test Fixture
• Can be implemented inside a source file
• No need for a header file
• Inherit from QObject
• Qt uses introspection to deduce test functions
• Private slots are test functions
• There are some reserved function names
• Use Q_TEST_MAIN macro to generate a main()
• Or create you own main.cpp to run multiple test fixtures
Creating a Test Fixture
#include <QtTest>
class TestQString: public QObject
{
Q_OBJECT
private slots:
void toUpper() {
QString str = "Hello"; // Prepare
str = str.toUpper(); // Stimulate
QCOMPARE(str, QString("HELLO")); // Verify
}
};
QTEST_MAIN(TestQString)
#include “testqstring.moc”
Test Fixture Project
QT += testlib # Plus libs your uses.
CONFIG += testcase # Creates make check target
SOURCES += TestQString.cpp
qmake
make
make check
********* Start testing of TestQString *********
Config: Using QtTest library %VERSION%, Qt %VERSION%
PASS : TestQString::initTestCase()
PASS : TestQString::toUpper()
PASS : TestQString::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped
********* Finished testing of TestQString *********
Running Multiple Tests
#include “QTestString.h” // Easier if you use a header file
int main(int argc, char** argc)
{
bool success = true;
r &= QTest::qExec(TestQString(), argc, argv);
...
return success;
}
Initializing and Cleaning Up
class TestQString: public QObject
{
Q_OBJECT
private slots:
void initTestCase() { // Called before ALL tests. }
void cleanupTestCase() { // Called after ALL tests}
void init() { // Called before each test. }
void cleanup() { // Called after each test }
void toUpper();
void toLower();
};
Writing Good Tests
• Test one thing at a time
• It’s tempting to get as much done in one function as you can.
• This makes one verification depend on another verification
• Tests will be brittle and changes to code could break lots of
verifications
• Do not have your tests depend on each other
• Order should not matter!
• Not depending on other tests will help you when you remove
functionality.
• You do not want to have to fix a cascading waterfall of tests!
Use New Object For Each Test
• Use init()
• Create your Object Under Test
• Plus whatever dependencies it has
• Production dependencies
• Or Test dependencies like Mock Classes
• Use cleanup()
• Do not be sloppy and leak memory in you tests.
• Your tests should run clean under Valgrind
• Aside for some suppressions for FreeType and FontConfig
Use New Object For Each Test
class MotorControllerTests: public QObject
{
Q_OBJECT
private slots:
void init() { controller = new MotorController; }
void cleanup() { delete controller; }
void motorRunsIfInterlockAndSwitchAreTrue() {
controller.setInterLock(true);
controller.setSwitch(true);
QCOMPARE(controller.motorOn(), true)
}
void motorDoesNotRunIfInterlockIsFalse() { ... }
private:
MotorController* controller;
};
Data Driven Tests
• Sometimes you need to test many inputs to a function
• NULL, Same Value Twice, Negative, Positive, NAN, etc
• This isn’t great test code. Violates Test 1 Thing
QCOMPARE(QString("hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("Hello").toUpper(), QString("HELLO"));
QCOMPARE(QString("HellO").toUpper(), QString("HELLO"));
QCOMPARE(QString("HELLO").toUpper(), QString("HELLO"));
• Or worse this. Lots of error prone typing if not trivial.
void testhelloToUpper() {...}
void testHELLOToUpper() {...}
void testHeLOToUpper() {...}
Data Driven Tests
private slots:
void toUpper_data() {
QTest::addColumn<QString>("string");
QTest::addColumn<QString>("result");
//We can name the sub tests
QTest::newRow("all lower") << "hello" << "HELLO";
QTest::newRow("mixed") << "Hello" << "HELLO";
QTest::newRow("all upper") << "HELLO" << "HELLO";
}
void TestQString::toUpper() { // Called 3 Times
QFETCH(QString, string);
QFETCH(QString, result);
QCOMPARE(string.toUpper(), result);
}
};
Testing Events and Signals
• Use QSignalSpy to attach to any signal
• Signal parameters need to be QVariant compatible
• May require Q_DECLARE_METATYPE()
• May require qRegisterMetaType<>()
• Verify with count() and arguments()
• Use QtTest static methods to stimulate events
• void mousePress(widget, button, modifiers, pos)
• void keyClicks(widget, string, modifiers)
• Etc, etc
Testing Events and Signals
class QPushButtonTests: public QObject
{
Q_OBJECT
private slots:
void init() { //Create, Show, Wait For Window Shown }
void emitsClickedWhenLeftMouseButtonIsClicked() {
QSignalSpy spy(button, &QPushButton::clicked);
QTest::mouseClick(button, Qt::LeftButton)
QCOMPARE(spy.count(), 1);
}
private:
QPushButton* button;
};
Stimulating Signals
• Often your object under test is depending on signals from
other objects.
• For example QPushButton clicked()
• Don’t re-test the button
• Directly call QPushButton clicked()
• signals access specifier is actually a #define public
Stimulating Signals
private slots:
void init() {
settings = new Settings;
settingsDialog = new SettingsDialog(settings);
}
void LanguageComboBoxUpdatesOnSettingsLanguageChanged() {
QComboBox* combo = settings->ui()->langCombo;
settings->lanuageChanged(“en_US”);
QCOMPARE(combo->currentText(), “English”);
}
private:
Settings* settings;
TestableSettingsDialog* button; // Exposes ui member via function
};
Testing QML with QTest
• Writing tests in QML is very similar to C++
• Create a test fixture class
• Implement specially named functions
• Prepare, Stimulate, Verify.
• KISS – Keep It Short and Simple
• There are QML equivalents to
• compare, verify, wait
• SignalSpy
• mouseClick(...)
• TestCase
• Specific test fixture class. C++ just uses QObject.
UI Control Test
• UI Controls are easy to test as they have no dependencies
TestCase {
name: "Button“
Button { id: button }
SignalSpy { id: clickedSpy; target: button; signal: ”clicked” }
function test_mouseClickEmitClicked() //Tests are run in alpha order
{
mouseClick(button)
compare(clickedSpy.count, 1)
}
}
New Objects For Each Test
TestCase {
id: testCase
property Button button: null
name: "Button“
Component { id: buttonFactory; Button{} }
function init() { button = buttonFacotry.createObject(testCase) }
function cleanup() { button.destroy() }
function test_mouseClickEmitClicked()
{
mouseClick(button)
compare(clickedSpy.count, 1)
}
}
Running QML Tests
• qmltestrunner
• Prebuilt test runner.
• Takes a filename or directory of files to run
• Many command line options
• See Qt Documentation
• Can run many test by itself.
• All UI controls should be testable this way
• Custom main.cpp runner
• Reuse the guts of qmltestrunner
• Add injected type information or other setup
• As required by your app
qmltestrunner
$QTDIR/bin/qmltestrunner –input TestDir
Custom main.cpp
#include <QtQuickTest/quicktest.h>
#include <QtCore/qstring.h>
#ifdef QT_OPENGL_LIB
#include <QtOpenGL/qgl.h>
#endif
#define TEST_DIR “UiTests” // Pass this as DEFINE in project file
int main(int argc, char **argv)
{
//Register Types Here
return quick_test_main(argc, argv, “UiTests", TEST_DIR);
}
Screen Tests
• Screens are more interesting
• They depend on Controllers and Models from C++
• QML and C++ is natively a layered architecture
• Most common ways to communicate with C++ is injection
• Of C++ instances or C++ types
• However we can Mock Controllers and Models
• Using QML instead of C++
C++ Integration Mechanisms
• Context Properties – Injects global pointers at root context
• view.rootContext()->setContextProperty(“coffeeMaker”, &maker);
• QML Singletons – Inject a singleton factory for import
• qmlRegisterSingletonType<CoffeeMaker>(“MrCoffee", 1, 0,
“CoffeeMaker",
factoryFunction);
• Registered Types – Add new types for import
• qmlRegisterType<CoffeeMaker>(“MrCoffee“, 1, 0, “CoffeeMaker“);
Mocking Context Properties
• Create a Mock[ClassName].qml file
• Create the equivalent property, signal and function API
• The TestCase item is the root item for your test
• It literally is the rootContext()
• Simply add properties to the TestCase with the same names
• They will have global scope
• Tests can be run through the standard qmltestrunner
Mocking Singletons
• Create a Mock[ClassName].qml file
• Create the equivalent property, signal and function API
• Create a custom QML Test main.cpp
• Call qmlRegisterSingletonType with URL to file name of mock
• qmlRegisterSingletonType(QUrl("file:///path/MockCoffeeMaker.qml"),
“MrCoffee", 1, 0,
“CoffeeMaker");
• Run tests as usual.
• Objects will use mock versions of C++ classes
Mocking Registered Types
• Create a Mock[ClassName].qml file
• Create the equivalent property, signal and function API
• Inside a directory structure similar to production
• Mocks/com/ics/qtest/examples/
• Create a qmldir manifest file listing your mock types
• CoffeeMaker 1.0 MockCoffeeMaker.qml
• Manipulate QML2_IMPORT_PATH to pull in testing
module rather than production module
CoffeeMaker.h
class CoffeeMaker : public QObject
{
Q_OBJECT
Q_PROPERTY(int temp READ temp
NOTIFY tempChanged)
Q_PROPERTY(int targetTemp READ targetTemp
WRITE setTargetTemp
NOTIFY targetTempChanged)
public:
enum Strength {
Bold=0, Medium, Light
} Q_ENUM(Strength)
CoffeeMaker(IPump& pump, IHeater& heater);
...
Q_INVOKABLE void brew(Strength strength);
};
main.cpp
int main(int argc, char** argv)
{
QGuiApplication app(argc, argv);
...
CoffeeMaker coffeeMaker(pump, heater);
qmlRegisterUncreatableType<CoffeeMaker>(“MrCoffee”,
1, 0,
“CoffeeMaker”, “”);
QQuickView view;
view.rootContext()->setContextProperty(“coffeeMaker”, & coffeeMaker);
view.setSource(“qrc:/Main.qml”);
view.show();
return app.exec();
}
CoffeeScreen.qml
import QtQuick 2.5
import MyComponents 1.0
import MrCoffee 1.0
Screen {
...
SpinBox {
value: coffeeMaker.targetTemp
onValueChanged: coffeeMaker.targetTemp = value
Connections {
target: coffeeMaker
onTargetTempChanged: value = coffeeMaker.targetTemp
}
}
Button {
text: qsTr(“Brew”)
onClicked: coffeeMaker.brew(CoffeeMaker.Medium)
}
}
CoffeeScreen.qml With Hooks
Screen {
property alias _spinBox: spinBox // No QML protected specifier 
property alias _button: button
...
SpinBox {
id: spinBox
value: coffeeMaker.targetTemp
onValueChanged: coffeeMaker.targetTemp = value
Connections {
target: coffeeMaker
onTargetTempChanged: value = coffeeMaker.targetTemp
}
}
Button {
id: button
text: qsTr(“Brew”)
onClicked: coffeeMaker.brew(CoffeeMaker.Medium)
}
}
Only Test CoffeeScreen
• CoffeeMaker is tested separately
• Is a discrete unit
• Has it’s own unit tests.
• A broken CoffeeMaker object shouldn’t fail CoffeeScreen tests
• UI Controls are tested separately
• SpinBox and Button are also discrete units
• Have their own tests
• Changing UI control APIs could cause tests not to run
• Controls are leaf nodes in the software design
• Easy to test by themselves.
• Should stabilize quickly
• When was the last time the API for SpinBox changed?
CoffeeScreen Text Fixture
CoffeeScreen
SpinBox
PushButton
MockCoffeeMaker
Stimulus: Set Values / EmitVerify: Was Function Called?
MockCoffeeMaker.qml
QtObject {
property int temp: 0
property int targetTemp: 0
property int brewInvokations: 0
property var brewStrengthParameter: []
function brew(strength) {
brewStrengthParameter[brewInvokations] = strength
brewInvokations++
}
function reset() {
brewStrengthParameter = []
brewInvokations = 0
}
}
TestCase with Mocks
UiTestCase.qml
---------------------------------------------------------------------
TestCase {
when: windowShown
property MockCoffeeMaker coffeeMaker: MockCoffeeMaker {}
function resetAllMocks() {
coffeeMaker.reset();
}
}
CoffeeScreenTest.qml
import “../qmlSource”
UiTestCase {
id: testCase
name: "CoffeeScreen“
property CoffeeScreen coffeeScreen: null
Component { id: factory; CoffeeScreen {} }
function init() {
resetAllMocks();
coffeeScreen = factory.createObject(testCase)
}
function cleanup() {
coffeeScreen.destroy()
coffeeScreen = null
}
...
CoffeeScreenTest.qml
...
function test_spinBoxValueIsBoundToCoffeeMakerTemp() {
coffeeMaker.temp = 50
compare(coffeeScreen._spinBox.value, 50)
}
}
// Bug #532
function test_settingSpinBoxValueDoesNotBreakBinding() {
coffeeScreen._spinBox.value = 99
coffeeMaker.temp = 20
compare(coffeeScreen._spinBox.value, 20)
}
}
CoffeeScreenTest.qml
...
function test_buttonClickedCallsBrew() {
coffeeScreen._button.clicked()
compare(coffeeMaker.brewInvokations, 1)
}
function test_buttonClickedCallsBrewWithMediumStregth() {
coffeeScreen._button.clicked()
compare(coffeeMaker.brewStrengthArgument[0], CoffeeMaker.Medium)
}
Custom Test Runner
#include <QtQuickTest/quicktest.h>
#include <QtCore/qstring.h>
#ifdef QT_OPENGL_LIB
#include <QtOpenGL/qgl.h>
#endif
#include “CoffeeMaker.h”
int main(int argc, char **argv)
{
qmlRegisterUncreatableType<CoffeeMaker>(“MrCoffee”, 1, 0,
“CoffeeMaker”, “”);
return quick_test_main(argc, argv, “UiTests", “.”);
}
Thank You!
Justin Noel
Senior Consulting Engineer
ICS, Inc.
www.ics.com

Contenu connexe

Tendances

Best Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIBest Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIICS
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threadsYnon Perek
 
QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? ICS
 
Qt Framework Events Signals Threads
Qt Framework Events Signals ThreadsQt Framework Events Signals Threads
Qt Framework Events Signals ThreadsNeera Mital
 
Introduction to the Qt State Machine Framework using Qt 6
Introduction to the Qt State Machine Framework using Qt 6Introduction to the Qt State Machine Framework using Qt 6
Introduction to the Qt State Machine Framework using Qt 6ICS
 
In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QMLICS
 
The Art of Java Type Patterns
The Art of Java Type PatternsThe Art of Java Type Patterns
The Art of Java Type PatternsSimon Ritter
 
Introduction to QML
Introduction to QMLIntroduction to QML
Introduction to QMLAlan Uthoff
 
Google mock training
Google mock trainingGoogle mock training
Google mock trainingThierry Gayet
 
Scripting Your Qt Application
Scripting Your Qt ApplicationScripting Your Qt Application
Scripting Your Qt Applicationaccount inactive
 
Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?COMAQA.BY
 
Distributed load testing with k6
Distributed load testing with k6Distributed load testing with k6
Distributed load testing with k6Thijs Feryn
 
Terraform: Infrastructure as Code
Terraform: Infrastructure as CodeTerraform: Infrastructure as Code
Terraform: Infrastructure as CodePradeep Bhadani
 
Lessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesLessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesICS
 

Tendances (20)

Best Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part IIBest Practices in Qt Quick/QML - Part II
Best Practices in Qt Quick/QML - Part II
 
Qt Application Programming with C++ - Part 1
Qt Application Programming with C++ - Part 1Qt Application Programming with C++ - Part 1
Qt Application Programming with C++ - Part 1
 
Qt multi threads
Qt multi threadsQt multi threads
Qt multi threads
 
QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong? QThreads: Are You Using Them Wrong?
QThreads: Are You Using Them Wrong?
 
Qt Framework Events Signals Threads
Qt Framework Events Signals ThreadsQt Framework Events Signals Threads
Qt Framework Events Signals Threads
 
Qt programming-using-cpp
Qt programming-using-cppQt programming-using-cpp
Qt programming-using-cpp
 
Qt Application Programming with C++ - Part 2
Qt Application Programming with C++ - Part 2Qt Application Programming with C++ - Part 2
Qt Application Programming with C++ - Part 2
 
Introduction to the Qt State Machine Framework using Qt 6
Introduction to the Qt State Machine Framework using Qt 6Introduction to the Qt State Machine Framework using Qt 6
Introduction to the Qt State Machine Framework using Qt 6
 
In-Depth Model/View with QML
In-Depth Model/View with QMLIn-Depth Model/View with QML
In-Depth Model/View with QML
 
The Art of Java Type Patterns
The Art of Java Type PatternsThe Art of Java Type Patterns
The Art of Java Type Patterns
 
Introduction to QML
Introduction to QMLIntroduction to QML
Introduction to QML
 
Introduction to JUnit
Introduction to JUnitIntroduction to JUnit
Introduction to JUnit
 
Google mock training
Google mock trainingGoogle mock training
Google mock training
 
Scripting Your Qt Application
Scripting Your Qt ApplicationScripting Your Qt Application
Scripting Your Qt Application
 
Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?Слои тестового фрамеворка. Что? Где? Когда?
Слои тестового фрамеворка. Что? Где? Когда?
 
Distributed load testing with k6
Distributed load testing with k6Distributed load testing with k6
Distributed load testing with k6
 
Terraform: Infrastructure as Code
Terraform: Infrastructure as CodeTerraform: Infrastructure as Code
Terraform: Infrastructure as Code
 
Lessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesLessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML Devices
 
Qt 5 - C++ and Widgets
Qt 5 - C++ and WidgetsQt 5 - C++ and Widgets
Qt 5 - C++ and Widgets
 
testng
testngtestng
testng
 

Similaire à Qt test framework

An Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitAn Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitweili_at_slideshare
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFXHendrik Ebbers
 
Pekka_Aho_Complementing GUI Testing Scripts - Testing Assembly 2022.pdf
Pekka_Aho_Complementing GUI Testing Scripts -  Testing Assembly 2022.pdfPekka_Aho_Complementing GUI Testing Scripts -  Testing Assembly 2022.pdf
Pekka_Aho_Complementing GUI Testing Scripts - Testing Assembly 2022.pdfFiSTB
 
How and what to unit test
How and what to unit testHow and what to unit test
How and what to unit testEugenio Lentini
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Dror Helper
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?Dmitry Buzdin
 
Unit Testing in R with Testthat - HRUG
Unit Testing in R with Testthat - HRUGUnit Testing in R with Testthat - HRUG
Unit Testing in R with Testthat - HRUGegoodwintx
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchMats Bryntse
 
Winning the battle against Automated testing
Winning the battle against Automated testingWinning the battle against Automated testing
Winning the battle against Automated testingElena Laskavaia
 
Cpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeCpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeClare Macrae
 
Database development unit test with tSQLt
Database development unit test with tSQLtDatabase development unit test with tSQLt
Database development unit test with tSQLtSergio Govoni
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherencearagozin
 

Similaire à Qt test framework (20)

An Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnitAn Introduction to Unit Test Using NUnit
An Introduction to Unit Test Using NUnit
 
Junit
JunitJunit
Junit
 
Test Driven Development with JavaFX
Test Driven Development with JavaFXTest Driven Development with JavaFX
Test Driven Development with JavaFX
 
Testing Angular
Testing AngularTesting Angular
Testing Angular
 
Building XWiki
Building XWikiBuilding XWiki
Building XWiki
 
Cpp unit
Cpp unit Cpp unit
Cpp unit
 
Test driven development
Test driven developmentTest driven development
Test driven development
 
Unit tests and TDD
Unit tests and TDDUnit tests and TDD
Unit tests and TDD
 
Pekka_Aho_Complementing GUI Testing Scripts - Testing Assembly 2022.pdf
Pekka_Aho_Complementing GUI Testing Scripts -  Testing Assembly 2022.pdfPekka_Aho_Complementing GUI Testing Scripts -  Testing Assembly 2022.pdf
Pekka_Aho_Complementing GUI Testing Scripts - Testing Assembly 2022.pdf
 
How and what to unit test
How and what to unit testHow and what to unit test
How and what to unit test
 
Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013Building unit tests correctly with visual studio 2013
Building unit tests correctly with visual studio 2013
 
Unit Testing
Unit TestingUnit Testing
Unit Testing
 
How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?How to Build Your Own Test Automation Framework?
How to Build Your Own Test Automation Framework?
 
Unit Testing in R with Testthat - HRUG
Unit Testing in R with Testthat - HRUGUnit Testing in R with Testthat - HRUG
Unit Testing in R with Testthat - HRUG
 
Testing Ext JS and Sencha Touch
Testing Ext JS and Sencha TouchTesting Ext JS and Sencha Touch
Testing Ext JS and Sencha Touch
 
Unit testing
Unit testingUnit testing
Unit testing
 
Winning the battle against Automated testing
Winning the battle against Automated testingWinning the battle against Automated testing
Winning the battle against Automated testing
 
Cpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp EuropeCpp Testing Techniques Tips and Tricks - Cpp Europe
Cpp Testing Techniques Tips and Tricks - Cpp Europe
 
Database development unit test with tSQLt
Database development unit test with tSQLtDatabase development unit test with tSQLt
Database development unit test with tSQLt
 
Performance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle CoherencePerformance Test Driven Development with Oracle Coherence
Performance Test Driven Development with Oracle Coherence
 

Plus de ICS

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfICS
 
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...ICS
 
Overcoming CMake Configuration Issues Webinar
Overcoming CMake Configuration Issues WebinarOvercoming CMake Configuration Issues Webinar
Overcoming CMake Configuration Issues WebinarICS
 
Enhancing Quality and Test in Medical Device Design - Part 2.pdf
Enhancing Quality and Test in Medical Device Design - Part 2.pdfEnhancing Quality and Test in Medical Device Design - Part 2.pdf
Enhancing Quality and Test in Medical Device Design - Part 2.pdfICS
 
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdf
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdfDesigning and Managing IoT Devices for Rapid Deployment - Webinar.pdf
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdfICS
 
Quality and Test in Medical Device Design - Part 1.pdf
Quality and Test in Medical Device Design - Part 1.pdfQuality and Test in Medical Device Design - Part 1.pdf
Quality and Test in Medical Device Design - Part 1.pdfICS
 
Creating Digital Twins Using Rapid Development Techniques.pdf
Creating Digital Twins Using Rapid Development Techniques.pdfCreating Digital Twins Using Rapid Development Techniques.pdf
Creating Digital Twins Using Rapid Development Techniques.pdfICS
 
Secure Your Medical Devices From the Ground Up
Secure Your Medical Devices From the Ground Up Secure Your Medical Devices From the Ground Up
Secure Your Medical Devices From the Ground Up ICS
 
Cybersecurity and Software Updates in Medical Devices.pdf
Cybersecurity and Software Updates in Medical Devices.pdfCybersecurity and Software Updates in Medical Devices.pdf
Cybersecurity and Software Updates in Medical Devices.pdfICS
 
MDG Panel - Creating Expert Level GUIs for Complex Medical Devices
MDG Panel - Creating Expert Level GUIs for Complex Medical DevicesMDG Panel - Creating Expert Level GUIs for Complex Medical Devices
MDG Panel - Creating Expert Level GUIs for Complex Medical DevicesICS
 
How to Craft a Winning IOT Device Management Solution
How to Craft a Winning IOT Device Management SolutionHow to Craft a Winning IOT Device Management Solution
How to Craft a Winning IOT Device Management SolutionICS
 
Bridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsBridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsICS
 
IoT Device Fleet Management: Create a Robust Solution with Azure
IoT Device Fleet Management: Create a Robust Solution with AzureIoT Device Fleet Management: Create a Robust Solution with Azure
IoT Device Fleet Management: Create a Robust Solution with AzureICS
 
Basic Cmake for Qt Users
Basic Cmake for Qt UsersBasic Cmake for Qt Users
Basic Cmake for Qt UsersICS
 
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...ICS
 
Qt Installer Framework
Qt Installer FrameworkQt Installer Framework
Qt Installer FrameworkICS
 
Bridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsBridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsICS
 
Overcome Hardware And Software Challenges - Medical Device Case Study
Overcome Hardware And Software Challenges - Medical Device Case StudyOvercome Hardware And Software Challenges - Medical Device Case Study
Overcome Hardware And Software Challenges - Medical Device Case StudyICS
 
User Experience Design for IoT
User Experience Design for IoTUser Experience Design for IoT
User Experience Design for IoTICS
 

Plus de ICS (20)

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Practical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdfPractical Advice for FDA’s 510(k) Requirements.pdf
Practical Advice for FDA’s 510(k) Requirements.pdf
 
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
Accelerating Development of a Safety-Critical Cobot Welding System with Qt/QM...
 
Overcoming CMake Configuration Issues Webinar
Overcoming CMake Configuration Issues WebinarOvercoming CMake Configuration Issues Webinar
Overcoming CMake Configuration Issues Webinar
 
Enhancing Quality and Test in Medical Device Design - Part 2.pdf
Enhancing Quality and Test in Medical Device Design - Part 2.pdfEnhancing Quality and Test in Medical Device Design - Part 2.pdf
Enhancing Quality and Test in Medical Device Design - Part 2.pdf
 
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdf
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdfDesigning and Managing IoT Devices for Rapid Deployment - Webinar.pdf
Designing and Managing IoT Devices for Rapid Deployment - Webinar.pdf
 
Quality and Test in Medical Device Design - Part 1.pdf
Quality and Test in Medical Device Design - Part 1.pdfQuality and Test in Medical Device Design - Part 1.pdf
Quality and Test in Medical Device Design - Part 1.pdf
 
Creating Digital Twins Using Rapid Development Techniques.pdf
Creating Digital Twins Using Rapid Development Techniques.pdfCreating Digital Twins Using Rapid Development Techniques.pdf
Creating Digital Twins Using Rapid Development Techniques.pdf
 
Secure Your Medical Devices From the Ground Up
Secure Your Medical Devices From the Ground Up Secure Your Medical Devices From the Ground Up
Secure Your Medical Devices From the Ground Up
 
Cybersecurity and Software Updates in Medical Devices.pdf
Cybersecurity and Software Updates in Medical Devices.pdfCybersecurity and Software Updates in Medical Devices.pdf
Cybersecurity and Software Updates in Medical Devices.pdf
 
MDG Panel - Creating Expert Level GUIs for Complex Medical Devices
MDG Panel - Creating Expert Level GUIs for Complex Medical DevicesMDG Panel - Creating Expert Level GUIs for Complex Medical Devices
MDG Panel - Creating Expert Level GUIs for Complex Medical Devices
 
How to Craft a Winning IOT Device Management Solution
How to Craft a Winning IOT Device Management SolutionHow to Craft a Winning IOT Device Management Solution
How to Craft a Winning IOT Device Management Solution
 
Bridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsBridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory Teams
 
IoT Device Fleet Management: Create a Robust Solution with Azure
IoT Device Fleet Management: Create a Robust Solution with AzureIoT Device Fleet Management: Create a Robust Solution with Azure
IoT Device Fleet Management: Create a Robust Solution with Azure
 
Basic Cmake for Qt Users
Basic Cmake for Qt UsersBasic Cmake for Qt Users
Basic Cmake for Qt Users
 
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...
Software Update Mechanisms: Selecting the Best Solutin for Your Embedded Linu...
 
Qt Installer Framework
Qt Installer FrameworkQt Installer Framework
Qt Installer Framework
 
Bridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory TeamsBridging the Gap Between Development and Regulatory Teams
Bridging the Gap Between Development and Regulatory Teams
 
Overcome Hardware And Software Challenges - Medical Device Case Study
Overcome Hardware And Software Challenges - Medical Device Case StudyOvercome Hardware And Software Challenges - Medical Device Case Study
Overcome Hardware And Software Challenges - Medical Device Case Study
 
User Experience Design for IoT
User Experience Design for IoTUser Experience Design for IoT
User Experience Design for IoT
 

Dernier

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...masabamasaba
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...Shane Coughlan
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 

Dernier (20)

Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
%+27788225528 love spells in Huntington Beach Psychic Readings, Attraction sp...
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 

Qt test framework

  • 1. QtTest Unit Testing Framework Justin Noel Senior Consulting Engineer ICS, Inc.
  • 2. Qt is the Kitchen Sink Toolkit • Qt comes with just about everything you need • SQL, Sockets, XML, GUI, etc • Often one of the challenges of using Qt is knowing all the modules • And what they do! • This is ICS performs these webinars! • Qt comes with it’s own Unit Testing Framework • QtTest
  • 3. Types of Testing • Unit Testing • Test one discrete area of the software • Usually on a class basis. Think “Test Piston Rod” • Tests can be written and performed as code is developed • White box tests. Often written by developers • “Does the software perform as the developer intended?” • Functional Testing • Tests subsystems of the whole software system • Usually a group of classes. Think “Test Engine” • Tests can be preformed once subsystem is wired together • Tests interaction between specific groups of units • “Does the software work together?”
  • 4. Types of Testing • System Testing • End to end testing of the whole software system • Sometimes includes actual hardware. Think “Test Car”. • Tests are written late in project • Because of the end to end nature. • Black box tests. Often written by separate SQA team • “Does the software do right thing?”
  • 5. Test Frameworks for Qt • QTest / QTest-QML • Unit testing framework that comes with Qt • Qt specific functionality • Can test blind signals. Can simulate mouse and key events. • Qt specific features can be used outside of QTest framework • Google Test • Unit testing framework from Google • Unique ability to do “Isolated Testing” via Google Mock • Requires “Inversion of Control” pattern • Squish • Playback / Record frame work for “end to end” system testing. • Used for System Testing
  • 6. Benefits of Unit Testing • Test Early! • Find errors while code is actively being developed • Rather than long investigations during system testing • Test Often! • Run unit tests per commit. Or even pre-commit! • Any failures must have been introduced by this 200 lines of code! • Test for Regressions! • Did new functionality or bug fixing break existing functionality? • What tests failed? • Did a code change re-introduce a bug? • Every bug can have it’s own set of unit tests.
  • 7. Design for Testability • Your code must be testable! • There are design techniques to help make your code more testable • Try not to add functions to production code just for tests • Subclassing for tests is acceptable (.ui file members) • Isolation of units is your primary goal • Can I test just this class? • Without re-testing lower level classes? • Also think about error conditions • Some may be hard to produce in production environments • Can I stimulate a bad MD5 error? • Socket disconnects? • Default switch cases?
  • 8. Build Application as Libraries • Building the bulk of your application as a set of libraries increases testability AppBackend.dll App.exe (main.cpp) AppUi.dll BackendTests.exe UiTests.exe C++ Test Fixtures QML Test Fixtures
  • 9. Layered Design • A layered design is more testable • Easy to isolate lower layers for testing • Test Communications without Data, Presentation or Visualization • No upwards dependencies • Hard downward dependencies Visualization Layer (QML) Presentation Layer (QObjects) Data Layer (Local Data Storage) Communications Layer (TCP) Calls Down Signals Up
  • 10. Break Downward Dependencies • Dependency injection works well • An Inversion of Control Pattern • Classes take their dependencies as constructor arguments • Classes do not construct any members themselves • Loose coupling with signals and slots also works well • Classes interface to each other via signals and slots only • 3rd class wires say the UI classes to the Backend classes • Lets you substitute a test fixture object for a dependency object • Instead of an actual production object.
  • 11. Why is isolation important? • Avoids testing the same code over and over • You have already tested the data model • Why do the UI tests need to also test the model? • This will make your tests run very quickly • If there is a failure in a low level class it won’t trigger errors in higher level tests • Avoid testing side effects • Tests can be implementation agnostic • DB, Files, Cloud. Shouldn’t matter for UI tests. • Tests should only depend on interfaces, not behavior
  • 12. EE Analogy: Motor Controller Test Motor Controller 7408 AND Momentary Switch Safety Interlock Motor 1 2 3 Stimulus: Apply PowerVerify: High or Low
  • 13. QtTest is a unit testing framework • QtTest comes with classes to build test fixtures for units • Has some “special sauce” for Qt • Test signals without needing to write slots (QSignalSpy) • Simulate user events (MousePress, KeyPress, FocusIn, etc) • QtTest is not an isolation framework • You will have to make replacement classes for dependencies yourself • These are usually referred to as Mock Classes. • Next month we will talk about Google Mock which is can help a lot with isolation framework.
  • 14. Creating a Test Fixture • Can be implemented inside a source file • No need for a header file • Inherit from QObject • Qt uses introspection to deduce test functions • Private slots are test functions • There are some reserved function names • Use Q_TEST_MAIN macro to generate a main() • Or create you own main.cpp to run multiple test fixtures
  • 15. Creating a Test Fixture #include <QtTest> class TestQString: public QObject { Q_OBJECT private slots: void toUpper() { QString str = "Hello"; // Prepare str = str.toUpper(); // Stimulate QCOMPARE(str, QString("HELLO")); // Verify } }; QTEST_MAIN(TestQString) #include “testqstring.moc”
  • 16. Test Fixture Project QT += testlib # Plus libs your uses. CONFIG += testcase # Creates make check target SOURCES += TestQString.cpp qmake make make check ********* Start testing of TestQString ********* Config: Using QtTest library %VERSION%, Qt %VERSION% PASS : TestQString::initTestCase() PASS : TestQString::toUpper() PASS : TestQString::cleanupTestCase() Totals: 3 passed, 0 failed, 0 skipped ********* Finished testing of TestQString *********
  • 17. Running Multiple Tests #include “QTestString.h” // Easier if you use a header file int main(int argc, char** argc) { bool success = true; r &= QTest::qExec(TestQString(), argc, argv); ... return success; }
  • 18. Initializing and Cleaning Up class TestQString: public QObject { Q_OBJECT private slots: void initTestCase() { // Called before ALL tests. } void cleanupTestCase() { // Called after ALL tests} void init() { // Called before each test. } void cleanup() { // Called after each test } void toUpper(); void toLower(); };
  • 19. Writing Good Tests • Test one thing at a time • It’s tempting to get as much done in one function as you can. • This makes one verification depend on another verification • Tests will be brittle and changes to code could break lots of verifications • Do not have your tests depend on each other • Order should not matter! • Not depending on other tests will help you when you remove functionality. • You do not want to have to fix a cascading waterfall of tests!
  • 20. Use New Object For Each Test • Use init() • Create your Object Under Test • Plus whatever dependencies it has • Production dependencies • Or Test dependencies like Mock Classes • Use cleanup() • Do not be sloppy and leak memory in you tests. • Your tests should run clean under Valgrind • Aside for some suppressions for FreeType and FontConfig
  • 21. Use New Object For Each Test class MotorControllerTests: public QObject { Q_OBJECT private slots: void init() { controller = new MotorController; } void cleanup() { delete controller; } void motorRunsIfInterlockAndSwitchAreTrue() { controller.setInterLock(true); controller.setSwitch(true); QCOMPARE(controller.motorOn(), true) } void motorDoesNotRunIfInterlockIsFalse() { ... } private: MotorController* controller; };
  • 22. Data Driven Tests • Sometimes you need to test many inputs to a function • NULL, Same Value Twice, Negative, Positive, NAN, etc • This isn’t great test code. Violates Test 1 Thing QCOMPARE(QString("hello").toUpper(), QString("HELLO")); QCOMPARE(QString("Hello").toUpper(), QString("HELLO")); QCOMPARE(QString("HellO").toUpper(), QString("HELLO")); QCOMPARE(QString("HELLO").toUpper(), QString("HELLO")); • Or worse this. Lots of error prone typing if not trivial. void testhelloToUpper() {...} void testHELLOToUpper() {...} void testHeLOToUpper() {...}
  • 23. Data Driven Tests private slots: void toUpper_data() { QTest::addColumn<QString>("string"); QTest::addColumn<QString>("result"); //We can name the sub tests QTest::newRow("all lower") << "hello" << "HELLO"; QTest::newRow("mixed") << "Hello" << "HELLO"; QTest::newRow("all upper") << "HELLO" << "HELLO"; } void TestQString::toUpper() { // Called 3 Times QFETCH(QString, string); QFETCH(QString, result); QCOMPARE(string.toUpper(), result); } };
  • 24. Testing Events and Signals • Use QSignalSpy to attach to any signal • Signal parameters need to be QVariant compatible • May require Q_DECLARE_METATYPE() • May require qRegisterMetaType<>() • Verify with count() and arguments() • Use QtTest static methods to stimulate events • void mousePress(widget, button, modifiers, pos) • void keyClicks(widget, string, modifiers) • Etc, etc
  • 25. Testing Events and Signals class QPushButtonTests: public QObject { Q_OBJECT private slots: void init() { //Create, Show, Wait For Window Shown } void emitsClickedWhenLeftMouseButtonIsClicked() { QSignalSpy spy(button, &QPushButton::clicked); QTest::mouseClick(button, Qt::LeftButton) QCOMPARE(spy.count(), 1); } private: QPushButton* button; };
  • 26. Stimulating Signals • Often your object under test is depending on signals from other objects. • For example QPushButton clicked() • Don’t re-test the button • Directly call QPushButton clicked() • signals access specifier is actually a #define public
  • 27. Stimulating Signals private slots: void init() { settings = new Settings; settingsDialog = new SettingsDialog(settings); } void LanguageComboBoxUpdatesOnSettingsLanguageChanged() { QComboBox* combo = settings->ui()->langCombo; settings->lanuageChanged(“en_US”); QCOMPARE(combo->currentText(), “English”); } private: Settings* settings; TestableSettingsDialog* button; // Exposes ui member via function };
  • 28. Testing QML with QTest • Writing tests in QML is very similar to C++ • Create a test fixture class • Implement specially named functions • Prepare, Stimulate, Verify. • KISS – Keep It Short and Simple • There are QML equivalents to • compare, verify, wait • SignalSpy • mouseClick(...) • TestCase • Specific test fixture class. C++ just uses QObject.
  • 29. UI Control Test • UI Controls are easy to test as they have no dependencies TestCase { name: "Button“ Button { id: button } SignalSpy { id: clickedSpy; target: button; signal: ”clicked” } function test_mouseClickEmitClicked() //Tests are run in alpha order { mouseClick(button) compare(clickedSpy.count, 1) } }
  • 30. New Objects For Each Test TestCase { id: testCase property Button button: null name: "Button“ Component { id: buttonFactory; Button{} } function init() { button = buttonFacotry.createObject(testCase) } function cleanup() { button.destroy() } function test_mouseClickEmitClicked() { mouseClick(button) compare(clickedSpy.count, 1) } }
  • 31. Running QML Tests • qmltestrunner • Prebuilt test runner. • Takes a filename or directory of files to run • Many command line options • See Qt Documentation • Can run many test by itself. • All UI controls should be testable this way • Custom main.cpp runner • Reuse the guts of qmltestrunner • Add injected type information or other setup • As required by your app
  • 33. Custom main.cpp #include <QtQuickTest/quicktest.h> #include <QtCore/qstring.h> #ifdef QT_OPENGL_LIB #include <QtOpenGL/qgl.h> #endif #define TEST_DIR “UiTests” // Pass this as DEFINE in project file int main(int argc, char **argv) { //Register Types Here return quick_test_main(argc, argv, “UiTests", TEST_DIR); }
  • 34. Screen Tests • Screens are more interesting • They depend on Controllers and Models from C++ • QML and C++ is natively a layered architecture • Most common ways to communicate with C++ is injection • Of C++ instances or C++ types • However we can Mock Controllers and Models • Using QML instead of C++
  • 35. C++ Integration Mechanisms • Context Properties – Injects global pointers at root context • view.rootContext()->setContextProperty(“coffeeMaker”, &maker); • QML Singletons – Inject a singleton factory for import • qmlRegisterSingletonType<CoffeeMaker>(“MrCoffee", 1, 0, “CoffeeMaker", factoryFunction); • Registered Types – Add new types for import • qmlRegisterType<CoffeeMaker>(“MrCoffee“, 1, 0, “CoffeeMaker“);
  • 36. Mocking Context Properties • Create a Mock[ClassName].qml file • Create the equivalent property, signal and function API • The TestCase item is the root item for your test • It literally is the rootContext() • Simply add properties to the TestCase with the same names • They will have global scope • Tests can be run through the standard qmltestrunner
  • 37. Mocking Singletons • Create a Mock[ClassName].qml file • Create the equivalent property, signal and function API • Create a custom QML Test main.cpp • Call qmlRegisterSingletonType with URL to file name of mock • qmlRegisterSingletonType(QUrl("file:///path/MockCoffeeMaker.qml"), “MrCoffee", 1, 0, “CoffeeMaker"); • Run tests as usual. • Objects will use mock versions of C++ classes
  • 38. Mocking Registered Types • Create a Mock[ClassName].qml file • Create the equivalent property, signal and function API • Inside a directory structure similar to production • Mocks/com/ics/qtest/examples/ • Create a qmldir manifest file listing your mock types • CoffeeMaker 1.0 MockCoffeeMaker.qml • Manipulate QML2_IMPORT_PATH to pull in testing module rather than production module
  • 39. CoffeeMaker.h class CoffeeMaker : public QObject { Q_OBJECT Q_PROPERTY(int temp READ temp NOTIFY tempChanged) Q_PROPERTY(int targetTemp READ targetTemp WRITE setTargetTemp NOTIFY targetTempChanged) public: enum Strength { Bold=0, Medium, Light } Q_ENUM(Strength) CoffeeMaker(IPump& pump, IHeater& heater); ... Q_INVOKABLE void brew(Strength strength); };
  • 40. main.cpp int main(int argc, char** argv) { QGuiApplication app(argc, argv); ... CoffeeMaker coffeeMaker(pump, heater); qmlRegisterUncreatableType<CoffeeMaker>(“MrCoffee”, 1, 0, “CoffeeMaker”, “”); QQuickView view; view.rootContext()->setContextProperty(“coffeeMaker”, & coffeeMaker); view.setSource(“qrc:/Main.qml”); view.show(); return app.exec(); }
  • 41. CoffeeScreen.qml import QtQuick 2.5 import MyComponents 1.0 import MrCoffee 1.0 Screen { ... SpinBox { value: coffeeMaker.targetTemp onValueChanged: coffeeMaker.targetTemp = value Connections { target: coffeeMaker onTargetTempChanged: value = coffeeMaker.targetTemp } } Button { text: qsTr(“Brew”) onClicked: coffeeMaker.brew(CoffeeMaker.Medium) } }
  • 42. CoffeeScreen.qml With Hooks Screen { property alias _spinBox: spinBox // No QML protected specifier  property alias _button: button ... SpinBox { id: spinBox value: coffeeMaker.targetTemp onValueChanged: coffeeMaker.targetTemp = value Connections { target: coffeeMaker onTargetTempChanged: value = coffeeMaker.targetTemp } } Button { id: button text: qsTr(“Brew”) onClicked: coffeeMaker.brew(CoffeeMaker.Medium) } }
  • 43. Only Test CoffeeScreen • CoffeeMaker is tested separately • Is a discrete unit • Has it’s own unit tests. • A broken CoffeeMaker object shouldn’t fail CoffeeScreen tests • UI Controls are tested separately • SpinBox and Button are also discrete units • Have their own tests • Changing UI control APIs could cause tests not to run • Controls are leaf nodes in the software design • Easy to test by themselves. • Should stabilize quickly • When was the last time the API for SpinBox changed?
  • 45. MockCoffeeMaker.qml QtObject { property int temp: 0 property int targetTemp: 0 property int brewInvokations: 0 property var brewStrengthParameter: [] function brew(strength) { brewStrengthParameter[brewInvokations] = strength brewInvokations++ } function reset() { brewStrengthParameter = [] brewInvokations = 0 } }
  • 46. TestCase with Mocks UiTestCase.qml --------------------------------------------------------------------- TestCase { when: windowShown property MockCoffeeMaker coffeeMaker: MockCoffeeMaker {} function resetAllMocks() { coffeeMaker.reset(); } }
  • 47. CoffeeScreenTest.qml import “../qmlSource” UiTestCase { id: testCase name: "CoffeeScreen“ property CoffeeScreen coffeeScreen: null Component { id: factory; CoffeeScreen {} } function init() { resetAllMocks(); coffeeScreen = factory.createObject(testCase) } function cleanup() { coffeeScreen.destroy() coffeeScreen = null } ...
  • 48. CoffeeScreenTest.qml ... function test_spinBoxValueIsBoundToCoffeeMakerTemp() { coffeeMaker.temp = 50 compare(coffeeScreen._spinBox.value, 50) } } // Bug #532 function test_settingSpinBoxValueDoesNotBreakBinding() { coffeeScreen._spinBox.value = 99 coffeeMaker.temp = 20 compare(coffeeScreen._spinBox.value, 20) } }
  • 49. CoffeeScreenTest.qml ... function test_buttonClickedCallsBrew() { coffeeScreen._button.clicked() compare(coffeeMaker.brewInvokations, 1) } function test_buttonClickedCallsBrewWithMediumStregth() { coffeeScreen._button.clicked() compare(coffeeMaker.brewStrengthArgument[0], CoffeeMaker.Medium) }
  • 50. Custom Test Runner #include <QtQuickTest/quicktest.h> #include <QtCore/qstring.h> #ifdef QT_OPENGL_LIB #include <QtOpenGL/qgl.h> #endif #include “CoffeeMaker.h” int main(int argc, char **argv) { qmlRegisterUncreatableType<CoffeeMaker>(“MrCoffee”, 1, 0, “CoffeeMaker”, “”); return quick_test_main(argc, argv, “UiTests", “.”); }
  • 51. Thank You! Justin Noel Senior Consulting Engineer ICS, Inc. www.ics.com