Outdated version of the documentation. Find the latest one here.

ユニットテスト

2007年11月の時点で、私たちはマスターに入るすべての新機能は、ユニットテストを伴うことを要求しています。当初は私たちはこの要件はqgis_coreに制限してきましたが、皆様が次のセクションで説明するユニットテストのための手続きに精通した後は、この要件をコードベースの他の部分に拡張するつもりです。

QGISのテストフレームワーク - 概要

ユニットテストはQTestLib(Qtのテストライブラリ)とCTEST(CMakeのビルドプロセスの一部として、テストをコンパイルおよび実行するためのフレームワーク)の組み合わせを用いて行われます。詳細を掘り下げる前に、プロセスの概要をおさらいしましょう:

  • テストしたいコード、クラスや関数などがあります。エクストリームプログラミングの支持者は、テストの構築を開始するときでもコードはまだ書かれてはならないことを示唆している、その後コードを実装していくにつれてすぐにテストと追加したそれぞれの新しい機能部分を検証できます。実際上はpractiveのではおそらく、多くのアプリケーションロジックが既に実装された後もテストフレームワークを始めているので、QGISでの既存のコードのテストを記述する必要があるでしょう。

  • ユニットテストを作成します。これはcore libの場合 <QGIS Source Dir>/tests/src/core の下で起こります。テストは、基本的には、クラスのインスタンスを作成し、そのクラスにいくつかのメソッドを呼び出すクライアントです。それは各メソッドからの戻りをチェックし、期待値と一致することを確認します。呼び出しのいずれかに障害が発生した場合、そのユニットは失敗します。

  • テストクラスにQtTestLibマクロを含めます。このマクロは、Qtのメタオブジェクトコンパイラ(MOC)によって処理され、実行可能なアプリケーションにテストクラスを拡張します。

  • テストを構築するtestsディレクトリにCMakeLists.txtにセクションを追加します。

  • ENABLE_TESTING がccmake/cmakesetupで有効になっていることを確認します。これは、makeと入力すると、テストが実際にコンパイルされることを保証します。

  • テストがデータ駆動されている場合、必要に応じて <QGIS Source Dir>/tests/testdata にテストデータを追加します(例えばシェープファイルをロードする必要があります)。これらのテストデータは、可能な限り小さくすべきであると、可能な限り、すでにそこに既存のデータセットを使用する必要があります。テストはその場でこのデータを変更することはありませんが、むしろ一時的なコピーが必要な場合はどこかにしてもよいです。

  • ソースをコンパイルしてインストールします。これは通常の make && (sudo) make install 手順を使用して実行します。

  • テストを実行します。これは通常、単に make install ステップの後に make test を実行することによって行われますが、ここではテストを実行するよりきめの細かい制御を提供する他のアプローチaproachesを説明します。

心の中にその概要を持って、私は細部の少し掘り下げます。ユニットテストを書く - 私はまだする必要があるすべては容易なビットであるソースツリーにCMakeのと他の場所であなたのための設定の多くをやりました!

ユニットテストの作成

ユニットテストの作成は簡単です - 通常は、1つだけ.cppファイル(.hファイルでないが使用される)を作成することによってこれを行い、voidを返すpublicメソッドとしてすべてのテストメソッドを実装します。私は説明のために、次のセクション全体においてQgsRasterLayerのための簡単なテストクラスを使用します。慣例により、私たちのテストには、それらがテストしているクラスの前に「Test」と付けた名前を付けます。だから、私たちのテストの実装は testqgsrasterlayer.cpp というファイルに入り、クラス自体はTestQgsRasterLayerになります。まず、私たちは、標準的な著作権のバナーを追加します。

/***************************************************************************
 testqgsvectorfilewriter.cpp
 --------------------------------------
  Date : Friday, Jan 27, 2015
  Copyright: (C) 2015 by Tim Sutton
  Email: [email protected]
 ***************************************************************************
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 ***************************************************************************/

次に私たちは私たちが実行する予定のテストのために必要なインクルードを起動しますuse。すべてのテストが持つ必要がある1つの特別なインクルードがあります:

#include <QtTest/QtTest>

その他は、必要となる可能性があるヘッダは何でも引っ張って、通常通りあなたのクラスを実装し続けるだけです:

//Qt includes...
#include <QObject>
#include <QString>
#include <QObject>
#include <QApplication>
#include <QFileInfo>
#include <QDir>

//qgis includes...
#include <qgsrasterlayer.h>
#include <qgsrasterbandstats.h>
#include <qgsapplication.h>

ここではクラス宣言と実装の両方を単一のファイルに組み合わせているので、クラス宣言が次に来ます。doxygenのドキュメントで始めます。すべてのテストケースは適切に文書化されなければなりません。すべてのユニットテストが生成されたDoxygenのドキュメントのモジュールとして表示されるように、doxygenのingroupディレクティブを使用します。その後にユニットテストの短い説明が来て、このクラスはQObjectを継承し、Q_OBJECTマクロをインクルードする必要があります。

/** \ingroup UnitTests
 * This is a unit test for the QgsRasterLayer class.
 */

class TestQgsRasterLayer: public QObject
{
    Q_OBJECT

私たちのすべてのテスト方法は、プライベートなスロットとして実装されます。QtTestフレームワークを順次テストクラス内の各プライベートスロットメソッドを呼び出します。ユニットテスト(cleanupTestCase)の終了時に実施された場合、ユニットテスト(initTestCase)の開始時に呼び出される4つの「特別」なメソッドがあります。各テストメソッドが呼び出される前に、init()メソッドが呼び出されると、各テストメソッドが呼び出された後cleanup()メソッドが呼び出されます。これらの方法は、各テスト、そして全体としてのテストユニットを実行するのに先だってリソースを割り当ておよびクリーンアップできる点で便利です。

private slots:
  // will be called before the first testfunction is executed.
  void initTestCase();
  // will be called after the last testfunction was executed.
  void cleanupTestCase(){};
  // will be called before each testfunction is executed.
  void init(){};
  // will be called after every testfunction.
  void cleanup();

その後にテストメソッドが来ます。それらはすべてパラメーターを取らずvoidを返す必要があります。メソッドは宣言した順序で呼び出されます。私はここで2つのメソッドを実装していますが、これらはテストの2種類を示しています。私は一般的に、クラスのさまざまな部分をテストする最初のケースで働いている、私は機能テスト手法を使用できます。ここでも、エクストリームプログラマであれば、クラスを実装する前にこれらのテストを書くことを提唱するでしょう。クラスの実装を通して、作業するにつれ、繰り返しユニットテストを実行します。クラスの実装作業が進行し、全体のユニットテストを通過したときに、新しいクラスが行われ、今それを検証する反復可能な方法で完了するように、より多くのテスト機能はsucessfully完了する必要があります。

一般的には、ユニットテストは、クラスの公開APIをカバーするだけで、通常はアクセサとミューテーターのテストを記述する必要はありません。acccessorやミューテータが期待通りに動作しないようなことが起こる場合、通常はこれをチェックするための回帰テストを実装したでしょう(下の下参照)。

//
// Functional Testing
//

/** Check if a raster is valid. */
void isValid();

// more functional tests here ...

次に私たちは回帰テストを実装します。回帰テストは、特定のバグの状況を再現するために実施されるべきです。たとえば私が最近電子メールで報告を受けたのは、ラスターバンドのすべての統計情報をオフに投げて、ラスターによるセル数が1でオフにしたというものです。私は、バグ(チケット#832)を開設し、その後、小さなテストデータセット(10×10ラスター)を使用してバグを複製し、回帰テストを作成しました。そして、私はそれが実際に失敗したことを確認し、テストを実行し、それを実行した(セル数が99ではなく100でした)。それから私は、バグを修正するために行って、ユニットテストを再実行し回帰テストが合格しました。私は、バグ修正と一緒に回帰テストをコミットしました。今、誰もが将来再びソースコードでこれをbreakes場合、私たちはすぐにコードが回帰したことを確認できます。できれば将来の変更をコミットする前に私たちのテストを実行すると、私たちの変更が予期しない副作用(既存の機能を壊すなど)を持っていないことを確認できるでしょう。

回帰テストへの1つの以上の利点があります - それらは時間を節約できます。ソースに変更を加えてからアプリケーションを実行して問題を再現するために複雑な一連のステップを実行することに関わるバグを修正したことがあれば、バグを修正する前に回帰テストを実装するだけで、効率的な方法でバグの解決のためのテストを自動化できることがすぐに明らかになるでしょう。

回帰テストを実装するには、テスト関数に対する回帰の命名規則<TicketID> に従ってください。その回帰についてのRedmineのチケットが存在しない場合は、最初にそれを作成する必要があります。このアプローチを使用すると、失敗した回帰テストを実行している人が簡単に行きより多くの情報を見つけることができます。

//
// Regression Testing
//

/** This is our second test case...to check if a raster
 *  reports its dimensions properly. It is a regression test
 *  for ticket #832 which was fixed with change r7650.
 */
void regression832();

// more regression tests go here ...

最後に、私たちのテストクラスの宣言中でユニットテストで必要になるかもしれないデータメンバーとヘルパーメソッドはすべてプライベートで宣言できます。私たちの場合、私は、テストのいずれかの方法で使用できる QgsRasterLayer * を宣言します。ラスターレイヤーは、他のテストの前に実行し、すべてのテストの後に実行され cleanupTestCase() を使用して破壊され initTestCase() 関数で作成されます。ヘルパーメソッド(各種テスト関数によって呼び出されることもある)をプライベートで宣言することにより、それらが私たちのテストをコンパイルするときに作成された QTest 実行ファイルが自動的に実行しないだろうことを確実にできます。

  private:
    // Here we have any data structures that may need to
    // be used in many test cases.
    QgsRasterLayer * mpLayer;
};

これで私たちのクラス宣言を終了します。実装は単に同じファイル中で下方にインライン化されます。まず、私たちのinitおよびcleanup関数:

void TestQgsRasterLayer::initTestCase()
{
  // init QGIS's paths - true means that all path will be inited from prefix
  QString qgisPath = QCoreApplication::applicationDirPath ();
  QgsApplication::setPrefixPath(qgisPath, TRUE);
#ifdef Q_OS_LINUX
  QgsApplication::setPkgDataPath(qgisPath + "/../share/qgis");
#endif
  //create some objects that will be used in all tests...

  std::cout << "PrefixPATH: " << QgsApplication::prefixPath().toLocal8Bit().data() << std::endl;
  std::cout << "PluginPATH: " << QgsApplication::pluginPath().toLocal8Bit().data() << std::endl;
  std::cout << "PkgData PATH: " << QgsApplication::pkgDataPath().toLocal8Bit().data() << std::endl;
  std::cout << "User DB PATH: " << QgsApplication::qgisUserDbFilePath().toLocal8Bit().data() << std::endl;

  //create a raster layer that will be used in all tests...
  QString myFileName (TEST_DATA_DIR); //defined in CmakeLists.txt
  myFileName = myFileName + QDir::separator() + "tenbytenraster.asc";
  QFileInfo myRasterFileInfo ( myFileName );
  mpLayer = new QgsRasterLayer ( myRasterFileInfo.filePath(),
  myRasterFileInfo.completeBaseName() );
}

void TestQgsRasterLayer::cleanupTestCase()
{
  delete mpLayer;
}

上記のinit関数はいくつかの興味深い物事を示しています。

  1. 私はsrs.dbなどのリソースを適切に見つけることができるように、手動でQGIS・アプリケーション・データ・パスを設定する必要がありました。

  2. 第二に、これは私たちが一般的に tenbytenraster.asc ファイルを見つけるための方法を提供するために必要なので、データ駆動型テストがあります。これは定義 TEST_DATA_PATH コンパイラを使用することによって達成されました。 CMakeLists.txt 構成ファイルで作成された定義 <QGIS Source Root>/tests/ CMakeLists.txt 下、すべてのQGISユニットテストに使用可能です。テストのためのテストデータが必要な場合は、 <QGIS Source Root>/tests/ testdata の下でそれをコミット。ここでしか、非常に小さなデータセットをコミットする必要があります。テストは、テスト・データを変更する必要がある場合、それは最初にそれのコピーを作成する必要があります。

Qtではまた、テストをデータ駆動するためのいくつかの他の興味深いメカニズムを提供していますので、この話題に関してもっと知りたいと興味をお持ちの方は、Qtのドキュメントを参照してください。

次の私たちの機能テストを見てみましょう。isValid()テストは、単にラスターレイヤーが正しくinitTestCaseにロードされたかをチェックします。QVERIFYは、テスト条件を評価するために使用できるQtのマクロです。Qtでテスト中で使用するために提供されている使用マクロが他にいくつかあります:

  • QCOMPARE ( actual, expected )
  • QEXPECT_FAIL ( dataIndex, comment, mode )
  • QFAIL ( message )
  • QFETCH ( type, name )
  • QSKIP ( description, mode )
  • QTEST ( actual, testElement )
  • QTEST_APPLESS_MAIN ( TestClass )
  • QTEST_MAIN ( TestClass )
  • QTEST_NOOP_MAIN ()
  • QVERIFY2 ( condition, message )
  • QVERIFY ( condition )
  • QWARN ( message )

これらのマクロの一部は(詳細はQtのドキュメントを参照してください)、テスト駆動型のデータのためのQtフレームワークを使用している場合にのみ便利です。

void TestQgsRasterLayer::isValid()
{
  QVERIFY ( mpLayer->isValid() );
}

通常、あなたの機能テストが可能な場合、あなたのクラスのパブリックAPIのすべての機能範囲をカバーするでしょう。私たちの機能テストは out the way、回帰テストの例を見ることができます。

バグ#832での問題はセル数の誤った報告なので、私たちのテストを書くことは、単純にセル数が期待値を満たしていることをQVERIFYを使用して確認する問題です。

void TestQgsRasterLayer::regression832()
{
  QVERIFY ( mpLayer->getRasterXDim() == 10 );
  QVERIFY ( mpLayer->getRasterYDim() == 10 );
  // regression check for ticket #832
  // note getRasterBandStats call is base 1
  QVERIFY ( mpLayer->getRasterBandStats(1).elementCountInt == 100 );
}

すべてのユニットテスト機能が実装されたら、テストクラスに追加する必要があり、そこに1つの最終の事:

QTEST_MAIN(TestQgsRasterLayer)
#include "testqgsrasterlayer.moc"

これらの2つの行の目的は、それがQtTestであることをQtのMOCに知らせることです(主なメソッドを生成して、各テスト関数を呼び出します)。最後の行は、MOC生成ソースのインクルードです。 ‘testqgsrasterlayer’は小文字のクラス名に置き換えてください。

CMakeLists.txtにユニットテストを追加する

ビルドシステムにユニットテストを追加することは、テストディレクトリにCMakeLists.txtを編集する既存のテストブロックの1つのクローンを作成し、それにあなたのテストクラス名を置き換えるだけの問題です。例えば:

# QgsRasterLayer test
ADD_QGIS_TEST(rasterlayertest testqgsrasterlayer.cpp)

説明されたADD_QGIS_TESTマクロ

私はこれらの行をそれらが何をするかを説明するため簡単に通して見ていきますが、興味をお持ちでない場合は、上記のセクションとセクションで説明されるステップだけ実行してください。

MACRO (ADD_QGIS_TEST testname testsrc)
SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})
SET(qgis_${testname}_MOC_CPPS ${testsrc})
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})
ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)
TARGET_LINK_LIBRARIES(qgis_${testname} ${QT_LIBRARIES} qgis_core)
SET_TARGET_PROPERTIES(qgis_${testname}
PROPERTIES
# skip the full RPATH for the build tree
SKIP_BUILD_RPATHTRUE
# when building, use the install RPATH already
# (so it doesn't need to relink when installing)
BUILD_WITH_INSTALL_RPATH TRUE
# the RPATH to be used when installing
INSTALL_RPATH ${QGIS_LIB_DIR}
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
INSTALL_RPATH_USE_LINK_PATH true)
IF (APPLE)
# For Mac OS X, the executable must be at the root of the bundle's executable folder
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/qgis_${testname})
ELSE (APPLE)
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/bin/qgis_${testname})
ENDIF (APPLE)
ENDMACRO (ADD_QGIS_TEST)

