Commit a494d27b authored by Don Gagne's avatar Don Gagne

Merge pull request #1025 from DonLakeFlyer/UnitTestV2

New Unit Testing framework
parents 9f6a69b5 89de2ae2
...@@ -130,6 +130,7 @@ MacBuild { ...@@ -130,6 +130,7 @@ MacBuild {
CONFIG += x86_64 CONFIG += x86_64
CONFIG -= x86 CONFIG -= x86
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6 QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.6
QMAKE_MAC_SDK = macosx10.9
ICON = $$BASEDIR/files/images/icons/macx.icns ICON = $$BASEDIR/files/images/icons/macx.icns
QT += quickwidgets QT += quickwidgets
} }
...@@ -633,7 +634,8 @@ INCLUDEPATH += \ ...@@ -633,7 +634,8 @@ INCLUDEPATH += \
src/qgcunittest src/qgcunittest
HEADERS += \ HEADERS += \
src/qgcunittest/AutoTest.h \ src/qgcunittest/UnitTest.h \
src/qgcunittest/MessageBoxTest.h \
src/qgcunittest/UASUnitTest.h \ src/qgcunittest/UASUnitTest.h \
src/qgcunittest/MockLink.h \ src/qgcunittest/MockLink.h \
src/qgcunittest/MockLinkMissionItemHandler.h \ src/qgcunittest/MockLinkMissionItemHandler.h \
...@@ -651,7 +653,9 @@ HEADERS += \ ...@@ -651,7 +653,9 @@ HEADERS += \
src/qgcunittest/LinkManagerTest.h src/qgcunittest/LinkManagerTest.h
SOURCES += \ SOURCES += \
src/qgcunittest/UnitTest.cc \
src/qgcunittest/UASUnitTest.cc \ src/qgcunittest/UASUnitTest.cc \
src/qgcunittest/MessageBoxTest.cc \
src/qgcunittest/MockLink.cc \ src/qgcunittest/MockLink.cc \
src/qgcunittest/MockLinkMissionItemHandler.cc \ src/qgcunittest/MockLinkMissionItemHandler.cc \
src/qgcunittest/MockUASManager.cc \ src/qgcunittest/MockUASManager.cc \
......
...@@ -84,8 +84,9 @@ const char* QGCApplication::_savedFileParameterDirectoryName = "SavedParameters" ...@@ -84,8 +84,9 @@ const char* QGCApplication::_savedFileParameterDirectoryName = "SavedParameters"
**/ **/
QGCApplication::QGCApplication(int &argc, char* argv[]) : QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) :
QApplication(argc, argv) QApplication(argc, argv),
_runningUnitTests(unitTesting)
{ {
Q_ASSERT(_app == NULL); Q_ASSERT(_app == NULL);
_app = this; _app = this;
...@@ -120,6 +121,13 @@ QGCApplication::QGCApplication(int &argc, char* argv[]) : ...@@ -120,6 +121,13 @@ QGCApplication::QGCApplication(int &argc, char* argv[]) :
// The setting will delete all settings on this boot // The setting will delete all settings on this boot
fClearSettingsOptions |= settings.contains(_deleteAllSettingsKey); fClearSettingsOptions |= settings.contains(_deleteAllSettingsKey);
// We don't want unit tests to use the same QSettings space as the normal app. So we tweak the app
// name. Also we want to run unit tests with clean settings every time.
if (_runningUnitTests) {
setApplicationName(applicationName().append("UnitTest"));
fClearSettingsOptions = true;
}
if (fClearSettingsOptions) { if (fClearSettingsOptions) {
// User requested settings to be cleared on command line // User requested settings to be cleared on command line
settings.clear(); settings.clear();
......
...@@ -54,7 +54,7 @@ class QGCApplication : public QApplication ...@@ -54,7 +54,7 @@ class QGCApplication : public QApplication
Q_OBJECT Q_OBJECT
public: public:
QGCApplication(int &argc, char* argv[]); QGCApplication(int &argc, char* argv[], bool unitTesting);
~QGCApplication(); ~QGCApplication();
/// @brief Sets the persistent flag to delete all settings the next time QGroundControl is started. /// @brief Sets the persistent flag to delete all settings the next time QGroundControl is started.
...@@ -94,6 +94,9 @@ public: ...@@ -94,6 +94,9 @@ public:
/// @brief Destroys all singletons. Used by unit test code to reset global state. /// @brief Destroys all singletons. Used by unit test code to reset global state.
void destroySingletonsForUnitTest(void); void destroySingletonsForUnitTest(void);
/// @brief Returns truee if unit test are being run
bool runningUnitTests(void) { return _runningUnitTests; }
public: public:
/// @brief Perform initialize which is common to both normal application running and unit tests. /// @brief Perform initialize which is common to both normal application running and unit tests.
/// Although public should only be called by main. /// Although public should only be called by main.
...@@ -122,6 +125,8 @@ private: ...@@ -122,6 +125,8 @@ private:
static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory
QList<QGCSingleton*> _singletons; ///< List of registered global singletons QList<QGCSingleton*> _singletons; ///< List of registered global singletons
bool _runningUnitTests; ///< true: running unit tests, false: normal app
}; };
/// @brief Returns the QGCApplication object singleton. /// @brief Returns the QGCApplication object singleton.
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#include <QMessageBox> #include <QMessageBox>
#include "MainWindow.h" #include "MainWindow.h"
#include "QGCApplication.h"
#ifdef QT_DEBUG
#include "UnitTest.h"
#endif
/// @file /// @file
/// @brief Subclass of QMessageBox which re-implements the static public functions. There are two reasons for this: /// @brief Subclass of QMessageBox which re-implements the static public functions. There are two reasons for this:
...@@ -50,30 +54,81 @@ public: ...@@ -50,30 +54,81 @@ public:
static StandardButton warning(const QString& title, const QString& text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton, QWidget* parent = NULL) static StandardButton warning(const QString& title, const QString& text, StandardButtons buttons = Ok, StandardButton defaultButton = NoButton, QWidget* parent = NULL)
{ return _messageBox(QMessageBox::Warning, title, text, buttons, defaultButton, parent); } { return _messageBox(QMessageBox::Warning, title, text, buttons, defaultButton, parent); }
private slots:
/// @brief The exec slot is private becasue when only want QGCMessageBox users to use the static methods. Otherwise it will break
/// unit testing.
int exec(void) { return QMessageBox::exec(); }
private: private:
static QWidget* _validateParameters(StandardButtons buttons, StandardButton* defaultButton, QWidget* parent)
{
// This is an obsolete bit which unit tests use for signalling. It should not be used in regular code.
Q_ASSERT(!(buttons & QMessageBox::Escape));
// If there is more than one button displayed, make sure a default button is set. Without this unit test code
// will not be able to respond to unexpected message boxes.
unsigned int bits = static_cast<unsigned int>(buttons);
int buttonCount = 0;
for (size_t i=0; i<sizeof(bits)*8; i++) {
if (bits & (1 << i)) {
buttonCount++;
}
}
Q_ASSERT(buttonCount != 0);
if (buttonCount > 1) {
Q_ASSERT(buttons & *defaultButton);
} else {
// Force default button to be set correctly for single button case to make unit test code simpler
*defaultButton = static_cast<QMessageBox::StandardButton>(static_cast<int>(buttons));
}
return (parent == NULL) ? MainWindow::instance() : parent;
}
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
static StandardButton _messageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons, StandardButton defaultButton, QWidget* parent) static StandardButton _messageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons, StandardButton defaultButton, QWidget* parent)
{ {
if (parent == NULL) { // You can't use QGCMessageBox if QGCApplication is not created yet.
parent = MainWindow::instance(); Q_ASSERT(qgcApp());
parent = _validateParameters(buttons, &defaultButton, parent);
#ifdef QT_DEBUG
if (qgcApp()->runningUnitTests()) {
return UnitTest::_messageBox(icon, title, text, buttons, defaultButton);
} else
#endif // QT_DEBUG
{
QString emptyTitle;
QMessageBox box(icon, emptyTitle, title, buttons, parent);
box.setDefaultButton(defaultButton);
box.setInformativeText(text);
return static_cast<QMessageBox::StandardButton>(box.exec());
} }
QString emptyTitle;
QMessageBox box(icon, emptyTitle, title, buttons, parent);
box.setDefaultButton(defaultButton);
box.setInformativeText(text);
return static_cast<QMessageBox::StandardButton>(box.exec());
} }
#else #else
static StandardButton _messageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons, StandardButton defaultButton, QWidget* parent) static StandardButton _messageBox(Icon icon, const QString& title, const QString& text, StandardButtons buttons, StandardButton defaultButton, QWidget* parent)
{ {
if (parent == NULL) { // You can't use QGCMessageBox if QGCApplication is not created yet.
parent = MainWindow::instance(); Q_ASSERT(qgcApp());
parent = _validateParameters(buttons, &defaultButton, parent);
#ifdef QT_DEBUG
if (qgcApp()->runningUnitTests()) {
return UnitTest::_messageBox(icon, title, text, buttons, defaultButton);
} else
#endif // QT_DEBUG
{
QMessageBox box(icon, title, text, buttons, parent);
box.setDefaultButton(defaultButton);
return static_cast<QMessageBox::StandardButton>(box.exec());
} }
QMessageBox box(icon, title, text, buttons, parent);
box.setDefaultButton(defaultButton);
return static_cast<QMessageBox::StandardButton>(box.exec());
} }
#endif
#endif // Q_OS_MAC
}; };
#endif #endif
...@@ -37,7 +37,7 @@ This file is part of the QGROUNDCONTROL project ...@@ -37,7 +37,7 @@ This file is part of the QGROUNDCONTROL project
#include "SerialLink.h" #include "SerialLink.h"
#include "TCPLink.h" #include "TCPLink.h"
#ifdef QT_DEBUG #ifdef QT_DEBUG
#include "AutoTest.h" #include "UnitTest.h"
#include "CmdLineOptParser.h" #include "CmdLineOptParser.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <crtdbg.h> #include <crtdbg.h>
...@@ -104,11 +104,12 @@ int main(int argc, char *argv[]) ...@@ -104,11 +104,12 @@ int main(int argc, char *argv[])
qRegisterMetaType<QSerialPort::SerialPortError>(); qRegisterMetaType<QSerialPort::SerialPortError>();
qRegisterMetaType<QAbstractSocket::SocketError>(); qRegisterMetaType<QAbstractSocket::SocketError>();
bool runUnitTests = false; // Run unit tests
#ifdef QT_DEBUG #ifdef QT_DEBUG
// We parse a small set of command line options here prior to QGCApplication in order to handle the ones // We parse a small set of command line options here prior to QGCApplication in order to handle the ones
// which need to be handled before a QApplication object is started. // which need to be handled before a QApplication object is started.
bool runUnitTests = false; // Run unit test
bool quietWindowsAsserts = false; // Don't let asserts pop dialog boxes bool quietWindowsAsserts = false; // Don't let asserts pop dialog boxes
CmdLineOpt_t rgCmdLineOptions[] = { CmdLineOpt_t rgCmdLineOptions[] = {
...@@ -126,7 +127,7 @@ int main(int argc, char *argv[]) ...@@ -126,7 +127,7 @@ int main(int argc, char *argv[])
} }
#endif #endif
QGCApplication* app = new QGCApplication(argc, argv); QGCApplication* app = new QGCApplication(argc, argv, runUnitTests);
Q_CHECK_PTR(app); Q_CHECK_PTR(app);
app->_initCommon(); app->_initCommon();
...@@ -140,13 +141,10 @@ int main(int argc, char *argv[]) ...@@ -140,13 +141,10 @@ int main(int argc, char *argv[])
} }
// Run the test // Run the test
int failures = AutoTest::run(argc-1, argv, rgCmdLineOptions[0].optionArg); int failures = UnitTest::run(argc-1, argv, rgCmdLineOptions[0].optionArg);
if (failures == 0) if (failures == 0) {
{
qDebug() << "ALL TESTS PASSED"; qDebug() << "ALL TESTS PASSED";
} } else {
else
{
qDebug() << failures << " TESTS FAILED!"; qDebug() << failures << " TESTS FAILED!";
} }
exitCode = -failures; exitCode = -failures;
......
/**
* @author Rob Caldecott
* @note This was obtained from http://qtcreator.blogspot.com/2010/04/sample-multiple-unit-test-project.html
*
*/
#ifndef AUTOTEST_H
#define AUTOTEST_H
#include <QTest>
#include <QList>
#include <QString>
#include <QSharedPointer>
#include "QGCApplication.h"
namespace AutoTest
{
typedef QList<QObject*> TestList;
inline TestList& testList()
{
static TestList list;
return list;
}
inline bool findObject(QObject* object)
{
TestList& list = testList();
if (list.contains(object))
{
return true;
}
foreach (QObject* test, list)
{
if (test->objectName() == object->objectName())
{
return true;
}
}
return false;
}
inline void addTest(QObject* object)
{
TestList& list = testList();
if (!findObject(object))
{
list.append(object);
}
}
inline int run(int argc, char *argv[], QString& singleTest)
{
int ret = 0;
foreach (QObject* test, testList())
{
if (singleTest.isEmpty() || singleTest == test->objectName()) {
qgcApp()->destroySingletonsForUnitTest();
qgcApp()->createSingletonsForUnitTest();
ret += QTest::qExec(test, argc, argv);
}
}
return ret;
}
}
template <class T>
class Test
{
public:
QSharedPointer<T> child;
Test(const QString& name) : child(new T)
{
child->setObjectName(name);
AutoTest::addTest(child.data());
}
};
#define DECLARE_TEST(className) static Test<className> t(#className);
#endif // AUTOTEST_H
...@@ -29,23 +29,13 @@ ...@@ -29,23 +29,13 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
UT_REGISTER_TEST(FlightGearUnitTest)
FlightGearUnitTest::FlightGearUnitTest(void) FlightGearUnitTest::FlightGearUnitTest(void)
{ {
} }
// Called before every test
void FlightGearUnitTest::init(void)
{
// Nothing here yet
}
// Called after every test
void FlightGearUnitTest::cleanup(void)
{
// Nothing here yet
}
/// @brief The QGCFlightGearLink::parseUIArguments method is fairly involved so we have a unit /// @brief The QGCFlightGearLink::parseUIArguments method is fairly involved so we have a unit
// test for it. // test for it.
void FlightGearUnitTest::_parseUIArguments_test(void) void FlightGearUnitTest::_parseUIArguments_test(void)
......
...@@ -24,11 +24,7 @@ ...@@ -24,11 +24,7 @@
#ifndef TCPLINKTEST_H #ifndef TCPLINKTEST_H
#define TCPLINKTEST_H #define TCPLINKTEST_H
#include <QObject> #include "UnitTest.h"
#include <QtTest>
#include <QApplication>
#include "AutoTest.h"
#include "TCPLink.h" #include "TCPLink.h"
#include "MultiSignalSpy.h" #include "MultiSignalSpy.h"
...@@ -37,7 +33,7 @@ ...@@ -37,7 +33,7 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
class FlightGearUnitTest : public QObject class FlightGearUnitTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
...@@ -45,14 +41,12 @@ public: ...@@ -45,14 +41,12 @@ public:
FlightGearUnitTest(void); FlightGearUnitTest(void);
private slots: private slots:
void init(void); UT_DECLARE_DEFAULT_initTestCase
void cleanup(void); UT_DECLARE_DEFAULT_cleanupTestCase
UT_DECLARE_DEFAULT_init
UT_DECLARE_DEFAULT_cleanup
void _parseUIArguments_test(void); void _parseUIArguments_test(void);
private:
}; };
DECLARE_TEST(FlightGearUnitTest)
#endif #endif
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include "LinkManagerTest.h" #include "LinkManagerTest.h"
#include "MockLink.h" #include "MockLink.h"
UT_REGISTER_TEST(LinkManagerTest)
LinkManagerTest::LinkManagerTest(void) : LinkManagerTest::LinkManagerTest(void) :
_linkMgr(NULL), _linkMgr(NULL),
_multiSpy(NULL) _multiSpy(NULL)
...@@ -38,6 +40,8 @@ LinkManagerTest::LinkManagerTest(void) : ...@@ -38,6 +40,8 @@ LinkManagerTest::LinkManagerTest(void) :
void LinkManagerTest::init(void) void LinkManagerTest::init(void)
{ {
UnitTest::init();
Q_ASSERT(_linkMgr == NULL); Q_ASSERT(_linkMgr == NULL);
Q_ASSERT(_multiSpy == NULL); Q_ASSERT(_multiSpy == NULL);
...@@ -53,6 +57,8 @@ void LinkManagerTest::init(void) ...@@ -53,6 +57,8 @@ void LinkManagerTest::init(void)
void LinkManagerTest::cleanup(void) void LinkManagerTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_linkMgr); Q_ASSERT(_linkMgr);
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
......
...@@ -24,10 +24,7 @@ ...@@ -24,10 +24,7 @@
#ifndef UASUNITTEST_H #ifndef UASUNITTEST_H
#define UASUNITTEST_H #define UASUNITTEST_H
#include <QObject> #include "UnitTest.h"
#include <QtTest>
#include "AutoTest.h"
#include "LinkManager.h" #include "LinkManager.h"
#include "MultiSignalSpy.h" #include "MultiSignalSpy.h"
...@@ -36,7 +33,7 @@ ...@@ -36,7 +33,7 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
class LinkManagerTest : public QObject class LinkManagerTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
...@@ -44,6 +41,9 @@ public: ...@@ -44,6 +41,9 @@ public:
LinkManagerTest(void); LinkManagerTest(void);
private slots: private slots:
UT_DECLARE_DEFAULT_initTestCase
UT_DECLARE_DEFAULT_cleanupTestCase
void init(void); void init(void);
void cleanup(void); void cleanup(void);
...@@ -69,9 +69,6 @@ private: ...@@ -69,9 +69,6 @@ private:
MultiSignalSpy* _multiSpy; MultiSignalSpy* _multiSpy;
static const size_t _cSignals = maxSignalIndex; static const size_t _cSignals = maxSignalIndex;
const char* _rgSignals[_cSignals]; const char* _rgSignals[_cSignals];
}; };
DECLARE_TEST(LinkManagerTest)
#endif #endif
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @brief The tests the unit test QGCMessageBox catching mechanism.
///
/// @author Don Gagne <don@thegagnes.com>
#include "MessageBoxTest.h"
#include "QGCMessageBox.h"
UT_REGISTER_TEST(MessageBoxTest)
MessageBoxTest::MessageBoxTest(void) :
_expectMissedMessageBox(false)
{
}
void MessageBoxTest::cleanup(void)
{
if (_expectMissedMessageBox) {
_expectMissedMessageBox = false;
QEXPECT_FAIL("", "Supposed to fail in cleanup with a missed message box", Continue);
}
UnitTest::cleanup();
}
void MessageBoxTest::_messageBoxExpected_test(void)
{
setExpectedMessageBox(QMessageBox::Ok);
QCOMPARE(QGCMessageBox::information(QString(), QString()), QMessageBox::Ok);
checkExpectedMessageBox();
}
void MessageBoxTest::_messageBoxUnexpected_test(void)
{
// This should cause the test to fail in the cleanup method
QGCMessageBox::information(QString(), QString());
_expectMissedMessageBox = true;
}
void MessageBoxTest::_previousMessageBox_test(void)
{
// This is the previous unexpected message box
QGCMessageBox::information(QString(), QString());
// Setup for an expected message box.
QEXPECT_FAIL("", "Expecting failure due to previous message boxes", Continue);
setExpectedMessageBox(QMessageBox::Ok);
}
void MessageBoxTest::_noMessageBox_test(void)
{
setExpectedMessageBox(QMessageBox::Ok);
checkExpectedMessageBox(expectFailNoMessageBox);
}
void MessageBoxTest::_badResponseButton_test(void)
{
setExpectedMessageBox(QMessageBox::Cancel);
// Will return Ok even though Cancel was specified, since that was wrong
QCOMPARE(QGCMessageBox::information(QString(), QString()), QMessageBox::Ok);
checkExpectedMessageBox(expectFailBadResponseButton);
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @brief The tests the unit test QGCMessageBox catching mechanism.
///
/// @author Don Gagne <don@thegagnes.com>
#ifndef MESSAGEBOXTEST_H
#define MESSAGEBOXTEST_H
#include "UnitTest.h"
class MessageBoxTest : public UnitTest
{
Q_OBJECT
public:
MessageBoxTest(void);
private slots:
UT_DECLARE_DEFAULT_initTestCase
UT_DECLARE_DEFAULT_cleanupTestCase
UT_DECLARE_DEFAULT_init
void cleanup(void);
void _messageBoxExpected_test(void);
void _messageBoxUnexpected_test(void);
void _previousMessageBox_test(void);
void _noMessageBox_test(void);
void _badResponseButton_test(void);
private:
bool _expectMissedMessageBox;
};
#endif
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
UT_REGISTER_TEST(PX4RCCalibrationTest)
// This will check for the wizard buttons being enabled of disabled according to the mask you pass in. // This will check for the wizard buttons being enabled of disabled according to the mask you pass in.
// We use a macro instead of a method so that we get better line number reporting on failure. // We use a macro instead of a method so that we get better line number reporting on failure.
#define CHK_BUTTONS(mask) \ #define CHK_BUTTONS(mask) \
...@@ -137,6 +139,8 @@ PX4RCCalibrationTest::PX4RCCalibrationTest(void) : ...@@ -137,6 +139,8 @@ PX4RCCalibrationTest::PX4RCCalibrationTest(void) :
/// @brief Called one time before any test cases are run. /// @brief Called one time before any test cases are run.
void PX4RCCalibrationTest::initTestCase(void) void PX4RCCalibrationTest::initTestCase(void)
{ {
UnitTest::initTestCase();
// Validate that our function to channel mapping is still correct. // Validate that our function to channel mapping is still correct.
for (int function=0; function<PX4RCCalibration::rcCalFunctionMax; function++) { for (int function=0; function<PX4RCCalibration::rcCalFunctionMax; function++) {
int chanIndex = _rgFunctionChannelMap[function]; int chanIndex = _rgFunctionChannelMap[function];
...@@ -149,6 +153,8 @@ void PX4RCCalibrationTest::initTestCase(void) ...@@ -149,6 +153,8 @@ void PX4RCCalibrationTest::initTestCase(void)
void PX4RCCalibrationTest::init(void) void PX4RCCalibrationTest::init(void)
{ {
UnitTest::init();
_mockUASManager = new MockUASManager(); _mockUASManager = new MockUASManager();
Q_ASSERT(_mockUASManager); Q_ASSERT(_mockUASManager);
...@@ -196,6 +202,8 @@ void PX4RCCalibrationTest::init(void) ...@@ -196,6 +202,8 @@ void PX4RCCalibrationTest::init(void)
void PX4RCCalibrationTest::cleanup(void) void PX4RCCalibrationTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_calWidget); Q_ASSERT(_calWidget);
delete _calWidget; delete _calWidget;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#ifndef PX4RCCALIBRATIONTEST_H #ifndef PX4RCCALIBRATIONTEST_H
#define PX4RCCALIBRATIONTEST_H #define PX4RCCALIBRATIONTEST_H
#include "AutoTest.h" #include "UnitTest.h"
#include "MockUASManager.h" #include "MockUASManager.h"
#include "MockUAS.h" #include "MockUAS.h"
#include "MultiSignalSpy.h" #include "MultiSignalSpy.h"
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
/// @brief PX4RCCalibration Widget unit test /// @brief PX4RCCalibration Widget unit test
class PX4RCCalibrationTest : public QObject class PX4RCCalibrationTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
...@@ -45,6 +45,7 @@ public: ...@@ -45,6 +45,7 @@ public:
private slots: private slots:
void initTestCase(void); void initTestCase(void);
UT_DECLARE_DEFAULT_cleanupTestCase
void init(void); void init(void);
void cleanup(void); void cleanup(void);
...@@ -129,6 +130,4 @@ private: ...@@ -129,6 +130,4 @@ private:
static const int _rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionMax]; static const int _rgFunctionChannelMap[PX4RCCalibration::rcCalFunctionMax];
}; };
DECLARE_TEST(PX4RCCalibrationTest)
#endif #endif
...@@ -30,17 +30,20 @@ ...@@ -30,17 +30,20 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
UT_REGISTER_TEST(QGCUASFileManagerUnitTest)
QGCUASFileManagerUnitTest::QGCUASFileManagerUnitTest(void) : QGCUASFileManagerUnitTest::QGCUASFileManagerUnitTest(void) :
_mockFileServer(_systemIdQGC, _systemIdServer), _mockFileServer(_systemIdQGC, _systemIdServer),
_fileManager(NULL), _fileManager(NULL),
_multiSpy(NULL) _multiSpy(NULL)
{ {
} }
// Called once before all test cases are run // Called once before all test cases are run
void QGCUASFileManagerUnitTest::initTestCase(void) void QGCUASFileManagerUnitTest::initTestCase(void)
{ {
UnitTest::initTestCase();
_mockUAS.setMockSystemId(_systemIdServer); _mockUAS.setMockSystemId(_systemIdServer);
_mockUAS.setMockMavlinkPlugin(&_mockFileServer); _mockUAS.setMockMavlinkPlugin(&_mockFileServer);
} }
...@@ -48,6 +51,8 @@ void QGCUASFileManagerUnitTest::initTestCase(void) ...@@ -48,6 +51,8 @@ void QGCUASFileManagerUnitTest::initTestCase(void)
// Called before every test case // Called before every test case
void QGCUASFileManagerUnitTest::init(void) void QGCUASFileManagerUnitTest::init(void)
{ {
UnitTest::init();
Q_ASSERT(_multiSpy == NULL); Q_ASSERT(_multiSpy == NULL);
_fileManager = new QGCUASFileManager(NULL, &_mockUAS, _systemIdQGC); _fileManager = new QGCUASFileManager(NULL, &_mockUAS, _systemIdQGC);
...@@ -77,6 +82,8 @@ void QGCUASFileManagerUnitTest::init(void) ...@@ -77,6 +82,8 @@ void QGCUASFileManagerUnitTest::init(void)
// Called after every test case // Called after every test case
void QGCUASFileManagerUnitTest::cleanup(void) void QGCUASFileManagerUnitTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
Q_ASSERT(_fileManager); Q_ASSERT(_fileManager);
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <QObject> #include <QObject>
#include <QtTest/QtTest> #include <QtTest/QtTest>
#include "AutoTest.h" #include "UnitTest.h"
#include "MockUAS.h" #include "MockUAS.h"
#include "MockMavlinkFileServer.h" #include "MockMavlinkFileServer.h"
#include "QGCUASFileManager.h" #include "QGCUASFileManager.h"
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
class QGCUASFileManagerUnitTest : public QObject class QGCUASFileManagerUnitTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
...@@ -48,6 +48,7 @@ public: ...@@ -48,6 +48,7 @@ public:
private slots: private slots:
// Test case initialization // Test case initialization
void initTestCase(void); void initTestCase(void);
UT_DECLARE_DEFAULT_cleanupTestCase
void init(void); void init(void);
void cleanup(void); void cleanup(void);
...@@ -100,6 +101,4 @@ private: ...@@ -100,6 +101,4 @@ private:
QStringList _fileListReceived; QStringList _fileListReceived;
}; };
DECLARE_TEST(QGCUASFileManagerUnitTest)
#endif #endif
...@@ -29,18 +29,24 @@ ...@@ -29,18 +29,24 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
// This unit test has gotten too flaky to run reliably under TeamCity. Removing for now till there is
// time to debug.
//UT_REGISTER_TEST(TCPLinkUnitTest)
TCPLinkUnitTest::TCPLinkUnitTest(void) : TCPLinkUnitTest::TCPLinkUnitTest(void) :
_link(NULL), _link(NULL),
_hostAddress(QHostAddress::LocalHost), _hostAddress(QHostAddress::LocalHost),
_port(5760), _port(5760),
_multiSpy(NULL) _multiSpy(NULL)
{ {
} }
// Called before every test // Called before every test
void TCPLinkUnitTest::init(void) void TCPLinkUnitTest::init(void)
{ {
UnitTest::init();
Q_ASSERT(_link == NULL); Q_ASSERT(_link == NULL);
Q_ASSERT(_multiSpy == NULL); Q_ASSERT(_multiSpy == NULL);
...@@ -63,6 +69,8 @@ void TCPLinkUnitTest::init(void) ...@@ -63,6 +69,8 @@ void TCPLinkUnitTest::init(void)
// Called after every test // Called after every test
void TCPLinkUnitTest::cleanup(void) void TCPLinkUnitTest::cleanup(void)
{ {
UnitTest::cleanup();
Q_ASSERT(_multiSpy); Q_ASSERT(_multiSpy);
Q_ASSERT(_link); Q_ASSERT(_link);
......
...@@ -24,11 +24,7 @@ ...@@ -24,11 +24,7 @@
#ifndef TCPLINKTEST_H #ifndef TCPLINKTEST_H
#define TCPLINKTEST_H #define TCPLINKTEST_H
#include <QObject> #include "UnitTest.h"
#include <QtTest/QtTest>
#include <QApplication>
#include "AutoTest.h"
#include "TCPLink.h" #include "TCPLink.h"
#include "MultiSignalSpy.h" #include "MultiSignalSpy.h"
...@@ -37,7 +33,7 @@ ...@@ -37,7 +33,7 @@
/// ///
/// @author Don Gagne <don@thegagnes.com> /// @author Don Gagne <don@thegagnes.com>
class TCPLinkUnitTest : public QObject class TCPLinkUnitTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
...@@ -49,6 +45,8 @@ signals: ...@@ -49,6 +45,8 @@ signals:
void waitForReadyRead(int msecs); void waitForReadyRead(int msecs);
private slots: private slots:
UT_DECLARE_DEFAULT_initTestCase
UT_DECLARE_DEFAULT_cleanupTestCase
void init(void); void init(void);
void cleanup(void); void cleanup(void);
...@@ -89,8 +87,4 @@ private: ...@@ -89,8 +87,4 @@ private:
const char* _rgSignals[_cSignals]; const char* _rgSignals[_cSignals];
}; };
// This unit test has gotten too flaky to run reliably under TeamCity. Removing for now till there is
// time to debug.
//DECLARE_TEST(TCPLinkUnitTest)
#endif #endif
...@@ -3,55 +3,61 @@ ...@@ -3,55 +3,61 @@
#include <QObject> #include <QObject>
#include <QThread> #include <QThread>
UT_REGISTER_TEST(UASUnitTest)
UASUnitTest::UASUnitTest() UASUnitTest::UASUnitTest()
{ {
} }
//This function is called after every test //This function is called after every test
void UASUnitTest::init() void UASUnitTest::init()
{ {
mav = new MAVLinkProtocol(); UnitTest::init();
uas = new UAS(mav, QThread::currentThread(), UASID);
uas->deleteSettings(); _mavlink = new MAVLinkProtocol();
_uas = new UAS(_mavlink, QThread::currentThread(), UASID);
_uas->deleteSettings();
} }
//this function is called after every test //this function is called after every test
void UASUnitTest::cleanup() void UASUnitTest::cleanup()
{ {
delete uas; UnitTest::cleanup();
uas = NULL;
delete _uas;
_uas = NULL;
delete mav; delete _mavlink;
mav = NULL; _mavlink = NULL;
} }
void UASUnitTest::getUASID_test() void UASUnitTest::getUASID_test()
{ {
// Test a default ID of zero is assigned // Test a default ID of zero is assigned
UAS* uas2 = new UAS(mav, QThread::currentThread()); UAS* uas2 = new UAS(_mavlink, QThread::currentThread());
QCOMPARE(uas2->getUASID(), 0); QCOMPARE(uas2->getUASID(), 0);
delete uas2; delete uas2;
// Test that the chosen ID was assigned at construction // Test that the chosen ID was assigned at construction
QCOMPARE(uas->getUASID(), UASID); QCOMPARE(_uas->getUASID(), UASID);
// Make sure that no other ID was set // Make sure that no other ID was set
QEXPECT_FAIL("", "When you set an ID it does not use the default ID of 0", Continue); QEXPECT_FAIL("", "When you set an ID it does not use the default ID of 0", Continue);
QCOMPARE(uas->getUASID(), 0); QCOMPARE(_uas->getUASID(), 0);
// Make sure that ID >= 0 // Make sure that ID >= 0
QCOMPARE(uas->getUASID(), 100); QCOMPARE(_uas->getUASID(), 100);
} }
void UASUnitTest::getUASName_test() void UASUnitTest::getUASName_test()
{ {
// Test that the name is build as MAV + ID // Test that the name is build as MAV + ID
QCOMPARE(uas->getUASName(), "MAV " + QString::number(UASID)); QCOMPARE(_uas->getUASName(), "MAV " + QString::number(UASID));
} }
void UASUnitTest::getUpTime_test() void UASUnitTest::getUpTime_test()
{ {
UAS* uas2 = new UAS(mav, QThread::currentThread()); UAS* uas2 = new UAS(_mavlink, QThread::currentThread());
// Test that the uptime starts at zero to a // Test that the uptime starts at zero to a
// precision of seconds // precision of seconds
QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0); QCOMPARE(floor(uas2->getUptime()/1000.0), 0.0);
...@@ -69,12 +75,12 @@ void UASUnitTest::getUpTime_test() ...@@ -69,12 +75,12 @@ void UASUnitTest::getUpTime_test()
void UASUnitTest::getCommunicationStatus_test() void UASUnitTest::getCommunicationStatus_test()
{ {
// Verify that upon construction the Comm status is disconnected // Verify that upon construction the Comm status is disconnected
QCOMPARE(uas->getCommunicationStatus(), static_cast<int>(UASInterface::COMM_DISCONNECTED)); QCOMPARE(_uas->getCommunicationStatus(), static_cast<int>(UASInterface::COMM_DISCONNECTED));
} }
void UASUnitTest::filterVoltage_test() void UASUnitTest::filterVoltage_test()
{ {
float verificar=uas->filterVoltage(0.4f); float verificar=_uas->filterVoltage(0.4f);
// We allow the voltage returned to be within a small delta // We allow the voltage returned to be within a small delta
const float allowedDelta = 0.05f; const float allowedDelta = 0.05f;
...@@ -84,153 +90,153 @@ void UASUnitTest::filterVoltage_test() ...@@ -84,153 +90,153 @@ void UASUnitTest::filterVoltage_test()
void UASUnitTest:: getAutopilotType_test() void UASUnitTest:: getAutopilotType_test()
{ {
int type = uas->getAutopilotType(); int type = _uas->getAutopilotType();
// Verify that upon construction the autopilot is set to -1 // Verify that upon construction the autopilot is set to -1
QCOMPARE(type, -1); QCOMPARE(type, -1);
} }
void UASUnitTest::setAutopilotType_test() void UASUnitTest::setAutopilotType_test()
{ {
uas->setAutopilotType(2); _uas->setAutopilotType(2);
// Verify that the autopilot is set // Verify that the autopilot is set
QCOMPARE(uas->getAutopilotType(), 2); QCOMPARE(_uas->getAutopilotType(), 2);
} }
//verify that the correct status is returned if a certain statue is given to uas //verify that the correct status is returned if a certain statue is given to _uas
void UASUnitTest::getStatusForCode_test() void UASUnitTest::getStatusForCode_test()
{ {
QString state, desc; QString state, desc;
state = ""; state = "";
desc = ""; desc = "";
uas->getStatusForCode(MAV_STATE_UNINIT, state, desc); _uas->getStatusForCode(MAV_STATE_UNINIT, state, desc);
QVERIFY(state == "UNINIT"); QVERIFY(state == "UNINIT");
uas->getStatusForCode(MAV_STATE_UNINIT, state, desc); _uas->getStatusForCode(MAV_STATE_UNINIT, state, desc);
QVERIFY(state == "UNINIT"); QVERIFY(state == "UNINIT");
uas->getStatusForCode(MAV_STATE_BOOT, state, desc); _uas->getStatusForCode(MAV_STATE_BOOT, state, desc);
QVERIFY(state == "BOOT"); QVERIFY(state == "BOOT");
uas->getStatusForCode(MAV_STATE_CALIBRATING, state, desc); _uas->getStatusForCode(MAV_STATE_CALIBRATING, state, desc);
QVERIFY(state == "CALIBRATING"); QVERIFY(state == "CALIBRATING");
uas->getStatusForCode(MAV_STATE_ACTIVE, state, desc); _uas->getStatusForCode(MAV_STATE_ACTIVE, state, desc);
QVERIFY(state == "ACTIVE"); QVERIFY(state == "ACTIVE");
uas->getStatusForCode(MAV_STATE_STANDBY, state, desc); _uas->getStatusForCode(MAV_STATE_STANDBY, state, desc);
QVERIFY(state == "STANDBY"); QVERIFY(state == "STANDBY");
uas->getStatusForCode(MAV_STATE_CRITICAL, state, desc); _uas->getStatusForCode(MAV_STATE_CRITICAL, state, desc);
QVERIFY(state == "CRITICAL"); QVERIFY(state == "CRITICAL");
uas->getStatusForCode(MAV_STATE_EMERGENCY, state, desc); _uas->getStatusForCode(MAV_STATE_EMERGENCY, state, desc);
QVERIFY(state == "EMERGENCY"); QVERIFY(state == "EMERGENCY");
uas->getStatusForCode(MAV_STATE_POWEROFF, state, desc); _uas->getStatusForCode(MAV_STATE_POWEROFF, state, desc);
QVERIFY(state == "SHUTDOWN"); QVERIFY(state == "SHUTDOWN");
uas->getStatusForCode(5325, state, desc); _uas->getStatusForCode(5325, state, desc);
QVERIFY(state == "UNKNOWN"); QVERIFY(state == "UNKNOWN");
} }
void UASUnitTest::getLocalX_test() void UASUnitTest::getLocalX_test()
{ {
QCOMPARE(uas->getLocalX(), 0.0); QCOMPARE(_uas->getLocalX(), 0.0);
} }
void UASUnitTest::getLocalY_test() void UASUnitTest::getLocalY_test()
{ {
QCOMPARE(uas->getLocalY(), 0.0); QCOMPARE(_uas->getLocalY(), 0.0);
} }
void UASUnitTest::getLocalZ_test() void UASUnitTest::getLocalZ_test()
{ {
QCOMPARE(uas->getLocalZ(), 0.0); QCOMPARE(_uas->getLocalZ(), 0.0);
} }
void UASUnitTest::getLatitude_test() void UASUnitTest::getLatitude_test()
{ {
QCOMPARE(uas->getLatitude(), 0.0); QCOMPARE(_uas->getLatitude(), 0.0);
} }
void UASUnitTest::getLongitude_test() void UASUnitTest::getLongitude_test()
{ {
QCOMPARE(uas->getLongitude(), 0.0); QCOMPARE(_uas->getLongitude(), 0.0);
} }
void UASUnitTest::getAltitudeAMSL_test() void UASUnitTest::getAltitudeAMSL_test()
{ {
QCOMPARE(uas->getAltitudeAMSL(), 0.0); QCOMPARE(_uas->getAltitudeAMSL(), 0.0);
} }
void UASUnitTest::getAltitudeRelative_test() void UASUnitTest::getAltitudeRelative_test()
{ {
QCOMPARE(uas->getAltitudeRelative(), 0.0); QCOMPARE(_uas->getAltitudeRelative(), 0.0);
} }
void UASUnitTest::getRoll_test() void UASUnitTest::getRoll_test()
{ {
QCOMPARE(uas->getRoll(), 0.0); QCOMPARE(_uas->getRoll(), 0.0);
} }
void UASUnitTest::getPitch_test() void UASUnitTest::getPitch_test()
{ {
QCOMPARE(uas->getPitch(), 0.0); QCOMPARE(_uas->getPitch(), 0.0);
} }
void UASUnitTest::getYaw_test() void UASUnitTest::getYaw_test()
{ {
QCOMPARE(uas->getYaw(), 0.0); QCOMPARE(_uas->getYaw(), 0.0);
} }
void UASUnitTest::getSelected_test() void UASUnitTest::getSelected_test()
{ {
QCOMPARE(uas->getSelected(), false); QCOMPARE(_uas->getSelected(), false);
} }
void UASUnitTest::getSystemType_test() void UASUnitTest::getSystemType_test()
{ //check that system type is set to MAV_TYPE_GENERIC when initialized { //check that system type is set to MAV_TYPE_GENERIC when initialized
QCOMPARE(uas->getSystemType(), 0); QCOMPARE(_uas->getSystemType(), 0);
uas->setSystemType(13); _uas->setSystemType(13);
QCOMPARE(uas->getSystemType(), 13); QCOMPARE(_uas->getSystemType(), 13);
} }
void UASUnitTest::getAirframe_test() void UASUnitTest::getAirframe_test()
{ {
//when uas is constructed, airframe is set to QGC_AIRFRAME_GENERIC //when _uas is constructed, airframe is set to QGC_AIRFRAME_GENERIC
QVERIFY(uas->getAirframe() == UASInterface::QGC_AIRFRAME_GENERIC); QVERIFY(_uas->getAirframe() == UASInterface::QGC_AIRFRAME_GENERIC);
} }
void UASUnitTest::setAirframe_test() void UASUnitTest::setAirframe_test()
{ {
//check at construction, that airframe=0 (GENERIC) //check at construction, that airframe=0 (GENERIC)
QVERIFY(uas->getAirframe() == UASInterface::QGC_AIRFRAME_GENERIC); QVERIFY(_uas->getAirframe() == UASInterface::QGC_AIRFRAME_GENERIC);
//check that set airframe works //check that set airframe works
uas->setAirframe(UASInterface::QGC_AIRFRAME_HEXCOPTER); _uas->setAirframe(UASInterface::QGC_AIRFRAME_HEXCOPTER);
QVERIFY(uas->getAirframe() == UASInterface::QGC_AIRFRAME_HEXCOPTER); QVERIFY(_uas->getAirframe() == UASInterface::QGC_AIRFRAME_HEXCOPTER);
//check that setAirframe will not assign a number to airframe, that is //check that setAirframe will not assign a number to airframe, that is
//not defined in the enum //not defined in the enum
uas->setAirframe(UASInterface::QGC_AIRFRAME_END_OF_ENUM); _uas->setAirframe(UASInterface::QGC_AIRFRAME_END_OF_ENUM);
QVERIFY(uas->getAirframe() == UASInterface::QGC_AIRFRAME_HEXCOPTER); QVERIFY(_uas->getAirframe() == UASInterface::QGC_AIRFRAME_HEXCOPTER);
} }
void UASUnitTest::getWaypointList_test() void UASUnitTest::getWaypointList_test()
{ {
QList<Waypoint*> kk = uas->getWaypointManager()->getWaypointEditableList(); QList<Waypoint*> kk = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(kk.count(), 0); QCOMPARE(kk.count(), 0);
Waypoint* wp = new Waypoint(0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah"); Waypoint* wp = new Waypoint(0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah");
uas->getWaypointManager()->addWaypointEditable(wp, true); _uas->getWaypointManager()->addWaypointEditable(wp, true);
kk = uas->getWaypointManager()->getWaypointEditableList(); kk = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(kk.count(), 1); QCOMPARE(kk.count(), 1);
wp = new Waypoint(); wp = new Waypoint();
uas->getWaypointManager()->addWaypointEditable(wp, false); _uas->getWaypointManager()->addWaypointEditable(wp, false);
kk = uas->getWaypointManager()->getWaypointEditableList(); kk = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(kk.count(), 2); QCOMPARE(kk.count(), 2);
uas->getWaypointManager()->removeWaypoint(1); _uas->getWaypointManager()->removeWaypoint(1);
kk = uas->getWaypointManager()->getWaypointEditableList(); kk = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(kk.count(), 1); QCOMPARE(kk.count(), 1);
uas->getWaypointManager()->removeWaypoint(0); _uas->getWaypointManager()->removeWaypoint(0);
kk = uas->getWaypointManager()->getWaypointEditableList(); kk = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(kk.count(), 0); QCOMPARE(kk.count(), 0);
qDebug()<<"disconnect SIGNAL waypointListChanged"; qDebug()<<"disconnect SIGNAL waypointListChanged";
...@@ -241,16 +247,16 @@ void UASUnitTest::getWaypoint_test() ...@@ -241,16 +247,16 @@ void UASUnitTest::getWaypoint_test()
{ {
Waypoint* wp = new Waypoint(0,5.6,2.0,3.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah"); Waypoint* wp = new Waypoint(0,5.6,2.0,3.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah");
uas->getWaypointManager()->addWaypointEditable(wp, true); _uas->getWaypointManager()->addWaypointEditable(wp, true);
QList<Waypoint*> wpList = uas->getWaypointManager()->getWaypointEditableList(); QList<Waypoint*> wpList = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(wpList.count(), 1); QCOMPARE(wpList.count(), 1);
QCOMPARE(static_cast<quint16>(0), static_cast<Waypoint*>(wpList.at(0))->getId()); QCOMPARE(static_cast<quint16>(0), static_cast<Waypoint*>(wpList.at(0))->getId());
Waypoint* wp3 = new Waypoint(1, 5.6, 2.0, 3.0); Waypoint* wp3 = new Waypoint(1, 5.6, 2.0, 3.0);
uas->getWaypointManager()->addWaypointEditable(wp3, true); _uas->getWaypointManager()->addWaypointEditable(wp3, true);
wpList = uas->getWaypointManager()->getWaypointEditableList(); wpList = _uas->getWaypointManager()->getWaypointEditableList();
Waypoint* wp2 = static_cast<Waypoint*>(wpList.at(0)); Waypoint* wp2 = static_cast<Waypoint*>(wpList.at(0));
QCOMPARE(wpList.count(), 2); QCOMPARE(wpList.count(), 2);
...@@ -267,34 +273,34 @@ void UASUnitTest::getWaypoint_test() ...@@ -267,34 +273,34 @@ void UASUnitTest::getWaypoint_test()
void UASUnitTest::signalWayPoint_test() void UASUnitTest::signalWayPoint_test()
{ {
QSignalSpy spy(uas->getWaypointManager(), SIGNAL(waypointEditableListChanged())); QSignalSpy spy(_uas->getWaypointManager(), SIGNAL(waypointEditableListChanged()));
Waypoint* wp = new Waypoint(0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah"); Waypoint* wp = new Waypoint(0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah");
uas->getWaypointManager()->addWaypointEditable(wp, true); _uas->getWaypointManager()->addWaypointEditable(wp, true);
QCOMPARE(spy.count(), 1); // 1 listChanged for add wayPoint QCOMPARE(spy.count(), 1); // 1 listChanged for add wayPoint
uas->getWaypointManager()->removeWaypoint(0); _uas->getWaypointManager()->removeWaypoint(0);
QCOMPARE(spy.count(), 2); // 2 listChanged for remove wayPoint QCOMPARE(spy.count(), 2); // 2 listChanged for remove wayPoint
QSignalSpy spyDestroyed(uas->getWaypointManager(), SIGNAL(destroyed())); QSignalSpy spyDestroyed(_uas->getWaypointManager(), SIGNAL(destroyed()));
QVERIFY(spyDestroyed.isValid()); QVERIFY(spyDestroyed.isValid());
QCOMPARE( spyDestroyed.count(), 0 ); QCOMPARE( spyDestroyed.count(), 0 );
delete uas;// delete(destroyed) uas for validating delete _uas;// delete(destroyed) _uas for validating
uas = NULL; _uas = NULL;
QCOMPARE(spyDestroyed.count(), 1);// count destroyed uas should are 1 QCOMPARE(spyDestroyed.count(), 1);// count destroyed _uas should are 1
uas = new UAS(mav, QThread::currentThread(), UASID); _uas = new UAS(_mavlink, QThread::currentThread(), UASID);
QSignalSpy spy2(uas->getWaypointManager(), SIGNAL(waypointEditableListChanged())); QSignalSpy spy2(_uas->getWaypointManager(), SIGNAL(waypointEditableListChanged()));
QCOMPARE(spy2.count(), 0); QCOMPARE(spy2.count(), 0);
Waypoint* wp2 = new Waypoint(0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah"); Waypoint* wp2 = new Waypoint(0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,false, false, MAV_FRAME_GLOBAL, MAV_CMD_MISSION_START, "blah");
uas->getWaypointManager()->addWaypointEditable(wp2, true); _uas->getWaypointManager()->addWaypointEditable(wp2, true);
QCOMPARE(spy2.count(), 1); QCOMPARE(spy2.count(), 1);
uas->getWaypointManager()->clearWaypointList(); _uas->getWaypointManager()->clearWaypointList();
QList<Waypoint*> wpList = uas->getWaypointManager()->getWaypointEditableList(); QList<Waypoint*> wpList = _uas->getWaypointManager()->getWaypointEditableList();
QCOMPARE(wpList.count(), 1); QCOMPARE(wpList.count(), 1);
delete uas; delete _uas;
uas = NULL; _uas = NULL;
delete wp2; delete wp2;
} }
#ifndef UASUNITTEST_H #ifndef UASUNITTEST_H
#define UASUNITTEST_H #define UASUNITTEST_H
#include <QObject>
#include <QtCore/QString>
#include <QtTest/QtTest>
#include <QApplication>
#include "UAS.h" #include "UAS.h"
#include "MAVLinkProtocol.h" #include "MAVLinkProtocol.h"
#include "SerialLink.h" #include "SerialLink.h"
#include "UASInterface.h" #include "UASInterface.h"
#include "AutoTest.h" #include "UnitTest.h"
#include "LinkManager.h" #include "LinkManager.h"
#include "UASWaypointManager.h" #include "UASWaypointManager.h"
#include "SerialLink.h" #include "SerialLink.h"
#include "LinkInterface.h" #include "LinkInterface.h"
class UASUnitTest : public QObject #define UASID 100
class UASUnitTest : public UnitTest
{ {
Q_OBJECT Q_OBJECT
public: public:
#define UASID 100 UASUnitTest(void);
MAVLinkProtocol* mav;
UAS* uas;
UASUnitTest();
private slots: private slots:
void init(); UT_DECLARE_DEFAULT_initTestCase
void cleanup(); UT_DECLARE_DEFAULT_cleanupTestCase
void init(void);
void getUASID_test(); void cleanup(void);
void getUASName_test();
void getUpTime_test(); void getUASID_test(void);
void getCommunicationStatus_test(); void getUASName_test(void);
void filterVoltage_test(); void getUpTime_test(void);
void getAutopilotType_test(); void getCommunicationStatus_test(void);
void setAutopilotType_test(); void filterVoltage_test(void);
void getStatusForCode_test(); void getAutopilotType_test(void);
void getLocalX_test(); void setAutopilotType_test(void);
void getLocalY_test(); void getStatusForCode_test(void);
void getLocalZ_test(); void getLocalX_test(void);
void getLatitude_test(); void getLocalY_test(void);
void getLongitude_test(); void getLocalZ_test(void);
void getAltitudeAMSL_test(); void getLatitude_test(void);
void getAltitudeRelative_test(); void getLongitude_test(void);
void getRoll_test(); void getAltitudeAMSL_test(void);
void getPitch_test(); void getAltitudeRelative_test(void);
void getYaw_test(); void getRoll_test(void);
void getSelected_test(); void getPitch_test(void);
void getSystemType_test(); void getYaw_test(void);
void getAirframe_test(); void getSelected_test(void);
void setAirframe_test(); void getSystemType_test(void);
void getWaypointList_test(); void getAirframe_test(void);
void signalWayPoint_test(); void setAirframe_test(void);
void getWaypoint_test(); void getWaypointList_test(void);
void signalWayPoint_test(void);
void getWaypoint_test(void);
private:
MAVLinkProtocol* _mavlink;
UAS* _uas;
}; };
DECLARE_TEST(UASUnitTest) #endif
#endif // UASUNITTEST_H
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @brief Base class for all unit tests
///
/// @author Don Gagne <don@thegagnes.com>
#include "UnitTest.h"
#include "QGCApplication.h"
bool UnitTest::_messageBoxRespondedTo = false;
bool UnitTest::_badResponseButton = false;
QMessageBox::StandardButton UnitTest::_messageBoxResponseButton = QMessageBox::NoButton;
int UnitTest::_missedMessageBoxCount = 0;
UnitTest::UnitTest(void) :
_unitTestRun(false),
_initTestCaseCalled(false),
_cleanupTestCaseCalled(false),
_initCalled(false),
_cleanupCalled(false)
{
}
UnitTest::~UnitTest()
{
if (_unitTestRun) {
// Derived classes must call base class implementations
Q_ASSERT(_initTestCaseCalled);
Q_ASSERT(_cleanupTestCaseCalled);
Q_ASSERT(_initCalled);
Q_ASSERT(_cleanupCalled);
}
}
void UnitTest::_addTest(QObject* test)
{
QList<QObject*>& tests = _testList();
Q_ASSERT(!tests.contains(test));
tests.append(test);
}
void UnitTest::_unitTestCalled(void)
{
_unitTestRun = true;
}
/// @brief Returns the list of unit tests.
QList<QObject*>& UnitTest::_testList(void)
{
static QList<QObject*> tests;
return tests;
}
int UnitTest::run(int argc, char *argv[], QString& singleTest)
{
int ret = 0;
foreach (QObject* test, _testList()) {
if (singleTest.isEmpty() || singleTest == test->objectName()) {
ret += QTest::qExec(test, argc, argv);
}
}
return ret;
}
/// @brief Called at the initialization of the entire unit test.
/// Make sure to call first in your derived class
void UnitTest::initTestCase(void)
{
_initTestCaseCalled = true;
_missedMessageBoxCount = 0;
_badResponseButton = false;
}
/// @brief Called at the end of the entire unit test.
/// Make sure to call first in your derived class
void UnitTest::cleanupTestCase(void)
{
_cleanupTestCaseCalled = true;
int missedMessageBoxCount = _missedMessageBoxCount;
_missedMessageBoxCount = 0;
// Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
QCOMPARE(missedMessageBoxCount, 0);
}
/// @brief Called before each test.
/// Make sure to call first in your derived class
void UnitTest::init(void)
{
_initCalled = true;
_messageBoxRespondedTo = false;
_missedMessageBoxCount = 0;
_badResponseButton = false;
_messageBoxResponseButton = QMessageBox::NoButton;
// Each test gets a clean global state
qgcApp()->destroySingletonsForUnitTest();
qgcApp()->createSingletonsForUnitTest();
}
/// @brief Called after each test.
/// Make sure to call first in your derived class
void UnitTest::cleanup(void)
{
_cleanupCalled = true;
int missedMessageBoxCount = _missedMessageBoxCount;
_missedMessageBoxCount = 0;
// Make sure to reset any needed variables since this can fall and cause the rest of the method to be skipped
QCOMPARE(missedMessageBoxCount, 0);
}
void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response)
{
Q_ASSERT(!_messageBoxRespondedTo);
// We use an obsolete StandardButton value to signal that response button has not been set. So you can't use this.
Q_ASSERT(response != QMessageBox::NoButton);
Q_ASSERT(_messageBoxResponseButton == QMessageBox::NoButton);
int missedMessageBoxCount = _missedMessageBoxCount;
_missedMessageBoxCount = 0;
QCOMPARE(missedMessageBoxCount, 0);
_messageBoxResponseButton = response;
}
void UnitTest::checkExpectedMessageBox(int expectFailFlags)
{
// Previous call to setExpectedMessageBox should have already checked this
Q_ASSERT(_missedMessageBoxCount == 0);
// Check for a valid response
if (expectFailFlags & expectFailBadResponseButton) {
QEXPECT_FAIL("", "Expecting failure due to bad button response", Continue);
}
QCOMPARE(_badResponseButton, false);
if (expectFailFlags & expectFailNoMessageBox) {
QEXPECT_FAIL("", "Expecting failure due to no message box", Continue);
}
QCOMPARE(_messageBoxRespondedTo, true);
}
QMessageBox::StandardButton UnitTest::_messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
{
QMessageBox::StandardButton retButton;
Q_UNUSED(icon);
Q_UNUSED(title);
Q_UNUSED(text);
if (_messageBoxResponseButton == QMessageBox::NoButton) {
// If no response button is set it means we were not expecting this message box. Response with default
_missedMessageBoxCount++;
retButton = defaultButton;
} else {
if (_messageBoxResponseButton & buttons) {
// Everything is correct, use the specified response
retButton = _messageBoxResponseButton;
} else {
// Trying to respond with a button not in the dialog. This is an error. Respond with default
_badResponseButton = true;
retButton = defaultButton;
}
_messageBoxRespondedTo = true;
}
// Clear response for next message box
_messageBoxResponseButton = QMessageBox::NoButton;
return retButton;
}
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @brief Base class for all unit tests
///
/// @author Don Gagne <don@thegagnes.com>
#ifndef UNITTEST_H
#define UNITTEST_H
#include <QObject>
#include <QtTest>
#include <QMessageBox>
#define UT_REGISTER_TEST(className) static UnitTestWrapper<className> t(#className);
/// @brief If you don't need you own specific implemenation of the test case setup methods
/// you can use these macros to declare the default implementation which just calls
/// the base class.
#define UT_DECLARE_DEFAULT_initTestCase
//virtual void initTestCase(void) { UnitTest::_initTestCase(); }
#define UT_DECLARE_DEFAULT_cleanupTestCase
// virtual void cleanupTestCase(void) { UnitTest::_cleanupTestCase(); }
#define UT_DECLARE_DEFAULT_init
//virtual void init(void) { UnitTest::_init(); }
#define UT_DECLARE_DEFAULT_cleanup
//virtual void cleanup(void) { UnitTest::_cleanup(); }
class QGCMessageBox;
class UnitTest;
class UnitTest : public QObject
{
Q_OBJECT
public:
UnitTest(void);
virtual ~UnitTest(void);
/// @brief Called to run all the registered unit tests
/// @param argc argc from main
/// @param argv argv from main
/// @param singleTest Name of test to just run a single test
static int run(int argc, char *argv[], QString& singleTest);
/// @brief Sets up for an expected QGCMessageBox
/// @param response Response to take on message box
void setExpectedMessageBox(QMessageBox::StandardButton response);
enum {
expectFailNoFailure = 1 << 0, ///< not expecting any failures
expectFailNoMessageBox = 1 << 1, ///< expecting a failure due to no message box displayed
expectFailBadResponseButton = 1 << 2 ///< expecting a failure due to bad button response
};
/// @brief Check whether a message box was displayed and correctly responded to
// @param Expected failure response flags
void checkExpectedMessageBox(int expectFailFlags = expectFailNoFailure);
/// @brief Adds a unit test to the list. Should only be called by UnitTestWrapper.
static void _addTest(QObject* test);
protected slots:
// These are all pure virtuals to force the derived class to implement each one and in turn
// call the UnitTest private implementation.
/// @brief Called at the initialization of the entire unit test.
/// Make sure to call _initTestCase first in your derived class.
virtual void initTestCase(void);
/// @brief Called at the end of the entire unit test.
/// Make sure to call _cleanupTestCase first in your derived class.
virtual void cleanupTestCase(void);
/// @brief Called before each test.
/// Make sure to call _init first in your derived class.
virtual void init(void);
/// @brief Called after each test.
/// Make sure to call _cleanup first in your derived class.
virtual void cleanup(void);
protected:
/// @brief Must be called first by derived class implementation
void _initTestCase(void);
/// @brief Must be called first by derived class implementation
void _cleanupTestCase(void);
/// @brief Must be called first by derived class implementation
void _init(void);
/// @brief Must be called first by derived class implementation
void _cleanup(void);
private:
// When the app is running in unit test mode the QGCMessageBox methods are re-routed here.
static QMessageBox::StandardButton _messageBox(QMessageBox::Icon icon, const QString& title, const QString& text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton);
// This allows the private call to _messageBox
friend class QGCMessageBox;
void _unitTestCalled(void);
static QList<QObject*>& _testList(void);
static bool _messageBoxRespondedTo; ///< Message box was responded to
static bool _badResponseButton; ///< Attempt to repond to expected message box with button not being displayed
static QMessageBox::StandardButton _messageBoxResponseButton; ///< Response to next message box
static int _missedMessageBoxCount; ///< Count of message box not checked with call to messageBoxWasDisplayed
bool _unitTestRun; ///< true: Unit Test was run
bool _initTestCaseCalled; ///< true: UnitTest::_initTestCase was called
bool _cleanupTestCaseCalled; ///< true: UnitTest::_cleanupTestCase was called
bool _initCalled; ///< true: UnitTest::_init was called
bool _cleanupCalled; ///< true: UnitTest::_cleanup was called
};
template <class T>
class UnitTestWrapper {
public:
UnitTestWrapper(const QString& name) :
_unitTest(new T)
{
_unitTest->setObjectName(name);
UnitTest::_addTest(_unitTest.data());
}
private:
QSharedPointer<T> _unitTest;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment