Commit b5c4c692 authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Unit tests for CourseResource

parent 4e5b50fb
......@@ -56,15 +56,19 @@ target_link_libraries(test_trainingsession
add_test(test_trainingsession test_trainingsession)
ecm_mark_as_test(test_trainingsession)
set(TestCourseFiles_SRCS testcoursefiles.cpp)
kconfig_add_kcfg_files(TestCourseFiles_SRCS ../src/settings.kcfgc)
add_executable(TestCourseFiles ${TestCourseFiles_SRCS} )
target_link_libraries(TestCourseFiles
# test course resource class
set(TestCourseResource_SRCS
courseresource/test_courseresource.cpp
courseresource/resourcerepositorystub.cpp
)
qt5_add_resources(TestCourseResource_SRCS ../data/languages.qrc)
add_executable(test_courseresource ${TestCourseResource_SRCS} )
target_link_libraries(test_courseresource
artikulatecore
Qt5::Test
)
add_test(TestCourseFiles TestCourseFiles)
ecm_mark_as_test(TestCourseFiles)
add_test(test_courseresource test_courseresource)
ecm_mark_as_test(test_courseresource)
# basic tests language files (input/output)
set(TestLanguageFiles_SRCS testlanguagefiles.cpp)
......
/*
* Copyright 2019 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "test_course.h"
#include "src/core/icourse.h"
#include "src/core/course.h"
#include "src/core/resources/courseresource.h"
#include "src/core/language.h"
#include "src/core/unit.h"
#include <QTest>
#include <QSignalSpy>
/*
class CourseStub : public ICourse
{
public:
CourseStub(Language *language, QVector<Unit *> units)
: m_language(language)
, m_units(units)
{
}
QString id() const override
{
return "courseid";
}
QString title() const override
{
return "title";
}
QString i18nTitle() const override
{
return "i18n title";
}
QString description() const override
{
return "description of the course";
}
Language * language() const override
{
return m_language;
}
QList<Unit *> unitList() const override
{
return m_units.toList();
}
QUrl file() const override
{
return QUrl();
}
private:
Language *m_language{nullptr};
QVector<Unit *> m_units;
};*/
void TestCourse::init()
{
// TODO initialization of test case
}
void TestCourse::cleanup()
{
// TODO cleanup after test run
}
void TestCourse::createCourseWithoutUnits()
{
// CourseResource resource(nullptr);
Course course();
//TODO
// virtual ~ICourse() = default;
// virtual QString id() const = 0;
// virtual QString title() const = 0;
// virtual QString i18nTitle() const = 0;
// virtual QString description() const = 0;
// virtual Language * language() const = 0;
// virtual QList<Unit *> unitList() const = 0;
// virtual QUrl file() const = 0;
// Language language;
// CourseStub course(&language, QVector<Unit *>());
// LearnerProfile::ProfileManager manager;
// TrainingSession session(&manager);
// session.setCourse(&course);
// QVERIFY(&course == session.course());
}
void TestCourse::createCourseWithoutPhrases()
{
// Language language;
// Unit unitA;
// Unit unitB;
// Phrase phraseA1;
// Phrase phraseA2;
// Phrase phraseB1;
// Phrase phraseB2;
// // note: phrases without soundfiles are skipped in session generation
// phraseA1.setId("A1");
// phraseA2.setId("A2");
// phraseB1.setId("B1");
// phraseB2.setId("B2");
// phraseA1.setSound(QUrl::fromLocalFile("/tmp/a1.ogg"));
// unitA.addPhrase(&phraseA1);
// unitA.addPhrase(&phraseA2);
// unitB.addPhrase(&phraseB1);
// unitB.addPhrase(&phraseB2);
// CourseStub course(&language, QVector<Unit *>({&unitA, &unitB}));
// LearnerProfile::ProfileManager manager;
// TrainingSession session(&manager);
// session.setCourse(&course);
// // test number of actions
// auto actions = session.trainingActions();
// QCOMPARE(actions.count(), 1);
// QCOMPARE(actions.at(0)->actions().count(), 1);
}
QTEST_GUILESS_MAIN(TestCourse)
/*
* Copyright 2019 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2019 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -18,38 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TEST_COURSE_H
#define TEST_COURSE_H
#include "resourcerepositorystub.h"
#include <QObject>
class TestCourse : public QObject
{
Q_OBJECT
public:
TestCourse() = default;
private Q_SLOTS:
/**
* Called before every test case.
*/
void init();
/**
* Called after every test case.
*/
void cleanup();
/**
* @brief Construct and destruct course without units
*/
void createCourseWithoutUnits();
/**
* @brief Construct training session and check that phrases without sound file paths are skipped
*/
void createCourseWithoutPhrases();
};
#endif
// define one virtual method out of line to pin CourseStub to this translation unit
ResourceRepositoryStub::~ResourceRepositoryStub() = default;
/*
* Copyright 2019 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOURCEREPOSITORYSTUB_H
#define RESOURCEREPOSITORYSTUB_H
#include "core/iresourcerepository.h"
#include <QObject>
#include <QVector>
class Language;
class ICourse;
/**
* @brief The ResourceRepositoryStub that only provides languages and a storage location, but nothing else
*/
class ResourceRepositoryStub : public IResourceRepository
{
Q_OBJECT
public:
ResourceRepositoryStub(QVector<Language *> languages)
{
m_languages = languages;
}
~ResourceRepositoryStub() override;
QString storageLocation() const override
{
return m_storageLocation;
}
QVector<ICourse *> courses() const override
{
return QVector<ICourse *>(); // do not return any courses: stub shall only provide languages
}
QVector<ICourse *> courses(Language *language) const override
{
Q_UNUSED(language);
return QVector<ICourse *>(); // do not return any courses: stub shall only provide languages
}
void reloadCourses() override
{
; // do nothing, stub shall only provide languages
}
QVector<Language *> languages() const override
{
return m_languages;
}
Q_SIGNALS:
void courseAboutToBeAdded(ICourse*,int) override;
void courseAdded() override;
void courseAboutToBeRemoved(int) override;
void courseRemoved() override;
private:
QString m_storageLocation;
QVector<Language *> m_languages;
};
#endif
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "test_courseresource.h"
#include "resourcerepositorystub.h"
#include "core/course.h"
#include "core/language.h"
#include "core/unit.h"
#include "core/phrase.h"
#include "core/resources/languageresource.h"
#include "core/resources/courseresource.h"
#include <QTest>
#include <QDebug>
#include <QTemporaryFile>
#include <QIODevice>
#include <QFile>
#include <QXmlSchema>
#include <QXmlSchemaValidator>
#include <QDomDocument>
TestCourseResource::TestCourseResource()
{
}
void TestCourseResource::init()
{
}
void TestCourseResource::cleanup()
{
}
void TestCourseResource::courseSchemeValidationTest()
{
QUrl schemeFile = QUrl::fromLocalFile(QStringLiteral("schemes/course.xsd"));
QXmlSchema courseSchema;
QVERIFY(courseSchema.load(schemeFile));
QVERIFY(courseSchema.isValid());
//TODO shall be used in skeleton specific test
QUrl skeletonFile = QUrl::fromLocalFile(QStringLiteral("schemes/skeleton.xsd"));
QXmlSchema skeletonScheme;
QVERIFY(skeletonScheme.load(skeletonFile));
QVERIFY(skeletonScheme.isValid());
}
void TestCourseResource::loadCourseResource()
{
Language language;
language.setId("de");
ResourceRepositoryStub repository({&language});
const QString courseDirectory = "data/courses/de/";
const QString courseFile = courseDirectory + "de.xml";
CourseResource course(QUrl::fromLocalFile(courseFile), &repository);
QCOMPARE(course.file().toLocalFile(), courseFile);
QCOMPARE(course.id(), "de");
QCOMPARE(course.title(), "Artikulate Deutsch");
QCOMPARE(course.description(), "Ein Kurs in (hoch-)deutscher Aussprache.");
QVERIFY(course.language() != nullptr);
QCOMPARE(course.language()->id(), "de");
QCOMPARE(course.unitList().count(), 1);
const auto unit = course.unitList().first();
QVERIFY(unit != nullptr);
QCOMPARE(unit->id(), "1");
QCOMPARE(unit->title(), QStringLiteral("Auf der Straße"));
QCOMPARE(unit->foreignId(), "{dd60f04a-eb37-44b7-9787-67aaf7d3578d}");
QCOMPARE(unit->phraseList().count(), 3);
// note: this test takes the silent assumption that phrases are added to the list in same
// order as they are defined in the file. This assumption should be made explicit or dropped
const auto firstPhrase = unit->phraseList().first();
QVERIFY(firstPhrase != nullptr);
QCOMPARE(firstPhrase->id(), "1");
QCOMPARE(firstPhrase->foreignId(), "{3a4c1926-60d7-44c6-80d1-03165a641c75}");
QCOMPARE(firstPhrase->text(), "Guten Tag.");
QCOMPARE(firstPhrase->soundFileUrl(), courseDirectory + "de_01.ogg");
QCOMPARE(firstPhrase->type(), Phrase::Type::Sentence);
QVERIFY(firstPhrase->phonemes().isEmpty());
}
//TODO test signals
// FIXME porting break
void TestCourseResource::fileLoadSaveCompleteness()
{
// ResourceManager manager;
// manager.addLanguage(QUrl::fromLocalFile(QStringLiteral("data/languages/de.xml")));
// manager.addCourse(QUrl::fromLocalFile(QStringLiteral("data/courses/de.xml")));
// // test to encure further logic
// QVERIFY(manager.courseResources(manager.languageResources().constFirst()->language()).count() == 1);
// Course *testCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constFirst()->course();
// QTemporaryFile outputFile;
// outputFile.open();
// QUrl oldFileName = testCourse->file();
// testCourse->setFile(QUrl::fromLocalFile(outputFile.fileName()));
// testCourse->setLanguage(manager.languageResources().constFirst()->language());
// testCourse->sync();
// testCourse->setFile(oldFileName); // restore for later tests
// QFile file(outputFile.fileName());
// if (!file.open(QIODevice::ReadOnly)) {
// qCritical() << "Could not open file to read.";
// }
// //TODO this only works, since the resource manager not checks uniqueness of course ids!
// manager.addCourse(QUrl::fromLocalFile(outputFile.fileName()));
// Course *compareCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constLast()->course();
// // test that we actually call the different files
// QVERIFY(testCourse->file().toLocalFile() != compareCourse->file().toLocalFile());
// QVERIFY(testCourse->id() == compareCourse->id());
// QVERIFY(testCourse->foreignId() == compareCourse->foreignId());
// QVERIFY(testCourse->title() == compareCourse->title());
// QVERIFY(testCourse->description() == compareCourse->description());
// QVERIFY(testCourse->language()->id() == compareCourse->language()->id());
// QVERIFY(testCourse->unitList().count() == compareCourse->unitList().count());
// Unit *testUnit = testCourse->unitList().constFirst();
// Unit *compareUnit = compareCourse->unitList().constFirst();
// QVERIFY(testUnit->id() == compareUnit->id());
// QVERIFY(testUnit->foreignId() == compareUnit->foreignId());
// QVERIFY(testUnit->title() == compareUnit->title());
// QVERIFY(testUnit->phraseList().count() == compareUnit->phraseList().count());
// Phrase *testPhrase = testUnit->phraseList().constFirst();
// Phrase *comparePhrase = new Phrase(this);
// // Note that this actually means that we DO NOT respect phrase orders by list order!
// foreach (Phrase *phrase, compareUnit->phraseList()) {
// if (testPhrase->id() == phrase->id()) {
// comparePhrase = phrase;
// break;
// }
// }
// QVERIFY(testPhrase->id() == comparePhrase->id());
// QVERIFY(testPhrase->foreignId() == comparePhrase->foreignId());
// QVERIFY(testPhrase->text() == comparePhrase->text());
// QVERIFY(testPhrase->type() == comparePhrase->type());
// QVERIFY(testPhrase->sound().fileName() == comparePhrase->sound().fileName());
// QVERIFY(testPhrase->phonemes().count() == comparePhrase->phonemes().count());
// //FIXME implement phoneme checks after phonemes are fully implemented
}
QTEST_GUILESS_MAIN(TestCourseResource)
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
* Copyright 2013-2019 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -18,18 +18,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TESTCOURSEFILES_H
#define TESTCOURSEFILES_H
#ifndef TESTCOURSERESOURCE_H
#define TESTCOURSERESOURCE_H
#include <QObject>
#include <QVariant>
class TestCourseFiles : public QObject
class TestCourseResource : public QObject
{
Q_OBJECT
public:
TestCourseFiles();
TestCourseResource();
private slots:
/**
......@@ -47,6 +47,8 @@ private slots:
*/
void courseSchemeValidationTest();
void loadCourseResource();
/**
* Test if serialization of unserialized file gives original file.
* TODO this is a test by only string equality and should improved to test on a data level
......
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@gmail.com>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "testcoursefiles.h"
#include "core/resourcemanager.h"
#include "core/course.h"
#include "core/language.h"
#include "core/unit.h"
#include "core/phrase.h"
#include "core/resources/languageresource.h"
#include "core/resources/courseresource.h"
#include "../src/settings.h"
#include <QTest>
#include <QDebug>
#include <QTemporaryFile>
#include <QIODevice>
#include <QFile>
#include <QXmlSchema>
#include <QXmlSchemaValidator>
#include <QDomDocument>
TestCourseFiles::TestCourseFiles()
: m_systemUseCourseRepositoryValue(Settings::useCourseRepository())
{
}
void TestCourseFiles::init()
{
//FIXME has to be ported
// KGlobal::dirs()->addResourceDir("appdata" , "./testcourses/");
// KGlobal::dirs()->addResourceDir("appdata" , "./");
// KGlobal::dirs()->addResourceDir("appdata" , "./autotests/");
// KGlobal::dirs()->addResourceDir("appdata" , "./autotests/testcourses/");
Settings::setUseCourseRepository(false);
Settings::self()->save();
}
void TestCourseFiles::cleanup()
{
// reset value
Settings::setUseCourseRepository(m_systemUseCourseRepositoryValue);
Settings::self()->save();
}
void TestCourseFiles::courseSchemeValidationTest()
{
QUrl schemeFile = QUrl::fromLocalFile(QStringLiteral("schemes/course.xsd"));
QXmlSchema courseSchema;
QVERIFY(courseSchema.load(schemeFile));
QVERIFY(courseSchema.isValid());
QUrl skeletonFile = QUrl::fromLocalFile(QStringLiteral("schemes/skeleton.xsd"));
QXmlSchema skeletonScheme;
QVERIFY(skeletonScheme.load(skeletonFile));
QVERIFY(skeletonScheme.isValid());
}
void TestCourseFiles::fileLoadSaveCompleteness()
{
ResourceManager manager;
manager.addLanguage(QUrl::fromLocalFile(QStringLiteral("data/languages/de.xml")));
manager.addCourse(QUrl::fromLocalFile(QStringLiteral("data/courses/de.xml")));
// test to encure further logic
QVERIFY(manager.courseResources(manager.languageResources().constFirst()->language()).count() == 1);
Course *testCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constFirst()->course();
QTemporaryFile outputFile;
outputFile.open();
QUrl oldFileName = testCourse->file();
testCourse->setFile(QUrl::fromLocalFile(outputFile.fileName()));
testCourse->setLanguage(manager.languageResources().constFirst()->language());
testCourse->sync();
testCourse->setFile(oldFileName); // restore for later tests
QFile file(outputFile.fileName());
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Could not open file to read.";
}
//TODO this only works, since the resource manager not checks uniqueness of course ids!
manager.addCourse(QUrl::fromLocalFile(outputFile.fileName()));
Course *compareCourse = manager.courseResources(manager.languageResources().constFirst()->language()).constLast()->course();
// test that we actually call the different files
QVERIFY(testCourse->file().toLocalFile() != compareCourse->file().toLocalFile());
QVERIFY(testCourse->id() == compareCourse->id());
QVERIFY(testCourse->foreignId() == compareCourse->foreignId());
QVERIFY(testCourse->title() == compareCourse->title());
QVERIFY(testCourse->description() == compareCourse->description());
QVERIFY(testCourse->language()->id() == compareCourse->language()->id());
QVERIFY(testCourse->unitList().count() == compareCourse->unitList().count());
Unit *testUnit = testCourse->unitList().constFirst();
Unit *compareUnit = compareCourse->unitList().constFirst();
QVERIFY(testUnit->id() == compareUnit->id());
QVERIFY(testUnit->foreignId() == compareUnit->foreignId());
QVERIFY(testUnit->title() == compareUnit->title());
QVERIFY(testUnit->phraseList().count() == compareUnit->phraseList().count());