個々の行で詳細にもう少し見てみましょう。まず、我々のテストのためのソースのリストを定義します。:私たちは、その簡単な文で(上で説明した方法論に従って、私はクラスの宣言と定義が同じファイルのどこにいるか)ソースファイルを1つだけ持っているので、

SET(qgis_${testname}_SRCS ${testsrc} ${util_SRCS})

我々のテストクラスは、Qtのメタオブジェクトコンパイラ(MOC)を介して実行する必要がありますので、それが実現するために何行かも提供する必要があります:

SET(qgis_${testname}_MOC_CPPS ${testsrc})
QT4_WRAP_CPP(qgis_${testname}_MOC_SRCS ${qgis_${testname}_MOC_CPPS})
ADD_CUSTOM_TARGET(qgis_${testname}moc ALL DEPENDS ${qgis_${testname}_MOC_SRCS})

次にそれがテストクラスから実行ファイルを作る必要があることをcmakeに伝えます。前のセクションでクラス実装の最後の行で私たちのテストクラス中にmoc出力を直接インクルードしたことを思い出してください。それは(とりわけ)mainメソッドをを与えるのでこのクラスは実行可能ファイルとしてコンパイルできます:

ADD_EXECUTABLE(qgis_${testname} ${qgis_${testname}_SRCS})
ADD_DEPENDENCIES(qgis_${testname} qgis_${testname}moc)

次はどんなライブラリの依存関係を指定する必要があります。現時点では、クラスががらくた入れQT_LIBRARIES依存で実装されているが、私は、各クラスにのみ必要がある特定のQtライブラリでそれを置き換えるために働くことになります。もちろん、あなたも、あなたのユニットテストで必要とされる関連QGISライブラリにリンクする必要があります。

TARGET_LINK_LIBRARIES(qgis_${testname} ${QT_LIBRARIES} qgis_core)

次に、QGISのバイナリ自体と同じ場所にテストをインストールするようcmakeに教えます。これは私がテストがソースツリー内から直接実行できるように、将来的に削除する予定のものです。

