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)
|
||||
|
||||
project(TestControls LANGUAGES CXX)
|
||||
project(TestStatusQ LANGUAGES CXX)
|
||||
|
||||
enable_testing()
|
||||
|
||||
# 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(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_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 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_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
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
|
@ -33,11 +35,10 @@ target_include_directories(${PROJECT_NAME}
|
|||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
add_subdirectory(TestHelpers)
|
||||
add_subdirectory(src)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Qt${QT_VERSION_MAJOR}::QuickTest
|
||||
Qt${QT_VERSION_MAJOR}::Qml
|
||||
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
|
||||
|
||||
function initTestCase() {
|
||||
function init() {
|
||||
qtOuput.restartCapturing()
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
|
|
|
@ -38,7 +38,8 @@ Item {
|
|||
|
||||
//
|
||||
// Test guards
|
||||
function initTestCase() {
|
||||
function init() {
|
||||
qtOuput.restartCapturing()
|
||||
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)
|
||||
{
|
||||
// TODO: Workaround until we make StatusQ a CMake library
|
||||
engine->addImportPath("../../src/");
|
||||
engine->addImportPath(".");
|
||||
engine->addImportPath("../src/");
|
||||
engine->addImportPath("./qml/");
|
||||
// TODO: Alternative to not yet supported QML_ELEMENT
|
||||
qmlRegisterType<MonitorQtOutput>("StatusQ.TestHelpers", 0, 1, "MonitorQtOutput");
|
||||
}
|
||||
private:
|
||||
MonitorQtOutput _monitorOutput;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
```sh
|
||||
cd StatusQ/tests/TestControls
|
||||
cd ./tests/
|
||||
cmake -B ./build/ -S .
|
||||
cmake --build ./build/
|
||||
./build/TestControls
|
||||
ctest --test-dir ./build/
|
||||
```
|
||||
|
||||
QtCreator
|
||||
|
||||
- Open the StatusQ/tests/CMakeLists.txt
|
||||
- Open the `./tests/CMakeLists.txt`
|
||||
- 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
|
||||
|
||||
- [ ] 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}
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MonitorQtOutput.h
|
|
@ -5,19 +5,21 @@
|
|||
|
||||
std::weak_ptr<QString> MonitorQtOutput::m_qtMessageOutputForSharing;
|
||||
std::mutex MonitorQtOutput::m_mutex;
|
||||
QtMessageHandler MonitorQtOutput::m_previousHandler = nullptr;
|
||||
|
||||
|
||||
MonitorQtOutput::MonitorQtOutput()
|
||||
{
|
||||
// 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);
|
||||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||
auto prev = qInstallMessageHandler(qtMessageOutput);
|
||||
if(prev != qtMessageOutput)
|
||||
m_previousHandler = prev;
|
||||
if(!globalMsgOut) {
|
||||
// Install message handler if not already done
|
||||
m_thisMessageOutput = std::make_shared<QString>();
|
||||
m_qtMessageOutputForSharing = m_thisMessageOutput;
|
||||
qInstallMessageHandler(qtMessageOutput);
|
||||
}
|
||||
else {
|
||||
m_thisMessageOutput = globalMsgOut;
|
||||
|
@ -42,11 +44,25 @@ MonitorQtOutput::qtMessageOutput(QtMsgType type, const QMessageLogContext &conte
|
|||
auto globalMsgOut = m_qtMessageOutputForSharing.lock();
|
||||
assert(globalMsgOut != nullptr);
|
||||
globalMsgOut->append(msg + '\n');
|
||||
// Also reproduce the default output
|
||||
m_previousHandler(type, context, msg);
|
||||
}
|
||||
|
||||
QString
|
||||
MonitorQtOutput::qtOuput()
|
||||
{
|
||||
std::unique_lock<std::mutex> localLock(m_mutex);
|
||||
assert(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