KDevelop5/Manual/Code generation with templates/da: Difference between revisions

From KDE Wiki Sandbox
No edit summary
No edit summary
 
(23 intermediate revisions by 2 users not shown)
Line 8: Line 8:
=== Opret en ny klasse ===
=== Opret en ny klasse ===


Den mest almindelige anvendelse af kodegenerering er formentlig at skrive en ny klasse. For at oprettet en ny klasse i et eksisterende projekt skal du højreklikke på projektmappen og vælge <menuchoice>Opret fra skabelon</menuchoice>. Den samme dialog kan startes fra menuen ved at vælge <menuchoice>Fil -> Ny fra skabelon</menuchoice>, men at bruge en projektmappe har den fordel, at basis-URL'en bliver sat for outputfilen. Vælg <tt>Klasse</tt> i afsnittet kategori og det sprog og den skabelon der ønskes i de andre to felter. Efter at du har valgt en klasseskabelon skal du angive detaljer om den nye klasse.  
Den mest almindelige anvendelse af kodegenerering er formentlig at skrive en ny klasse. For at oprettet en ny klasse i et eksisterende projekt skal du højreklikke på projektmappen og vælge <menuchoice>Opret fra skabelon...</menuchoice>. Den samme dialog kan startes fra menuen ved at vælge <menuchoice>Fil -> Ny fra skabelon...</menuchoice>, men fordelen ved at bruge en projektmappe er, at basis-URL'en bliver sat for outputfilen. Vælg <tt>C++</tt> i afsnittet "Sprog", og det framework og den skabelon der ønskes i de andre to felter. Nederst i dialoges ser du en forhåndsvisning af de filer, der vil blive genereret, og hvor du kan browse igennem disse filer. Efter at du har foretaget dine valg skal du angive detaljer om den nye klasse i dialogen "Basalt for klasse" efter at du har klikket på <menuchoice>> Næste</menuchoice>..  


[[Image:kdevelop-template-selection.png|thumb|500px|center]]
[[File:Kdevelop-new-from-template.png|500px|thumb|center]]


Først skal du angive en identifikator for klassen. Dette kan være en simpelt navn (som <code>Bus</code>) eller en komplet identifikator men navnerum (som <code>Transportation::Bus</code>). I det sidste tilfælde vil '''KDevelop''' fortolke identifikatoren og separere navnerummet fra det egentlige navn. I det samme vindue kan du tilføje den nye klasses basisklasser. Du bemærker måske, at nogle skabeloner selv vælger en basisklasse, men du kan frit fjerne den og du kan tilføje andre basisklasser. Du bør skrive hele nedarvningserklæringen her, hvilket afhænger af sproget, fx  <code>public QObject</code> for C++, <code>extends SomeClass</code> for PHP og blot klassens navn for Python.  
Først skal du angive en identifikator for klassen. Dette kan være en simpelt navn (som <code>Bus</code>) eller en komplet identifikator men navnerum (som <code>Transportation::Bus</code>). I det sidste tilfælde vil '''KDevelop''' fortolke identifikatoren og separere navnerummet fra det egentlige navn. I det samme vindue kan du tilføje den nye klasses basisklasser. Du bemærker måske, at nogle skabeloner selv vælger en basisklasse, men du kan frit fjerne den og du kan tilføje andre basisklasser. Du bør skrive hele nedarvningserklæringen her, hvilket afhænger af sproget, fx  <code>public QObject</code> for C++, <code>extends SomeClass</code> for PHP og blot klassens navn for Python.  


[[Image:kdevelop-template-inheritance.png|thumb|500px|center]]
[[File:Kdevelop-class-basics1.png|500px|thumb|center]]


I det næste vindue kan du vælge bland de virtuelle metoder fra alle nedarvede klasser samt nogle standard konstruktorer, destruktorer og operatorer. Markér afkrydsningsfeltet vedsiden af en metodesignatur for at implementere denne metode i den nye klasse.  
I det næste vindue kan du vælge bland de virtuelle metoder fra alle nedarvede klasser samt nogle standard konstruktorer, destruktorer og operatorer. Markér afkrydsningsfeltet ved siden af en metodesignatur for at implementere denne metode i den nye klasse.


Når du klikker på <menuchoice>Næste</menuchoice> kommer du til et vindue, hvor du kan tilføje medlemmer til klassen. Afhængigt af den valgte skabelon vil de optræde som medlemsvariable i den nye klasse eller skabelonen vil oprette settere og gettere for dem. I sprog som C++, hvor variable skal erklæres skal du angive både type og navn for medlemmet som fx <code>int number</code> eller <code>QString name</code>. I andre sprog behøver du ikke at angive typen, men det er god praksis at have den med alligevel, for den valgte skabelon kan stadig drage nytte af det.  
Når du klikker på <menuchoice>> Næste</menuchoice> kommer du til dialogen "Medlemmer af klasse", hvor du kan tilføje medlemmer til klassen. Afhængigt af den valgte skabelon vil de optræde som medlemsvariable i den nye klasse eller skabelonen vil oprette egenskaber med settere og gettere for dem. I sprog som C++, hvor variable skal erklæres skal du angive både type og navn for medlemmet som fx <code>int number</code> eller <code>QString name</code>. I andre sprog behøver du ikke at angive typen, men det er god praksis at have den med alligevel, for den valgte skabelon kan stadig drage nytte af det.Du har også mulighed for at ændre rækkefølgen af klassens medlemmer ved at vælge et medlem og så klikke på enten <menuchoice>Flyt op</menuchoice> eller <menuchoice>Flyt ned</menuchoice>. Når filen genereres, så bruges den rækkefølge, som du har valgt.


[[Image:kdevelop-template-members.png|thumb|500px|center]]
[[File:Kdevelop-class-members-template.png|500px|thumb|center]]


I de følgende vinduer kan du vælge licensen for din nye klasse, angive særlige oplysninger, som den valgte skabelon skal bruge og angive, hvor de genererede filer skal placeres. Du afslutter guiden ved at klikke <menuchoice>Afslut</menuchoice>, hvorefter den nye klasse genereres. De genererede filer vil blive åbnet i editoren, sådan at du kan begynde at arbejde med dem med det samme.  
I de følgende vinduer kan du vælge licensen for din nye klasse, angive særlige oplysninger, som den valgte skabelon skal bruge og angive, hvor de genererede filer skal placeres. Du afslutter guiden ved at klikke <menuchoice>Afslut</menuchoice>, hvorefter den nye klasse genereres. De genererede filer vil blive åbnet i editoren, sådan at du kan begynde at arbejde med dem med det samme.
 
[[File:Kdevelop-class-gen-license-choices.png|400px|thumb|center]]


Efter at have oprettet en ny C++-klasse vil du få mulighed for at føje den til et projektmål. Vælg et mål i dialogvinduet eller annulér vinduet og føj filen til et mål manuelt.  
Efter at have oprettet en ny C++-klasse vil du få mulighed for at føje den til et projektmål. Vælg et mål i dialogvinduet eller annulér vinduet og føj filen til et mål manuelt.  


Hvis du valgte skabelonen <tt>Qt Objekt</tt>, markerede nogle standardmetoder og tilføjede et par medlemsvariable, så skulle outputtet ligne det på billedet herunder.  
Hvis du valgte skabelonen <tt>Qt Objekt-underklasse</tt>, markeret nogle standardmetoder og tilføjede et par medlemsvariable, så skulle outputtet ligne det på billedet herunder. Alle de automatisk tilføjede dokumentationsheadere for hver klasse, funktion og dataelement er blevet fjernet for overskuelighedens skyld.  


[[Image:kdevelop-template-result.png|thumb|500px|center]]
[[File:Kdevelop-after-class-generation-lessdoc.png|500px|thumb|center]]


Du kan se, at datamedlemmerne er blevet lavet om til Qt egenskaber med tilgangsfunktioner og Q_PROPERTY-makroer. Argumenter til setterfunktioner overgives endda ved const-reference, hvor det er passende. Desuden er en privat klasse blevet erklæret og en privat pointer oprettet med Q_DECLARE_PRIVATE. Alt dette gøres af skabelonen. Havde du valgt en anden skabelon, så havde resultatet nok set helt anderledes ud.  
Du kan se, at datamedlemmerne er blevet lavet om til Qt egenskaber med tilgangsfunktioner og Q_PROPERTY-makroer. Argumenter til setterfunktioner overgives endda ved const-reference, hvor det er passende. Hvis du vælger <tt>QObject pimpl subclass</tt>, så bliver en privat klasse erklæret og en privat pointer oprettet med Q_DECLARE_PRIVATE. Alt dette gøres af skabelonen. Havde du valgt en anden skabelon, så havde resultatet nok set helt anderledes ud.  
<span id="Creating a new unit test"></span>
<span id="Creating a new unit test"></span>
=== Opret en ny unittest ===
=== Opret en ny unittest ===


Selv om de fleste testsystemer kræver, at hver test også er en klasse, så har '''KDevelop''' en metode til at forenkle oprettelsen af enhedstest. For at oprette en ny test skal du højreklikke på en projektmappe og vælge <menuchoice>Opret fra skabelon</menuchoice>. I skabelonvalgsvinduet vælger du <tt>Test</tt> som kategori og derefter dit programmeringssprog og din skabelon og klikker så <menuchoice>Næste</menuchoice>.  
Selv om de fleste testsystemer kræver, at hver test også er en klasse, så har '''KDevelop''' en metode til at forenkle oprettelsen af enhedstest. For at oprette en ny test skal du højreklikke på en projektmappe og vælge <menuchoice>Opret fra skabelon...</menuchoice>. I dialogen <tt>Sprog og skabelon</tt> vælger du (programmerings-) <tt>Sprog</tt>, dit <tt>Framework</tt> og <tt>Skabelon</tt> og klikker så <menuchoice>Næste</menuchoice>.
 
[[File:Kdevelop-test-selection.png|500px|thumb|center]]
 
Du bliver nu spurgt om testens navn og en liste af testtilfælde. For testilfældene skal du blot angive en liste med navne. Nogle unittestsystemer så som PyUnit og PHPUnit kræver, at testtilfældene starter med et specielt præfiks. I '''KDevelop''' er skabelonen ansvarlig for at tilføje præfikset, så du skal ikke føje det til testtilfældene her. Efter at have klikket på <menuchoice>Næste</menuchoice> skal du angive licens og outputplacering for de genererede filer; så bliver testen oprettet. Unittests, som oprettes på denne måde bliver ikke automatisk føjet til et mål.
 
[[File:Kdevelop-testcases.png|500px|thumb|center]]
 
Tilføjer du unittests, og en <tt>CMakeLists.txt</tt>-fil for at tilføje unittestene til projektet Bus, så får du følgende <tt>CMakeLists.txt</tt> for projektet Bus, mappen src og mappen tests:
* Projektet Bus: <syntaxhighlight lang="CMake" line>cmake_minimum_required(VERSION 3.0)
 
project(Bus LANGUAGES CXX)
 
set(QT_REQUIRED_VERSION "5.14.0")
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test)
 
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
 
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
# Docs only available if this is the main app
find_package(Doxygen)
if(Doxygen_FOUND)
add_subdirectory(docs)
else()
message(STATUS "Doxygen not found, not building docs")
endif()
 
add_subdirectory(src)
 
enable_testing()
add_subdirectory(tests)</syntaxhighlight>
 
* src folder:<syntaxhighlight lang="CMake" line>set(HEADER_LIST "bus.h")
add_executable(bus main.cpp bus.cpp)
 
target_link_libraries(bus PRIVATE Qt5::Core)
</syntaxhighlight>
 
* mappen tests:<syntaxhighlight lang="CMake" line>include_directories("../src")
 
add_executable(TestBus testbus.cpp ../src/bus.cpp)
 
add_test(NAME TestBus COMMAND TestBus)
 
target_link_libraries(TestBus PRIVATE Qt5::Test) </syntaxhighlight>
 
I filen <tt>testbus.h</tt> ser du de testtilfælde, som blev angivet i dialogen; testprefikset er blevet tilføjet af skabelonen:
 
<syntaxhighlight lang="cpp" line>class TestBus: public QObject
{
    Q_OBJECT
 
// each private slot is a test
private slots:
    // -- tests to run on slots --
    void testNumberOfPassengers();
    void testNameOfDriver();
    // -- tests to run on signals --
    void testNumberOfPassengersChanged();
    void testNameOfDriverChanged();
private:
    Transportation::Bus m_bus;
};</syntaxhighlight>
 
De færdiggjorte funktioner i testbus.cpp vises herunder:
 
* testNumberOfPassengers<syntaxhighlight lang="cpp" line>void TestBus::testNumberOfPassengers()
{
    m_bus.setNumberOfPassengers(1);
    QVERIFY(m_bus.numberOfPassengers() == 1);
}</syntaxhighlight>
 
* testNameOfDriver<syntaxhighlight lang="cpp" line>void TestBus::testNameOfDriver()
{
    m_bus.setNameOfDriver(QString("Billy"));
    QVERIFY(m_bus.nameOfDriver() == QString("Billy"));
}</syntaxhighlight>
 
* testNumberOfPassengersChanged<syntaxhighlight lang="cpp" line>void TestBus::testNumberOfPassengersChanged()
{
    // create spy object
    QSignalSpy spy1(&m_bus,
                    &Transportation::Bus::numberOfPassengersChanged);
    // now change the number of passengers
    m_bus.setNumberOfPassengers(4);
    // verify the check was made
    QVERIFY(m_bus.numberOfPassengers() == 4);
    // verify the signal was sent
    QCOMPARE(spy1.count(), 1);
}</syntaxhighlight>
 
* testNameOfDriverChanged<syntaxhighlight lang="cpp" line>void TestBus::testNameOfDriverChanged()
{
    // create spy object
    QSignalSpy spy1(&m_bus,
                    &Transportation::Bus::nameOfDriverChanged);
    // now change the name of driver
    m_bus.setNameOfDriver(QString("Jim"));
    // verify the check was made
    QVERIFY(m_bus.nameOfDriver() == QString("Jim"));
    // verify the signal was sent
    QCOMPARE(spy1.count(), 1);
   
}</syntaxhighlight>
 
At this point, running build on the project also builds the tests. You can run Bus and TestBus separately. Right clicking on the TestBus target gives a pop-up menu where you can select <menuchoice>Execute As ...</menuchoice> then <menuchoice>Compiled Binary</menuchoice>. This opens the <tt>Run</tt> tool view with the following output:
 
{{Input|1=<nowiki>********* Start testing of TestBus *********
Config: Using QtTest library 5.14.1, Qt 5.14.1 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 7.4.0)
PASS  : TestBus::initTestCase()
PASS  : TestBus::testNumberOfPassengers()
PASS  : TestBus::testNameOfDriver()
PASS  : TestBus::testNumberOfPassengersChanged()
PASS  : TestBus::testNameOfDriverChanged()
PASS  : TestBus::cleanupTestCase()
Totals: 6 passed, 0 failed, 0 skipped, 0 blacklisted, 8ms
********* Finished testing of TestBus *********
*** Finished ***</nowiki>}}
 
Running the build, executable, and tests form the command line looks a little different. The tests are combined as one file test. Looking in <tt>build/Testing/Temporary</tt> you will find the <tt>LastTest.log</tt> that shows each test performed similar to above.


Du bliver nu spurgt om testens navn og en liste af testtilfælde. For testilfældene skal du blot angive el liste med navne. Nogle enhedstestsystemer så som PyUnit og PHPUnit kræver, at testtilfældene starter med et specielt præfiks. I '''KDevelop''' er skabelonen ansvarlig for at tilføje præfikset, så du skal ikke føje det til testtilfældene her. Efter at have klikket på <menuchoice>Næste</menuchoice> skal du angive licens og outputplacering for de genererede filer; så bliver testen oprettet.  
[[File:kdevelop-bus-command-line.png|500px|thumb|center]]


Enhedstest oprettet på denne måde vil ikke automatisk blive føjet til noget mål. Hvis du bruger CTest eller et andet testsystem, så sørg for at føje de nye filer til et mål. '''KDevelop''' giver dig en [[KDevelop5/Manual/Tool_list/Unit_Tests|værktøjsvisning til enhedstests]], som integrerer med CTest.  
Hvis du bruger CTest eller et andet testsystem, så sørg for at føje de nye filer til et mål. '''KDevelop''' giver dig en [[KDevelop5/Manual/Tool_list/Unit_Tests|værktøjsvisning til enhedstests]], som integrerer med CTest.  
<span id="Other files"></span>
<span id="Other files"></span>
=== Andre filer ===
=== Andre filer ===
Line 48: Line 173:
I guiden <menuchoice>Fil -> Ny fra skabelon</menuchoice> kan du også downloade flere filskabeloner ved at klikke på knappen <menuchoice>Hent flere skabeloner...</menuchoice>. Dette åbner en Hent smarte nye ting-dialog, hvor du kan installere flere skabeloner samt opdatere eller fjerne dem. Der er også et konfigurationsmodul for skabeloner, som åbnes med menuen <menuchoice>Indstillinger -> Indstil KDevelop -> Skabeloner</menuchoice>. Her kan du håndtere både filskabeloner (forklaret ovenfor) og projektskabeloner (som bruges til at oprette nye projekter).  
I guiden <menuchoice>Fil -> Ny fra skabelon</menuchoice> kan du også downloade flere filskabeloner ved at klikke på knappen <menuchoice>Hent flere skabeloner...</menuchoice>. Dette åbner en Hent smarte nye ting-dialog, hvor du kan installere flere skabeloner samt opdatere eller fjerne dem. Der er også et konfigurationsmodul for skabeloner, som åbnes med menuen <menuchoice>Indstillinger -> Indstil KDevelop -> Skabeloner</menuchoice>. Her kan du håndtere både filskabeloner (forklaret ovenfor) og projektskabeloner (som bruges til at oprette nye projekter).  


[[Image:kdevelop-template-manager.png|thumb|500px|center]]
[[File:Kdevelop-templatemanager.png|500px|thumb|center]]


Du kan selvfølgelig altid oprette nye skabeloner, hvis ingen af de tilgængelige skabeloner passer til dit projekt. Den nemmeste måde er nok at kopiere og modificere en eksisterende skabelon; du kan finde hjælp i den korte [http://techbase.kde.org/Development/Tutorials/KDevelop/Creating_a_class_template vejledning] og det længere [http://techbase.kde.org/Projects/KDevelop5/File_template_specification specifikationsdokument]. For at kopiere en installeret skabelon åbner du skabelonhåndteringen ved <menuchoice>Indstillinger -> Indstil KDevelop... -> Skabeloner</menuchoice>, <!--XXTjekXX--> markerer den skabelon du vil kopiere og klikker på knappen<menuchoice>Extract Template</menuchoice>. Vælg en målmappe og klik på <menuchoice>O.k.</menuchoice>, så bliver indholdet af skabelonen overført til den valgte mappe. Du kan nu redigere skabelonen ved at åben de overførte filer og modificere dem. Når du er færdig kan du importere dine nye skabeloner i '''KDevelop''' ved at åbne skabelonhåndteringen, gå til de relevante faneblad (enten <menuchoice>Projektskabeloner</menuchoice> eller <menuchoice>Filskabeloner</menuchoice>) og klikke på <menuchoice>Indlæs skabelon</menuchoice>. Åbn skabelonens beskrivelsesfil, som har filendelse <code>.kdevtemplate</code> eller <code>.desktop</code>. '''KDevelop''' vil komprimere filerne til et skabelonarkiv og importere skabelonen.  
Du kan selvfølgelig altid oprette nye skabeloner, hvis ingen af de tilgængelige skabeloner passer til dit projekt. Den nemmeste måde er nok at kopiere og modificere en eksisterende skabelon; du kan finde hjælp i den korte [http://techbase.kde.org/Development/Tutorials/KDevelop/Creating_a_class_template vejledning] og det længere [http://techbase.kde.org/Projects/KDevelop5/File_template_specification specifikationsdokument]. For at kopiere en installeret skabelon åbner du skabelonhåndteringen ved <menuchoice>Indstillinger -> Indstil KDevelop... -> Skabeloner</menuchoice>, <!--XXTjekXX--> markerer den skabelon du vil kopiere og klikker på knappen<menuchoice>Extract Template</menuchoice>. Vælg en målmappe og klik på <menuchoice>O.k.</menuchoice>, så bliver indholdet af skabelonen overført til den valgte mappe. Du kan nu redigere skabelonen ved at åben de overførte filer og modificere dem. Når du er færdig kan du importere dine nye skabeloner i '''KDevelop''' ved at åbne skabelonhåndteringen, gå til de relevante faneblad (enten <menuchoice>Projektskabeloner</menuchoice> eller <menuchoice>Filskabeloner</menuchoice>) og klikke på <menuchoice>Indlæs skabelon</menuchoice>. Åbn skabelonens beskrivelsesfil, som har filendelse <code>.kdevtemplate</code> eller <code>.desktop</code>. '''KDevelop''' vil komprimere filerne til et skabelonarkiv og importere skabelonen.  

Latest revision as of 11:14, 7 April 2020

Other languages:
Under konstruktion
Dette er en ny side, som er ved at blive færdiggjort!


Kodegenering med skabeloner

KDevelop bruger skabeloner til at generere kildekodefiler og for at undgå at skrive kode som gentages.

Opret en ny klasse

Den mest almindelige anvendelse af kodegenerering er formentlig at skrive en ny klasse. For at oprettet en ny klasse i et eksisterende projekt skal du højreklikke på projektmappen og vælge Opret fra skabelon.... Den samme dialog kan startes fra menuen ved at vælge Fil -> Ny fra skabelon..., men fordelen ved at bruge en projektmappe er, at basis-URL'en bliver sat for outputfilen. Vælg C++ i afsnittet "Sprog", og det framework og den skabelon der ønskes i de andre to felter. Nederst i dialoges ser du en forhåndsvisning af de filer, der vil blive genereret, og hvor du kan browse igennem disse filer. Efter at du har foretaget dine valg skal du angive detaljer om den nye klasse i dialogen "Basalt for klasse" efter at du har klikket på > Næste..

Først skal du angive en identifikator for klassen. Dette kan være en simpelt navn (som Bus) eller en komplet identifikator men navnerum (som Transportation::Bus). I det sidste tilfælde vil KDevelop fortolke identifikatoren og separere navnerummet fra det egentlige navn. I det samme vindue kan du tilføje den nye klasses basisklasser. Du bemærker måske, at nogle skabeloner selv vælger en basisklasse, men du kan frit fjerne den og du kan tilføje andre basisklasser. Du bør skrive hele nedarvningserklæringen her, hvilket afhænger af sproget, fx public QObject for C++, extends SomeClass for PHP og blot klassens navn for Python.

I det næste vindue kan du vælge bland de virtuelle metoder fra alle nedarvede klasser samt nogle standard konstruktorer, destruktorer og operatorer. Markér afkrydsningsfeltet ved siden af en metodesignatur for at implementere denne metode i den nye klasse.

Når du klikker på > Næste kommer du til dialogen "Medlemmer af klasse", hvor du kan tilføje medlemmer til klassen. Afhængigt af den valgte skabelon vil de optræde som medlemsvariable i den nye klasse eller skabelonen vil oprette egenskaber med settere og gettere for dem. I sprog som C++, hvor variable skal erklæres skal du angive både type og navn for medlemmet som fx int number eller QString name. I andre sprog behøver du ikke at angive typen, men det er god praksis at have den med alligevel, for den valgte skabelon kan stadig drage nytte af det.Du har også mulighed for at ændre rækkefølgen af klassens medlemmer ved at vælge et medlem og så klikke på enten Flyt op eller Flyt ned. Når filen genereres, så bruges den rækkefølge, som du har valgt.

I de følgende vinduer kan du vælge licensen for din nye klasse, angive særlige oplysninger, som den valgte skabelon skal bruge og angive, hvor de genererede filer skal placeres. Du afslutter guiden ved at klikke Afslut, hvorefter den nye klasse genereres. De genererede filer vil blive åbnet i editoren, sådan at du kan begynde at arbejde med dem med det samme.

Efter at have oprettet en ny C++-klasse vil du få mulighed for at føje den til et projektmål. Vælg et mål i dialogvinduet eller annulér vinduet og føj filen til et mål manuelt.

Hvis du valgte skabelonen Qt Objekt-underklasse, markeret nogle standardmetoder og tilføjede et par medlemsvariable, så skulle outputtet ligne det på billedet herunder. Alle de automatisk tilføjede dokumentationsheadere for hver klasse, funktion og dataelement er blevet fjernet for overskuelighedens skyld.

Du kan se, at datamedlemmerne er blevet lavet om til Qt egenskaber med tilgangsfunktioner og Q_PROPERTY-makroer. Argumenter til setterfunktioner overgives endda ved const-reference, hvor det er passende. Hvis du vælger QObject pimpl subclass, så bliver en privat klasse erklæret og en privat pointer oprettet med Q_DECLARE_PRIVATE. Alt dette gøres af skabelonen. Havde du valgt en anden skabelon, så havde resultatet nok set helt anderledes ud.

Opret en ny unittest

Selv om de fleste testsystemer kræver, at hver test også er en klasse, så har KDevelop en metode til at forenkle oprettelsen af enhedstest. For at oprette en ny test skal du højreklikke på en projektmappe og vælge Opret fra skabelon.... I dialogen Sprog og skabelon vælger du (programmerings-) Sprog, dit Framework og Skabelon og klikker så Næste.

Du bliver nu spurgt om testens navn og en liste af testtilfælde. For testilfældene skal du blot angive en liste med navne. Nogle unittestsystemer så som PyUnit og PHPUnit kræver, at testtilfældene starter med et specielt præfiks. I KDevelop er skabelonen ansvarlig for at tilføje præfikset, så du skal ikke føje det til testtilfældene her. Efter at have klikket på Næste skal du angive licens og outputplacering for de genererede filer; så bliver testen oprettet. Unittests, som oprettes på denne måde bliver ikke automatisk føjet til et mål.

Tilføjer du unittests, og en CMakeLists.txt-fil for at tilføje unittestene til projektet Bus, så får du følgende CMakeLists.txt for projektet Bus, mappen src og mappen tests:

  • Projektet Bus:
    cmake_minimum_required(VERSION 3.0)
    
    project(Bus LANGUAGES CXX)
    
    set(QT_REQUIRED_VERSION "5.14.0")
    find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test)
    
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    # Docs only available if this is the main app
    find_package(Doxygen)
    if(Doxygen_FOUND)
    	add_subdirectory(docs)
    else()
    	message(STATUS "Doxygen not found, not building docs")
    endif()
    
    add_subdirectory(src)
    
    enable_testing()
    add_subdirectory(tests)
    
  • src folder:
    set(HEADER_LIST "bus.h")
    add_executable(bus main.cpp bus.cpp)
    
    target_link_libraries(bus PRIVATE Qt5::Core)
    
  • mappen tests:
    include_directories("../src")
    
    add_executable(TestBus testbus.cpp ../src/bus.cpp)
    
    add_test(NAME TestBus COMMAND TestBus)
    
    target_link_libraries(TestBus PRIVATE Qt5::Test)
    

I filen testbus.h ser du de testtilfælde, som blev angivet i dialogen; testprefikset er blevet tilføjet af skabelonen:

class TestBus: public QObject
{
    Q_OBJECT

// each private slot is a test
private slots:
    // -- tests to run on slots --
    void testNumberOfPassengers();
    void testNameOfDriver();
    // -- tests to run on signals --
    void testNumberOfPassengersChanged();
    void testNameOfDriverChanged();
private:
    Transportation::Bus m_bus;
};

De færdiggjorte funktioner i testbus.cpp vises herunder:

  • testNumberOfPassengers
    void TestBus::testNumberOfPassengers()
    {
        m_bus.setNumberOfPassengers(1);
        QVERIFY(m_bus.numberOfPassengers() == 1);
    }
    
  • testNameOfDriver
    void TestBus::testNameOfDriver()
    {
        m_bus.setNameOfDriver(QString("Billy"));
        QVERIFY(m_bus.nameOfDriver() == QString("Billy"));
    }
    
  • testNumberOfPassengersChanged
    void TestBus::testNumberOfPassengersChanged()
    {
        // create spy object
        QSignalSpy spy1(&m_bus,
                        &Transportation::Bus::numberOfPassengersChanged);
        // now change the number of passengers
        m_bus.setNumberOfPassengers(4);
        // verify the check was made
        QVERIFY(m_bus.numberOfPassengers() == 4);
        // verify the signal was sent
        QCOMPARE(spy1.count(), 1);
    }
    
  • testNameOfDriverChanged
    void TestBus::testNameOfDriverChanged()
    {
        // create spy object
        QSignalSpy spy1(&m_bus,
                        &Transportation::Bus::nameOfDriverChanged);
        // now change the name of driver
        m_bus.setNameOfDriver(QString("Jim"));
        // verify the check was made
        QVERIFY(m_bus.nameOfDriver() == QString("Jim"));
        // verify the signal was sent
        QCOMPARE(spy1.count(), 1);
        
    }
    

At this point, running build on the project also builds the tests. You can run Bus and TestBus separately. Right clicking on the TestBus target gives a pop-up menu where you can select Execute As ... then Compiled Binary. This opens the Run tool view with the following output:

********* Start testing of TestBus *********
Config: Using QtTest library 5.14.1, Qt 5.14.1 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 7.4.0)
PASS   : TestBus::initTestCase()
PASS   : TestBus::testNumberOfPassengers()
PASS   : TestBus::testNameOfDriver()
PASS   : TestBus::testNumberOfPassengersChanged()
PASS   : TestBus::testNameOfDriverChanged()
PASS   : TestBus::cleanupTestCase()
Totals: 6 passed, 0 failed, 0 skipped, 0 blacklisted, 8ms
********* Finished testing of TestBus *********
*** Finished ***