SET_TARGET_PROPERTIES(qgis_${testname}
PROPERTIES
# skip the full RPATH for the build tree
SKIP_BUILD_RPATHTRUE
# when building, use the install RPATH already
# (so it doesn't need to relink when installing)
BUILD_WITH_INSTALL_RPATH TRUE
# the RPATH to be used when installing
INSTALL_RPATH ${QGIS_LIB_DIR}
# add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
INSTALL_RPATH_USE_LINK_PATH true)
IF (APPLE)
# For Mac OS X, the executable must be at the root of the bundle's executable folder
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/qgis_${testname})
ELSE (APPLE)
INSTALL(TARGETS qgis_${testname} RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
ADD_TEST(qgis_${testname} ${CMAKE_INSTALL_PREFIX}/bin/qgis_${testname})
ENDIF (APPLE)

最後に、上記の使用 ADD_TEST はcmake / ctest.を用いたテストを登録します。最高の魔法が起こるのはここです - 私たちはctestを持つクラスを登録します。私は、このセクションの初めに与えた概要でリコールした場合、私たちは一緒にQtTestとCTestの両方を使用しています。要約すると、QtTestは、テストユニットにmainメソッドを追加し、クラス内のテストメソッドを呼び出して処理します。それはまた、条件を使用して、テストの失敗をテストするためにとして使用できます QVERIFY のようないくつかのマクロを提供します。QtTestユニットテストからの出力は、コマンドラインから実行できる実行可能です。テストスイートを持っていて、順番に各実行可能ファイルを実行し、いっそのビルドプロセスにテストを実行して統合したいときしかし、CTESTは、私たちが使用しているものです。

ユニットテストをビルドする

ユニットテストをビルドするには、cmakeの設定で ENABLE_TESTS=true を確認するだけが必要です。これを行うには2つの方法があります:

  1. ccmake.. (またはウィンドウズの下では cmakesetup.. )を実行し、対話的に ENABLE_TESTS フラグを ON に設定します。

  2. cmakeのためのコマンドラインフラグを追加します、例えば cmake -DENABLE_TESTS=true ..

それ以外は、通常通りQGISをビルドするだけであり、またテストもビルドする必要があります。

テストを実行

テストを実行する最も簡単な方法は、通常のビルドプロセスの一部としてです:

make && make install && make test

make test コマンドは、上述ADD_TEST CMakeのディレクティブを使用して登録された各テストを実行するCTESTを呼び出します。make test からの典型的な出力は次のようになります。

Running tests...
Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
## 13 Testing qgis_applicationtest***Exception: Other
## 23 Testing qgis_filewritertest *** Passed
## 33 Testing qgis_rasterlayertest*** Passed

## 0 tests passed, 3 tests failed out of 3

The following tests FAILED:
## 1- qgis_applicationtest (OTHER_FAULT)
Errors while running CTest
make: *** [test] Error 8

テストが失敗した場合は、それが失敗した理由をより密接に検討するctestコマンドを使用できます。実行したいテストするために正規表現を指定するためには -R オプションを、冗長な出力を得るためには -V オプションを使用してください:

$ ctest -R appl -V

Start processing tests
Test project /Users/tim/dev/cpp/qgis/build
Constructing a list of tests
Done constructing a list of tests
Changing directory into /Users/tim/dev/cpp/qgis/build/tests/src/core
## 13 Testing qgis_applicationtest
Test command: /Users/tim/dev/cpp/qgis/build/tests/src/core/qgis_applicationtest
********* Start testing of TestQgsApplication *********
Config: Using QTest library 4.3.0, Qt 4.3.0
PASS : TestQgsApplication::initTestCase()
PrefixPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
PluginPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
User DB PATH: /Users/tim/.qgis/qgis.db
PASS : TestQgsApplication::getPaths()
PrefixPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/../
PluginPATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//lib/qgis
PkgData PATH: /Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis
User DB PATH: /Users/tim/.qgis/qgis.db
QDEBUG : TestQgsApplication::checkTheme() Checking if a theme icon exists:
QDEBUG : TestQgsApplication::checkTheme()
/Users/tim/dev/cpp/qgis/build/tests/src/core/..//share/qgis/themes/default//mIconProjectionDisabled.png
FAIL!: TestQgsApplication::checkTheme() '!myPixmap.isNull()' returned FALSE. ()
Loc: [/Users/tim/dev/cpp/qgis/tests/src/core/testqgsapplication.cpp(59)]
PASS : TestQgsApplication::cleanupTestCase()
Totals: 3 passed, 1 failed, 0 skipped
********* Finished testing of TestQgsApplication *********
-- Process completed
***Failed

## 0 tests passed, 1 tests failed out of 1

The following tests FAILED:
## 1- qgis_applicationtest (Failed)
Errors while running CTest

Well that concludes this section on writing unit tests in QGIS. We hope you will get into the habit of writing test to test new functionality and to check for regressions. Some aspects of the test system (in particular the CMakeLists.txt parts) are still being worked on so that the testing framework works in a truly platform way. I will update this document as things progress.