こんにちは この記事は、Sailfish OSモバイルプラットフォームの開発とテストに関する一連の記事の続きです。
以前の記事の1つは、アプリケーションのQMLコンポーネントのテストに当てられていました。 ただし、開発者は多くの場合、QMLで利用できない機能を使用したり、パフォーマンスを改善したりするために、独自のコンポーネントをC ++で記述する必要に直面しています。 これも
書かれています。 こうしたコンポーネントのテストは、既存のコンポーネントのテストとは異なります。 この記事では、C ++で作成された独自のQMLコンポーネントをテストする方法を示します。
テストアプリケーション
アプリケーションとして、
前回の記事で取り上げたものと同じものを取り上げましょう-カウンターアプリケーション(アプリケーションのソースコードは
GitHubで入手可能です)。 現在の実装では、カウンター値はページプロパティに保存されます。 この値は、追加ボタンとリセットボタンをクリックすると変更され、ビューに表示するために使用されます。
C ++で記述されたコードを使用して値が保存および変更されるように、アプリケーションを変更します。 次のような
Counterクラスを追加します。
このクラスは
QObjectから継承され、本体に
Q_OBJECTマクロが含まれているため、QMLにエクスポートできます。 クラスには、単一の読み取り専用プロパティ
countが含まれ
ます 。
incrementCount()および
resetCount()メソッドは、このプロパティの値を変更するために使用されます。 メソッドは
Q_INVOKABLEマクロでマークされているため、QMLから呼び出すことができます。
C ++で記述されたクラスをQMLで使用するには、クラスをQMLタイプとして登録する必要があります。 これは通常、アプリケーションの
main()関数の本体で行われます。 この場合、これはできません。 事実、
qmltestrunnerはテストの実行時にアプリケーションのメイン関数を呼び出しません。
QMLプラグイン
QMLプラグインを使用して、上記の問題を解決でき
ます 。 アイデアは、C ++コードをライブラリに割り当て、アプリケーションとテストを開始するときに使用することです。 この場合のQMLタイプの登録は、QMLプラグインに転送されます。
プラグインを作成するには、プロジェクトを2つの部分に分割する必要があります。 各部分の下に、ディレクトリの名前に対応する名前の
* .proファイルを含むサブプロジェクトでディレクトリを作成します。 最初のサブプロジェクト
コアを呼び出します。これには、
main()関数を持つ
* .cppファイルを除くすべてのC ++コードが含まれます。 2つ目は
アプリで 、QMLファイル、
* .desktopファイル、および翻訳ファイルが含まれます。 ここでは、
main()関数を使用して
* .cppファイルを配置します。
core.proファイルは次のとおりです。
TEMPLATE = lib TARGET = core CONFIG += qt plugin c++11 QT += qml\ quick\ HEADERS += \ counter.h SOURCES += \ counter.cpp DISTFILES += qmldir uri = counter.cpp.application.Core qmldir.files = qmldir installPath = /usr/lib/counter-cpp-application/$$replace(uri, \\., /) qmldir.path = $$installPath target.path = $$installPath INSTALLS += target qmldir
core.proでは、 TEMPLATE = libを使用して、サブプロジェクトをライブラリーとして使用する必要があります。 ライブラリ(
TARGET )の目的は、その名前、つまり
コア CONFIGで 、ライブラリがプラグインとして接続していることを示す
プラグインを追加してください。
DISTFILESで 、
qmldirファイルへのパスを追加する必要があります。このファイルは
コアディレクトリにあり、モジュールとプラグインの名前を含む必要があります。 この場合、このファイルの次の内容は次のようになります。
module counter.cpp.application.Core plugin core
core.proファイルの最後に、ライブラリファイルと
qmldirファイルへのパスを指定
する必要
があります。 ライブラリをディレクトリ
/ usr / lib /に配置し、プラグイン
カウンタ/ cpp / application / Coreへのパスを指定します。
app.proファイルには、アプリケーション自体の構成が含まれています。 ターゲットアプリケーション、qmlファイルへのパス、アイコン、および翻訳がここに示されています。 ここで、main関数を使用して
* .cppファイルを追加します。 この例では、ファイルの形式は次のとおりです。
TARGET = counter-cpp-application CONFIG += sailfishapp \ sailfishapp_i18n \ c++11 SOURCES += src/counter-cpp-application.cpp OTHER_FILES += qml/counter-cpp-application.qml \ qml/cover/CoverPage.qml \ translations/*.ts \ counter-cpp-application.desktop TRANSLATIONS += translations/counter-cpp-application-de.ts SAILFISHAPP_ICONS = 86x86 108x108 128x128 256x256 DISTFILES += \ qml/CounterCppApplication.qml \ qml/pages/CounterPage.qml
ここで、作成した2つのサブプロジェクトが含まれるように
* .proプロジェクトファイルを変更する必要があります。 これを行うには、
TEMPLATE = subdirsをこのファイルに追加し、ディレクトリをサブプロジェクトとして追加します。 この場合、これらのディレクトリにあるサブプロジェクトが順番に収集されます。 ここでは、プロジェクトファイルは常にメインプロジェクトのルートにある必要があるため、
rpmディレクトリからプロジェクトファイルを追加したままにする必要があります。 このアプリケーションでは、次のようになります。
TEMPLATE = subdirs OTHER_FILES += $$files(rpm/*) SUBDIRS += \ app \ core app.depends = core
ここで、
アプリサブプロジェクトは
コアに依存していることを指摘しました。
プロジェクト構造が準備できたので、プラグインの実装を開始できます。 C ++クラスを作成する必要があります。これを
CorePluginと呼び
ます 。 クラスは
QQmlExtensionPluginから継承する必要があります。 タイプを登録し、エンジンを初期化します。
QQmlExtensionPluginクラスには、オーバーライドできる2つのメソッドがあります。
- registerTypes(const char * uri) :QMLタイプを登録するために必要です。 プラグインのURIは、 qmldirsファイルで指定されており、パラメーターとしてメソッドに渡されます。
- initializeEngine(QQmlEngine * engine、const char * uri) :アプリケーションのエンジンを初期化するために必要です。 最初のパラメーターはアプリケーションを構成できるQMLエンジンで、2番目はプラグインURIです。
ここでは、最初の方法のみで十分です。 これを使用して、
Counterクラスを登録します。
registerTypes()メソッドの本体に、次を入力します。
qmlRegisterType<Counter>(uri, 1, 0, "Counter")
山括弧内に、登録されたクラスの名前が示されます。 最初のパラメーターはプラグインのURIです。 2番目と3番目のパラメーターは、メジャーバージョン番号とマイナーバージョン番号です。 4番目のパラメーターは、QMLのクラスを使用できる名前です。 これで、アプリケーションでタイプCounterを使用できます。
独自のQMLコンポーネントを使用する
次に、アプリケーションのメイン関数でライブラリへのパスを指定する必要があります。 これを行うには、アプリケーションとビューを手動で初期化する必要があります。 通常の場合、初期化は次のように実行されます。
int main(int argc, char *argv[]) { return SailfishApp::main(argc, argv); }
メイン()関数コードを変更して、ライブラリパスを示します。
int main(int argc, char *argv[]) { QGuiApplication* app = SailfishApp::application(argc, argv); QQuickView* view = SailfishApp::createView(); view->engine()->addImportPath("/usr/lib/counter-cpp-application/"); view->setSource(SailfishApp::pathTo("qml/counter-cpp-application.qml")); view->showFullScreen(); QObject::connect(view->engine(), &QQmlEngine::quit, app, &QGuiApplication::quit); return app->exec(); }
ここで、アプリケーションとビューのインスタンスを作成します。 次に、ライブラリへのパス、アプリケーションのメインQMLファイルへのパスを指定し、全画面表示を表示します。 最後に、アプリケーションの終了ハンドラーを構成して実行します。 これで、作成したライブラリをQMLファイルにインポートして、
カウンタータイプを使用できます。
前の記事の
CounerPage.qmlファイルに基づいています。 次のようにプラグインを追加します。
import counter.cpp.application.Core 1.0
以前に
qmldirsファイルで指定されたURIと、タイプの登録時に指定されたバージョン1.0を使用します。 タイプを使用するには、ページ内にタイプを追加します。
Counter { id: counter }
ここで、countプロパティの値を変更する代わりに、カウンターを追加およびリセットするときに、それぞれ
counter.increment()および
counter.reset()メソッドを呼び出し
ます 。
テストコードは、視覚コンポーネントを変更しなかったため、前の記事と同じままです。
テストを実行する
テストは
qmltestrunnerを使用して
起動されます。 コードの一部がQMLプラグインに渡されるため、手動でパスを指定する必要があります。 これを行うには、テストを実行する前にライブラリファイルへのパスが割り当てられている変数
QML2_IMPORT_PATHを使用します。 その結果、問題のアプリケーションでは、次のようになります。
QML2_IMPORT_PATH=/usr/lib/counter-cpp-application/ /usr/lib/qt5/bin/qmltestrunner -input /usr/share/counter-cpp-application/tests/
テストコードと結果の出力は、
前の記事と同じままです。
********* Start testing of qmltestrunner ********* Config: Using QtTest library 5.2.2, Qt 5.2.2 PASS : qmltestrunner::Counter tests::initTestCase() PASS : qmltestrunner::Counter tests::test_counterAdd() PASS : qmltestrunner::Counter tests::test_counterReset() PASS : qmltestrunner::Counter tests::cleanupTestCase() Totals: 4 passed, 0 failed, 0 skipped ********* Finished testing of qmltestrunner *********
おわりに
独自のQMLコンポーネントのテストは、QtQuickライブラリで既に利用可能なテストとは異なります。 それらをテストする可能性を実現するには、QMLプラグイン内のすべてのC ++コードを選択し、ライブラリとして接続する必要がありました。 その結果、テストコードは標準のQMLコンポーネントをテストするコードと変わりません。 それにもかかわらず、プロジェクト自体に大きな変更が必要でした。 この形式のアプリケーションは、ストアで公開するときにすでに使用できます。 この例のソースコードは
GitHubで入手でき
ます 。
技術的な問題
は、ロシア語を話すコミュニティのSailfish OSのTelegramまたは
VKontakteグループの
チャネルでも議論できます。
著者:セルゲイ・アヴェルキエフ