Running the build, executable, and tests form the command line looks a little different. The tests are combined as one file test. Looking in build/Testing/Temporary you will find the LastTest.log that shows each test performed similar to above.

Hvis du bruger CTest eller et andet testsystem, så sørg for at føje de nye filer til et mål. KDevelop giver dig en værktøjsvisning til enhedstests, som integrerer med CTest.

Andre filer

Selv om klasser og enhedstest får særlig opmærksomhed ved kodegenerering fra skabeloner, så kan samme metode bruges til enhver slags kildekodefiler. Du kan for eksempel bruge en skabelon til et Find-modul til CMake eller til en .desktop-fil. Dette kan gøres ved at vælge Opret fra skabelon og vælge den ønskede kategori og skabelon. Hvis du vælger en anden kategori end Klasse eller Test, så vil du kun få mulighed for at vælge licens, særlige oplysninger krævet af skabelonen samt placering af outputfiler. Som med klasser og test bliver filerne genereret og åbnet i editoren når du afslutter guiden.

Håndtering af skabeloner

I guiden Fil -> Ny fra skabelon kan du også downloade flere filskabeloner ved at klikke på knappen Hent flere skabeloner.... Dette åbner en Hent smarte nye ting-dialog, hvor du kan installere flere skabeloner samt opdatere eller fjerne dem. Der er også et konfigurationsmodul for skabeloner, som åbnes med menuen Indstillinger -> Indstil KDevelop -> Skabeloner. Her kan du håndtere både filskabeloner (forklaret ovenfor) og projektskabeloner (som bruges til at oprette nye projekter).

