tests(general): refactor tests
Enhance the CMake strucuture of thests Update documentation
This commit is contained in:
parent
59fc0a6669
commit
e293f80554
|
@ -0,0 +1,5 @@
|
||||||
|
cmake_minimum_required(VERSION 3.19)
|
||||||
|
|
||||||
|
project(StatusQ)
|
||||||
|
|
||||||
|
add_subdirectory(tests)
|
|
@ -1,11 +1,11 @@
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
project(TestControls LANGUAGES CXX)
|
project(TestStatusQ LANGUAGES CXX)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|
||||||
# TODO: Workaround until we make StatusQ a CMake library
|
# TODO: Workaround until we make StatusQ a CMake library
|
||||||
list(APPEND QML_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../../src/")
|
list(APPEND QML_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../src/")
|
||||||
set(QML_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths")
|
set(QML_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths")
|
||||||
set(QML2_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths")
|
set(QML2_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator extra qml import paths")
|
||||||
|
|
||||||
|
@ -14,18 +14,20 @@ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS QuickTest Qml Quick REQUIRED)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
# no need to copy around qml test files for shadow builds - just set the respective define
|
# no need to copy around qml test files for shadow builds - just set the respective define
|
||||||
add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
add_definitions(-DQUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
add_executable(${PROJECT_NAME} main.cpp)
|
add_executable(${PROJECT_NAME} main.cpp)
|
||||||
add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME})
|
|
||||||
|
add_test(NAME ${PROJECT_NAME} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME} -input "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
add_custom_target("Run_${PROJECT_NAME}" COMMAND ${CMAKE_CTEST_COMMAND} --test-dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
add_dependencies("Run_${PROJECT_NAME}" ${PROJECT_NAME})
|
||||||
|
|
||||||
# TODO: move this to a test helpers library
|
# TODO: move this to a test helpers library
|
||||||
target_include_directories(${PROJECT_NAME}
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
@ -33,11 +35,10 @@ target_include_directories(${PROJECT_NAME}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(TestHelpers)
|
add_subdirectory(src)
|
||||||
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
Qt${QT_VERSION_MAJOR}::QuickTest
|
Qt${QT_VERSION_MAJOR}::QuickTest
|
||||||
Qt${QT_VERSION_MAJOR}::Qml
|
Qt${QT_VERSION_MAJOR}::Qml
|
||||||
Qt${QT_VERSION_MAJOR}::Quick
|
Qt${QT_VERSION_MAJOR}::Quick
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
pragma Singleton
|
|
||||||
|
|
||||||
import QtQml 2.14
|
|
||||||
import QtTest 1.0
|
|
||||||
|
|
||||||
QtObject {
|
|
||||||
|
|
||||||
//> Simulate key and wait for side effects
|
|
||||||
function pressKeyAndWait(test, item, key) {
|
|
||||||
test.keyClick(key)
|
|
||||||
|
|
||||||
test.waitForRendering(item)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QQuickItem>
|
|
||||||
#include <QtGlobal>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
///
|
|
||||||
/// \brief Monitor output for tests and declarativelly control message handler availability
|
|
||||||
/// \todo Check that QML doesn't keep instance between test runs
|
|
||||||
///
|
|
||||||
class MonitorQtOutput : public QQuickItem
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
MonitorQtOutput();
|
|
||||||
~MonitorQtOutput();
|
|
||||||
|
|
||||||
Q_INVOKABLE QString qtOuput();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void qtMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
|
||||||
|
|
||||||
// Use it to keep track of qInstallMessageHandler call
|
|
||||||
static std::weak_ptr<QString> m_qtMessageOutputForSharing;
|
|
||||||
static std::mutex m_mutex;
|
|
||||||
std::shared_ptr<QString> m_thisMessageOutput;
|
|
||||||
int m_start = 0;
|
|
||||||
};
|
|
|
@ -26,7 +26,8 @@ Item {
|
||||||
//
|
//
|
||||||
// Test guards
|
// Test guards
|
||||||
|
|
||||||
function initTestCase() {
|
function init() {
|
||||||
|
qtOuput.restartCapturing()
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
|
|
|
@ -38,7 +38,8 @@ Item {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Test guards
|
// Test guards
|
||||||
function initTestCase() {
|
function init() {
|
||||||
|
qtOuput.restartCapturing()
|
||||||
mouseClick(statusInput)
|
mouseClick(statusInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
---
|
|
@ -0,0 +1,3 @@
|
||||||
|
Start testing: Apr 18 18:49 CEST
|
||||||
|
----------------------------------------------------------
|
||||||
|
End testing: Apr 18 18:49 CEST
|
|
@ -14,13 +14,11 @@ public slots:
|
||||||
void qmlEngineAvailable(QQmlEngine *engine)
|
void qmlEngineAvailable(QQmlEngine *engine)
|
||||||
{
|
{
|
||||||
// TODO: Workaround until we make StatusQ a CMake library
|
// TODO: Workaround until we make StatusQ a CMake library
|
||||||
engine->addImportPath("../../src/");
|
engine->addImportPath("../src/");
|
||||||
engine->addImportPath(".");
|
engine->addImportPath("./qml/");
|
||||||
// TODO: Alternative to not yet supported QML_ELEMENT
|
// TODO: Alternative to not yet supported QML_ELEMENT
|
||||||
qmlRegisterType<MonitorQtOutput>("StatusQ.TestHelpers", 0, 1, "MonitorQtOutput");
|
qmlRegisterType<MonitorQtOutput>("StatusQ.TestHelpers", 0, 1, "MonitorQtOutput");
|
||||||
}
|
}
|
||||||
private:
|
|
||||||
MonitorQtOutput _monitorOutput;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
QUICK_TEST_MAIN_WITH_SETUP(TestControls, TestSetup)
|
QUICK_TEST_MAIN_WITH_SETUP(TestControls, TestSetup)
|
|
@ -0,0 +1,23 @@
|
||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import QtQml 2.14
|
||||||
|
import QtTest 1.0
|
||||||
|
|
||||||
|
QtObject {
|
||||||
|
|
||||||
|
//> Simulate key and wait for side effects
|
||||||
|
function pressKeyAndWait(test, item, key) {
|
||||||
|
test.keyClick(key)
|
||||||
|
|
||||||
|
ensureRendered(test, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureRendered(test, item) {
|
||||||
|
test.verify(test.waitForRendering(item, 1000))
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectRendering(test, item) {
|
||||||
|
test.verify(test.isPolishScheduled(item))
|
||||||
|
test.verify(test.waitForRendering(item, 1000))
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,18 +5,21 @@
|
||||||
CMake
|
CMake
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd StatusQ/tests/TestControls
|
cd ./tests/
|
||||||
cmake -B ./build/ -S .
|
cmake -B ./build/ -S .
|
||||||
cmake --build ./build/
|
cmake --build ./build/
|
||||||
./build/TestControls
|
ctest --test-dir ./build/
|
||||||
```
|
```
|
||||||
|
|
||||||
QtCreator
|
QtCreator
|
||||||
|
|
||||||
- Open the StatusQ/tests/CMakeLists.txt
|
- Open the `./tests/CMakeLists.txt`
|
||||||
- Choose a QT kit to run the tests
|
- Choose a QT kit to run the tests
|
||||||
- In the `Test Results` panel choose Run All Tests
|
- Set `%{sourceDir}/tests` as Working Directory for the TestStatusQ target
|
||||||
|
- In the *Test Results* panel choose Run All Tests or just run the *TestStatusQ* target
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] Consolidate and integrate with https://github.com/status-im/desktop-ui-tests
|
- [ ] TestHelpers library
|
||||||
|
- [ ] Consolidate and integrate with https://github.com/status-im/desktop-ui-tests
|
||||||
|
- [ ] Separate projects per scope: TestControls, TestComponents
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
target_include_directories(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_subdirectory(TestHelpers)
|
|
@ -1,8 +1,3 @@
|
||||||
target_include_directories(${PROJECT_NAME}
|
|
||||||
PUBLIC
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_sources(${PROJECT_NAME}
|
target_sources(${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.h
|
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.h
|
|
@ -5,19 +5,21 @@
|
||||||
|
|
||||||
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
||||||
std::mutex MonitorQtOutput::m_mutex;
|
std::mutex MonitorQtOutput::m_mutex;
|
||||||
|
QtMessageHandler MonitorQtOutput::m_previousHandler = nullptr;
|
||||||
|
|
||||||
|
|
||||||
MonitorQtOutput::MonitorQtOutput()
|
MonitorQtOutput::MonitorQtOutput()
|
||||||
{
|
{
|
||||||
// Ensure only one instance registers a handler
|
// Ensure only one instance registers a handler
|
||||||
// Warning: don't QT's call loger functions inside the critical section
|
// Warning: don't call QT's logger functions inside the critical section
|
||||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||||
|
auto prev = qInstallMessageHandler(qtMessageOutput);
|
||||||
|
if(prev != qtMessageOutput)
|
||||||
|
m_previousHandler = prev;
|
||||||
if(!globalMsgOut) {
|
if(!globalMsgOut) {
|
||||||
// Install message handler if not already done
|
|
||||||
m_thisMessageOutput = std::make_shared<QString>();
|
m_thisMessageOutput = std::make_shared<QString>();
|
||||||
m_qtMessageOutputForSharing = m_thisMessageOutput;
|
m_qtMessageOutputForSharing = m_thisMessageOutput;
|
||||||
qInstallMessageHandler(qtMessageOutput);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_thisMessageOutput = globalMsgOut;
|
m_thisMessageOutput = globalMsgOut;
|
||||||
|
@ -42,11 +44,25 @@ MonitorQtOutput::qtMessageOutput(QtMsgType type, const QMessageLogContext &conte
|
||||||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||||
assert(globalMsgOut != nullptr);
|
assert(globalMsgOut != nullptr);
|
||||||
globalMsgOut->append(msg + '\n');
|
globalMsgOut->append(msg + '\n');
|
||||||
|
// Also reproduce the default output
|
||||||
|
m_previousHandler(type, context, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
MonitorQtOutput::qtOuput()
|
MonitorQtOutput::qtOuput()
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||||
assert(m_thisMessageOutput->length() >= m_start);
|
assert(m_thisMessageOutput->length() >= m_start);
|
||||||
return m_thisMessageOutput->right(m_thisMessageOutput->length() - m_start);
|
return m_thisMessageOutput->right(m_thisMessageOutput->length() - m_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MonitorQtOutput::restartCapturing()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||||
|
// Ensure the messageHandler is installed. Foun to be reset at test initializaiton
|
||||||
|
auto prev = qInstallMessageHandler(qtMessageOutput);
|
||||||
|
if(prev != qtMessageOutput)
|
||||||
|
m_previousHandler = prev;
|
||||||
|
m_start = m_thisMessageOutput->length();
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
///
|
||||||
|
/// \brief Monitor output for tests and declaratively control message handler availability
|
||||||
|
///
|
||||||
|
/// The captured buffer is global and each instance has a reference to it and a start pointer
|
||||||
|
/// from its creation or last clear call
|
||||||
|
/// The first instance installs a QT message handler @see Qt::qInstallMessageHandler then
|
||||||
|
/// All other instances share the global buffer until the last instance goes out of scope and deregisters
|
||||||
|
/// from Qt's global message handler and destroyes the buffer
|
||||||
|
///
|
||||||
|
/// \todo Check that QML doesn't keep instance between test runs
|
||||||
|
///
|
||||||
|
class MonitorQtOutput : public QQuickItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
MonitorQtOutput();
|
||||||
|
~MonitorQtOutput();
|
||||||
|
|
||||||
|
/// Return captured output from the global buffer. That is from the instantiation or last `clear()` was called
|
||||||
|
Q_INVOKABLE QString qtOuput();
|
||||||
|
/// Reset buffer start after the last line. qtOutput won't return anything until new output is captured
|
||||||
|
Q_INVOKABLE void restartCapturing();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void qtMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg);
|
||||||
|
static QtMessageHandler m_previousHandler;
|
||||||
|
|
||||||
|
// Use it to keep track of qInstallMessageHandler call
|
||||||
|
static std::weak_ptr<QString> m_qtMessageOutputForSharing;
|
||||||
|
static std::mutex m_mutex;
|
||||||
|
std::shared_ptr<QString> m_thisMessageOutput;
|
||||||
|
int m_start = 0;
|
||||||
|
};
|
Loading…
Reference in New Issue