
Context
Vanuit Newspark was ik al bij ANWB ingezet om een team te ondersteunen op technisch testvlak. Dit betekende onder andere het opstellen en uitvoeren van testplannen, het schrijven van Postman scripts en suites, het opzetten van applicatie monitoring en ga zo maar door. Sinds oktober ben ik aan de slag gegaan als Mendix ontwikkelaar voor een nieuwe propositie van de ANWB.

Sinds wij zijn gestart aan de propositie heeft Mendix een officieel ondersteunde module opgeleverd waar “unittests” mee kunnen worden geschreven. Ik zet unittests tussen aanhalingstekens omdat Mendix onder water Java gebruikt en wij niet op dat niveau (kunnen/willen) testen. De unittests zijn bedoeld om de kleinst mogelijke stukjes van een microflow te testen.
Ik deel graag mijn eerste ervaringen met jullie!
Voorwaarden:
- Enige Mendix kennis
- Mendix Studio Pro 8.x (8.6.1 is gebruikt in dit voorbeeld)
- CommunityCommons v8.2.0
- ObjectHandling v3.0.1
- UnitTesting v8.0
De modules CommunityCommons, ObjectHandling en UnitTesting zijn te vinden in de Mendix App store.
Doel van deze blog:
Ik heb een simpel project opgezet om een beeld te geven van de UnitTesting module. Ik heb hierbij niet alle facetten van deze module behandeld, maar een simpele, begrijpelijke test geschreven. Denk er dus aan dat dit niet mijn beste staaltje Mendix ontwikkelen is, maar dat dit project puur dient als voorbeeld en ter inspiratie!
Domeinmodel
Mijn domeinmodel ziet er als volgt uit:

Een persistable database entity waar een Name attribuut in zit in de vorm van een stringwaarde.
GUI
Mijn home page is een datagrid met daarin het Person object:

Mijn NewEdit pagina (om een nieuwe “Person” op te voeren in de database, of om er een te wijzigen) is ook niet al te ingewikkeld, en is gegenereerd door Mendix:

In het “echt” (als ik de code run), dan ziet het er als volgt uit:

Microflow
Achter de “Save” knop zit echter een microflow. Normaliter als een NewEdit pagina wordt gegenereerd, worden bij het drukken op de “Save” knop de wijzigingen opgeslagen. In dit geval doe ik een simpele validatie, waarin ik kijk of het “Name” attribuut leeg is of een lege string is.

Op het moment dat het “Name” attribuut niet is gevuld, gaat de flow naar beneden, wordt een pop-up getoond met een foutmelding, en wordt er niets opgeslagen. Als het “Name” attribuut wel is gevuld, gaat de flow verder naar rechts, worden de wijzigingen opgeslagen en wordt de pop-up gesloten.
Ik heb verder geen validatie op duplicaten in de database gezet, om het simpel te houden.
UnitTesting
Nu hebben we een database, we hebben een GUI voor het opvoeren van namen in de database, en we hebben een validatieflow die checkt of er wel een naam wordt meegegeven voor in de database. Op naar de UnitTest!
App store modules
Voor het gebruiken van de UnitTesting module hebben we een drietal Mendix App store modules nodig. LET OP! Bij het inladen van de UnitTesting module verschijnt er onderin een error omdat een icoontje niet gevonden kan worden. Dit is makkelijk op te lossen door op de error te dubbelklikken. Je komt dan bij het element waar het icoontje mist, je kunt hier een ander willekeurig icoontje instellen en dan werkt alles weer!

Runtime settings
Daarnaast moeten we aan ons project iets in de settings aanpassen, zodat de tooling weet welke testen we hebben geschreven. Door het aanroepen van deze microflow bij het starten van onze applicatie, zal de UnitTesting module op zoek gaan naar files die beginnen met Test_ of UT_:

UnitTest Overview
Tot slot willen we onze unittests kunnen zien op onze pagina, zodat we ze ook kunnen draaien vanuit onze eigen GUI. Dit heb ik gedaan door een container toe te voegen, en hier de snippet “UnitTestOverview” in te slepen. Een snippet is een (deel van) een pagina die je op verschillende pagina’s kunt hergebruiken. Heel handig dus, want door die snippet in mijn GUI te slepen, hoef ik zelf niets aan te passen of te doen om de testen te kunnen zien en te kunnen draaien.

Als we nu lokaal onze code draaien, dan zien we als het goed is de UnitTests onder onze Datagrid verschijnen:

Mocht je niet direct UnitTests zien, maar zie je wel de knoppen “Run all module tests” en “Reset all tests”, druk dan op de knop “Reset all tests”. Dan gaat de tooling op zoek naar nieuwe testen, en vindt de tooling de testen die bij de UnitTesting module horen (die komt namelijk met een aantal voorbeelden). Je kunt voor de grap eens op “Run all module tests” klikken, dan zie je gelijk een rapportje verschijnen!
UnitTest schrijven
Maargoed, onze eerste eigen UnitTest dus. Wij hebben in onze applicatie slechts 1 microflow zitten met logica, namelijk de validatie flow. Deze flow checkt of het attribuut “Name” gevuld is. Hier kunnen wij een test op schrijven!
UnitTest microflow
De eerste test die we gaan schrijven noemen we Test_Validation_No_Name. We kunnen vast helemaal los gaan op naming conventions, maar laten we het even simpel houden. Belangrijkste hier is dat de UnitTesting tool checkt of microflows met “Test_” of met “UT_” beginnen.
Testdata
Bij onze UnitTest willen we in control zijn van de data die we gebruiken, dus we maken hier in de test een object “Person” aan, ZONDER “Name” attribuut. Normaal gesproken wordt dit object aangemaakt zodra we iets invoeren in onze GUI, maar dat kunnen we dus omzeilen in de code door hem hier aan te maken:

Te testen logica als submicroflow
Vervolgens slepen we onze Validation microflow in onze test microflow. De microflow wordt dan een blokje, en dus eigenlijk een submicroflow van onze UnitTest:

We moeten niet vergeten om ons zojuist gemaakte “Person” object mee te geven aan de “Validation” flow. Dit doen we door te dubbelklikken op deze flow, en op het mee te geven object. Hier geven we dan $NewPerson mee, ons nieuwe object!

Validatie
Onder de “Validation” flow (ik heb hem voor de duidelijkheid even paars gemaakt), zien we “Variable” staan, met daaronder in het blauw “Boolean”. Dit is een stukje voorbereiding die ik in onze Validation flow heb gedaan; hier geef ik voor de GOED flow een “true” terug, en voor de FOUT flow een “false”. En die kunnen we dan weer gebruiken voor het valideren van onze test:

Goed, we hebben dus een “Create object” gedaan om een “Person” object aan te maken ZONDER een “Name” attribuut. Vervolgens gaan we ons paarse blokje in, de “Validation” flow. Zoals we in de afbeelding hierboven kunnen zien, gaat de Validation flow mis als het “Name” attribuut niet aanwezig is… En verwachten we dus dat de Variable die uit de Validation flow komt, “false” is!
Dit gaan we checken in de test:

Test OK/NOK
Vervolgens geef ik aan het eind van mijn UnitTest ook een “true” of een “false” mee, zodat de tooling weet of hij mijn resultaat GROEN of ROOD (OK/NOK) moet markeren:

Eigen UnitTest in het overzicht
Wanneer we nu de code nogmaals draaien (Run Locally) en nogmaals op “Reset all tests” klikken, dan is er nu als het goed is een UnitTest bij gekomen, namelijk de test die wij zojuist hebben gemaakt!

Resultaat
En als we dan op “Run test” klikken, rechtsonderin….

Test geslaagd!
Conclusie
Dit was een eerste indruk van de UnitTesting tool die nu wordt aangeboden door Mendix. Zoals ik aan het begin al schreef, er zijn verschillende manieren om met de UnitTesting module te werken. Ik heb nu, om het leesbaar en begrijpelijk te houden voor iedereen, gekozen om zelf een assertion te doen op of er een “true” of een “false” uit mijn Validation flow zou komen. Er bestaan binnen de UnitTesting module ook twee varianten van een Assertion microflow die ik daar ook voor kan gebruiken. Daarnaast heb ik nu geen gebruik gemaakt van de “ReportStep” microflow van de UnitTesting module. Deze ReportStep kan helpen bij debugging, omdat je dan in het schermpje “Details” (rechts van “Run test”) kunt zien welke stap het laatst is gelukt voordat de test is gefaald. Maar dit kan ik vast behandelen in een volgende blog 😊
Wil jij meer weten over Lowcode development met Mendix, en/of over het testen van je Mendix applicatie? Stuur me dan gerust een mailtje op wb@newspark.nl!