Du kan selvfølgelig altid oprette nye skabeloner, hvis ingen af de tilgængelige skabeloner passer til dit projekt. Den nemmeste måde er nok at kopiere og modificere en eksisterende skabelon; du kan finde hjælp i den korte vejledning og det længere specifikationsdokument. For at kopiere en installeret skabelon åbner du skabelonhåndteringen ved Indstillinger -> Indstil KDevelop... -> Skabeloner, markerer den skabelon du vil kopiere og klikker på knappenExtract Template. Vælg en målmappe og klik på O.k., så bliver indholdet af skabelonen overført til den valgte mappe. Du kan nu redigere skabelonen ved at åben de overførte filer og modificere dem. Når du er færdig kan du importere dine nye skabeloner i KDevelop ved at åbne skabelonhåndteringen, gå til de relevante faneblad (enten Projektskabeloner eller Filskabeloner) og klikke på Indlæs skabelon. Åbn skabelonens beskrivelsesfil, som har filendelse .kdevtemplate eller .desktop. KDevelop vil komprimere filerne til et skabelonarkiv og importere skabelonen.

Note
Når du kopierer eksisterende skabeloner, så sørg for at omdøbe dem før du importerer dem igen. Ellers vil du enten overskrive den gamle skabelon eller vil ende med to skabeloner med samme navn. For at omdøbe en skabelon skal du omdøbe beskrivelsesfilen til noget, der ikke er brugt før (men bevar filendelsen) og ændre feltet Name i beskrivelsesfilen.


Hvis du ønsker at skrive en skabelon fra grunde, så kan du starte med et eksempel på en skabelon for C++-klasser ved at oprette et nyt projekt og vælge projektet C++Class Template i kategorien KDevelop.