UnitTest.h 7.75 KB
Newer Older
Don Gagne's avatar
Don Gagne committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*=====================================================================
 
 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>
35
#include <QFileDialog>
Don Gagne's avatar
Don Gagne committed
36 37 38 39

#define UT_REGISTER_TEST(className) static UnitTestWrapper<className> t(#className);

class QGCMessageBox;
40
class QGCFileDialog;
Don Gagne's avatar
Don Gagne committed
41 42 43 44 45 46 47 48 49 50 51 52
class UnitTest;

class UnitTest : public QObject
{
    Q_OBJECT

public:
    UnitTest(void);
    virtual ~UnitTest(void);
    
    /// @brief Called to run all the registered unit tests
    ///     @param singleTest Name of test to just run a single test
53
    static int run(QString& singleTest);
Don Gagne's avatar
Don Gagne committed
54 55 56 57 58
    
    /// @brief Sets up for an expected QGCMessageBox
    ///     @param response Response to take on message box
    void setExpectedMessageBox(QMessageBox::StandardButton response);
    
59 60 61 62 63 64 65 66 67 68 69 70 71
    /// @brief Types for UnitTest::setExpectedFileDialog
    enum FileDialogType {
        getExistingDirectory,
        getOpenFileName,
        getOpenFileNames,
        getSaveFileName
    };
    
    /// @brief Sets up for an expected QGCFileDialog
    ///     @param type Type of expected file dialog
    ///     @param response Files to return from call. Multiple files only supported by getOpenFileNames
    void setExpectedFileDialog(enum FileDialogType type, QStringList response);
    
Don Gagne's avatar
Don Gagne committed
72 73
    enum {
        expectFailNoFailure =           1 << 0, ///< not expecting any failures
74 75 76
        expectFailNoDialog =            1 << 1, ///< expecting a failure due to no dialog displayed
        expectFailBadResponseButton =   1 << 2, ///< expecting a failure due to bad button response (QGCMessageBox only)
        expectFailWrongFileDialog =     1 << 3  ///< expecting one dialog type, got the wrong type (QGCFileDialog ony)
Don Gagne's avatar
Don Gagne committed
77 78 79 80 81 82
    };
    
    /// @brief Check whether a message box was displayed and correctly responded to
    //          @param Expected failure response flags
    void checkExpectedMessageBox(int expectFailFlags = expectFailNoFailure);
    
83 84 85 86
    /// @brief Check whether a message box was displayed and correctly responded to
    //          @param Expected failure response flags
    void checkExpectedFileDialog(int expectFailFlags = expectFailNoFailure);
    
Don Gagne's avatar
Don Gagne committed
87
    /// @brief Adds a unit test to the list. Should only be called by UnitTestWrapper.
Don Gagne's avatar
Don Gagne committed
88
    static void _addTest(QObject* test);
Don Gagne's avatar
Don Gagne committed
89

Don Gagne's avatar
Don Gagne committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103
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 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:
104 105 106
    bool _expectMissedFileDialog;   // true: expect a missed file dialog, used for internal testing
    bool _expectMissedMessageBox;   // true: expect a missed message box, used for internal testing
    
Don Gagne's avatar
Don Gagne committed
107 108
private:
    // When the app is running in unit test mode the QGCMessageBox methods are re-routed here.
109 110 111 112 113 114
    
    static QMessageBox::StandardButton _messageBox(QMessageBox::Icon icon,
                                                   const QString& title,
                                                   const QString& text,
                                                   QMessageBox::StandardButtons buttons,
                                                   QMessageBox::StandardButton defaultButton);
Don Gagne's avatar
Don Gagne committed
115 116 117 118
    
    // This allows the private call to _messageBox
    friend class QGCMessageBox;
    
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    // When the app is running in unit test mode the QGCFileDialog methods are re-routed here.
    
    static QString _getExistingDirectory(QWidget* parent,
                                         const QString& caption,
                                         const QString& dir,
                                         QFileDialog::Options options);
    
    static QString _getOpenFileName(QWidget* parent,
                                    const QString& caption,
                                    const QString& dir,
                                    const QString& filter,
                                    QString* selectedFilter,
                                    QFileDialog::Options options);
    
    static QStringList _getOpenFileNames(QWidget* parent,
                                         const QString& caption,
                                         const QString& dir,
                                         const QString& filter,
                                         QString* selectedFilter,
                                         QFileDialog::Options options);
    
    static QString _getSaveFileName(QWidget* parent,
                                    const QString& caption,
                                    const QString& dir,
                                    const QString& filter,
                                    QString* selectedFilter,
                                    QFileDialog::Options options);
    
    static QString _fileDialogResponseSingle(enum FileDialogType type);

    // This allows the private calls to the file dialog methods
    friend class QGCFileDialog;

Don Gagne's avatar
Don Gagne committed
152
    void _unitTestCalled(void);
Don Gagne's avatar
Don Gagne committed
153 154
	static QList<QObject*>& _testList(void);

155
    // Catch QGCMessageBox calls
Don Gagne's avatar
Don Gagne committed
156 157 158 159 160
    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
    
161 162 163 164 165 166 167
    // Catch QGCFileDialog calls
    static bool         _fileDialogRespondedTo;         ///< File dialog was responded to
    static bool         _fileDialogResponseSet;         ///< true: _fileDialogResponse was set by a call to UnitTest::setExpectedFileDialog
    static QStringList  _fileDialogResponse;            ///< Response to next file dialog
    static enum FileDialogType _fileDialogExpectedType; ///< type of file dialog expected to show
    static int          _missedFileDialogCount;         ///< Count of file dialogs not checked with call to UnitTest::fileDialogWasDisplayed
    
Don Gagne's avatar
Don Gagne committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    bool _unitTestRun;              ///< true: Unit Test was run
    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