Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Hé Habr!

Mijn naam is Maxim Ponomarenko en ik ben ontwikkelaar bij Sportmaster. Ik heb 10 jaar ervaring op IT-gebied. Hij begon zijn carrière in handmatig testen en schakelde vervolgens over naar databaseontwikkeling. De afgelopen vier jaar heb ik, door de kennis op te doen die ik heb opgedaan bij het testen en ontwikkelen, het testen op DBMS-niveau geautomatiseerd.

Ik zit nu iets meer dan een jaar in het Sportmaster-team en ontwikkel geautomatiseerde tests voor een van de grote projecten. In april spraken de jongens van Sportmaster Lab en ik op een conferentie in Krasnodar, mijn rapport heette "Unit-tests in een DBMS", en nu wil ik het met jullie delen. Er zal veel tekst zijn, dus heb ik besloten het rapport in twee berichten te splitsen. In de eerste zullen we het hebben over autotests en testen in het algemeen, en in de tweede zal ik dieper ingaan op ons unit-testsysteem en de resultaten van de toepassing ervan.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Eerst een beetje saaie theorie. Wat is geautomatiseerd testen? Dit is testen dat wordt uitgevoerd met behulp van software, en in de moderne IT wordt het steeds vaker gebruikt bij softwareontwikkeling. Dit komt door het feit dat bedrijven groeien, hun informatiesystemen groeien en daardoor de hoeveelheid functionaliteit die moet worden getest groeit. Handmatig testen wordt steeds duurder.

Ik werkte voor een groot bedrijf waarvan de releases elke twee maanden verschijnen. Tegelijkertijd is er een hele maand aan besteed om een ​​tiental testers handmatig de functionaliteit te laten controleren. Dankzij de implementatie van automatisering door een klein team ontwikkelaars hebben we de testtijd in anderhalf jaar kunnen terugbrengen naar 2 weken. We hebben niet alleen de snelheid van het testen verhoogd, maar ook de kwaliteit ervan verbeterd. Er worden regelmatig geautomatiseerde tests gelanceerd en deze voeren altijd het hele traject van controles uit, dat wil zeggen dat we de menselijke factor uitsluiten.

Moderne IT wordt gekenmerkt door het feit dat van een ontwikkelaar kan worden verlangd dat hij niet alleen productcode schrijft, maar ook unittests schrijft die deze code controleren.

Maar wat als uw systeem voornamelijk op serverlogica is gebaseerd? Er is geen universele oplossing of best practices op de markt. In de regel lossen bedrijven dit probleem op door hun eigen, zelfgeschreven testsysteem te creëren. Dit is ons eigen, zelfgeschreven geautomatiseerde testsysteem dat voor ons project is gemaakt en ik zal erover praten in mijn rapport.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Loyaliteit testen

Laten we het eerst hebben over het project waarbij we een geautomatiseerd testsysteem hebben geïmplementeerd. Ons project is het Sportmaster loyaliteitssysteem (we schreven er overigens al over in deze post).

Als uw bedrijf groot genoeg is, heeft uw loyaliteitssysteem standaard drie eigenschappen:

  • Uw systeem zal zwaar belast zijn
  • Uw systeem bevat complexe computerprocessen
  • Uw systeem wordt actief verbeterd.

Laten we gaan bestellen... Als we alle Sportmaster-merken in ogenschouw nemen, hebben we in totaal meer dan 1000 winkels in Rusland, Oekraïne, China, Kazachstan en Wit-Rusland. Dagelijks worden in deze winkels ongeveer 300 aankopen gedaan. Dat wil zeggen dat elke seconde 000-3 controles ons systeem binnenkomen. Uiteraard is ons loyaliteitssysteem zwaar belast. En omdat het actief wordt gebruikt, moeten we de hoogste kwaliteitsnormen bieden, omdat elke fout in de software grote financiële verliezen, reputatieschade en andere verliezen met zich meebrengt.

Tegelijkertijd heeft Sportmaster ruim honderd verschillende promoties. Er zijn verschillende promoties: er zijn productpromoties, er zijn promoties gewijd aan de dag van de week, er zijn promoties die verband houden met een specifieke winkel, er zijn promoties voor het bedrag van de bon, er zijn promoties voor het aantal goederen. Over het algemeen niet slecht. Klanten hebben bonussen en promotiecodes die worden gebruikt bij het doen van aankopen. Dit alles leidt ertoe dat het berekenen van elke bestelling een zeer niet-triviale taak is.

Het algoritme dat de orderverwerking implementeert is echt verschrikkelijk en ingewikkeld. En elke wijziging aan dit algoritme is behoorlijk riskant. Het leek erop dat de meest ogenschijnlijk onbeduidende veranderingen tot tamelijk onvoorspelbare effecten konden leiden. Maar juist zulke complexe computerprocessen, vooral de processen die kritische functionaliteit implementeren, zijn de beste kandidaten voor automatisering. Het handmatig controleren van tientallen soortgelijke gevallen is zeer tijdrovend. En aangezien het beginpunt van het proces ongewijzigd is, kunt u, nadat u het eenmaal hebt beschreven, snel automatische tests maken en erop vertrouwen dat de functionaliteit zal werken.

Doordat ons systeem actief gebruikt wordt, zal de business iets nieuws van je willen, met de tijd meeleven en klantgericht zijn. In ons loyaliteitssysteem verschijnen er elke twee maanden releases. Dit betekent dat we elke twee maanden een volledige regressie van het hele systeem moeten uitvoeren. Tegelijkertijd gaat de ontwikkeling natuurlijk, zoals bij elke moderne IT, niet onmiddellijk van de ontwikkelaar naar de productie. Het vindt zijn oorsprong in het ontwikkelaarscircuit, passeert achtereenvolgens de testbank, release, acceptatie en komt dan pas in productie terecht. Op zijn minst moeten we op de test- en vrijgavecircuits een volledige regressie van het hele systeem uitvoeren.

De beschreven eigenschappen zijn standaard voor vrijwel elk loyaliteitssysteem. Laten we het hebben over de kenmerken van ons project.

Technologisch gezien is 90% van de logica van ons loyaliteitssysteem servergebaseerd en geïmplementeerd op Oracle. Er is een client beschikbaar in Delphi, die de functie vervult van een geautomatiseerde werkplekbeheerder. Er zijn zichtbare webservices voor externe applicaties (bijvoorbeeld een website). Daarom is het heel logisch dat als we een geautomatiseerd testsysteem inzetten, we dit op Oracle zullen doen.

Het loyaliteitssysteem in Sportmaster bestaat al meer dan 7 jaar en is gemaakt door afzonderlijke ontwikkelaars... Het gemiddelde aantal ontwikkelaars op ons project gedurende deze 7 jaar was 3-4 personen. Maar het afgelopen jaar is ons team aanzienlijk gegroeid en nu werken er 10 mensen aan het project. Dat wil zeggen dat er mensen naar het project komen die niet bekend zijn met typische taken, processen en architectuur. En er is een verhoogd risico dat we fouten missen.

Het project wordt gekenmerkt door de afwezigheid van toegewijde testers als stafeenheden. Er zijn uiteraard testen, maar testen worden uitgevoerd door analisten, naast hun andere hoofdverantwoordelijkheden: communiceren met zakelijke klanten, gebruikers, ontwikkelen van systeemvereisten, enz. enz... Ondanks het feit dat de tests van zeer hoge kwaliteit worden uitgevoerd (dit is vooral passend om te vermelden, aangezien sommige analisten de aandacht van dit rapport zouden kunnen trekken), is de effectiviteit van specialisatie en concentratie op één ding niet teniet gedaan .

Gezien al het bovenstaande lijkt het idee om het testen van een project te automatiseren, om de kwaliteit van het geleverde product te verbeteren en de ontwikkelingstijd te verkorten, heel logisch. En in verschillende stadia van het bestaan ​​van het loyaliteitssysteem hebben individuele ontwikkelaars hun best gedaan om hun code te bedekken met unit-tests. Over het geheel genomen was het een tamelijk onsamenhangend proces, waarbij iedereen zijn eigen architectuur en methoden gebruikte. De uiteindelijke resultaten waren hetzelfde voor unit-tests: tests werden ontwikkeld, enige tijd gebruikt, opgeslagen in een bestandsopslag met versiebeheer, maar op een gegeven moment stopten ze met draaien en werden ze vergeten. In de eerste plaats was dit te wijten aan het feit dat de tests meer aan een specifieke uitvoerder waren gekoppeld, en niet aan het project.

utPLSQL komt te hulp

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Weet jij iets over Stephen Feuerstein?

Dit is een slimme kerel die een groot deel van zijn carrière heeft gewijd aan het werken met Oracle en PL/SQL, en een behoorlijk groot aantal werken over dit onderwerp heeft geschreven. Eén van zijn beroemde boeken heet: “Oracle PL/SQL. Voor professionals." Het was Stephen die de utPLSQL-oplossing ontwikkelde, of, zoals het staat, Unit Testing-framework voor Oracle PL/SQL. De utPLSQL-oplossing is in 2016 ontstaan, maar er wordt nog steeds actief aan gewerkt en er komen steeds nieuwe versies uit. Op het moment van berichtgeving dateert de laatste versie van 24 maart 2019.
Wat is het. Dit is een apart open source-project. Het weegt een paar megabytes, inclusief voorbeelden en documentatie. Fysiek is het een apart schema in de ORACLE-database met een reeks pakketten en tabellen voor het organiseren van unit-tests. De installatie duurt een paar seconden. Een onderscheidend kenmerk van utPLSQL is het gebruiksgemak.
Globaal gezien is utPLSQL een mechanisme voor het uitvoeren van unit-tests, waarbij een unit-test wordt opgevat als gewone Oracle-batchprocedures, waarvan de organisatie bepaalde regels volgt. Naast het starten slaat utPLSQL een logboek op van al uw testruns en heeft het ook een intern rapportagesysteem.

Laten we eens kijken naar een voorbeeld van hoe de unit-testcode eruit ziet, geïmplementeerd met behulp van deze techniek.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Het scherm toont dus de code voor een typische pakketspecificatie met unit-tests. Wat zijn de verplichte eisen? Het pakket moet worden voorafgegaan door "utp_". Alle procedures met tests moeten exact hetzelfde voorvoegsel hebben. Het pakket moet twee standaardprocedures bevatten: “utp_setup” en “utp_teardown”. De eerste procedure wordt aangeroepen door elke unittest opnieuw te starten, de tweede - na de lancering.

“utp_setup” bereidt ons systeem in de regel voor op het uitvoeren van een unit-test, bijvoorbeeld door testgegevens te creëren. "utp_teardown" - integendeel, alles keert terug naar de oorspronkelijke instellingen en reset de startresultaten.

Hier is een voorbeeld van de eenvoudigste unittest die de normalisatie van het ingevoerde klanttelefoonnummer naar het standaardformulier voor ons loyaliteitssysteem controleert. Er zijn geen verplichte normen voor het schrijven van procedures met unit-tests. In de regel wordt een methode van het te testen systeem aangeroepen en het door deze methode geretourneerde resultaat wordt vergeleken met het referentieresultaat. Het is belangrijk dat de vergelijking van het referentieresultaat en het verkregen resultaat plaatsvindt via standaard utPLSQL-methoden.

Een unittest kan een willekeurig aantal controles bevatten. Zoals uit het voorbeeld blijkt, voeren we vier opeenvolgende oproepen uit naar de geteste methode om het telefoonnummer te normaliseren en het resultaat na elke oproep te evalueren. Bij het ontwikkelen van een unit-test moet u er rekening mee houden dat er controles zijn die op geen enkele manier invloed hebben op het systeem, en dat u na een aantal controles moet terugkeren naar de oorspronkelijke staat van het systeem.
In de gepresenteerde unittest formatteren we bijvoorbeeld eenvoudigweg het ingevoerde telefoonnummer, wat op geen enkele manier invloed heeft op het loyaliteitssysteem.

En als we unit-tests schrijven met behulp van de methode om een ​​nieuwe client aan te maken, dan wordt na elke test een nieuwe client in het systeem aangemaakt, wat van invloed kan zijn op de daaropvolgende lancering van de test.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Dit is hoe unit-tests worden uitgevoerd. Er zijn twee mogelijke startopties: het uitvoeren van alle unit-tests vanuit een specifiek pakket of het uitvoeren van een specifieke unit-test in een specifiek pakket.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

Zo ziet een voorbeeld van een intern rapportagesysteem eruit. Op basis van de resultaten van de unittest bouwt utPLSQL een klein rapport. Daarin zien we het resultaat voor elke specifieke controle en het algehele resultaat van de unittest.

6 regels voor autotests

Voordat we begonnen met het creëren van een nieuw systeem voor het geautomatiseerd testen van het loyaliteitssysteem, hebben we samen met het management de principes bepaald waaraan onze toekomstige geautomatiseerde tests moeten voldoen.

Unittests in een DBMS - hoe we het doen in Sportmaster, deel één

  1. Autotests moeten effectief en nuttig zijn. We hebben geweldige ontwikkelaars, die zeker vermeld moeten worden, omdat sommigen van hen dit rapport waarschijnlijk zullen zien, en ze schrijven prachtige code. Maar zelfs hun prachtige code is niet perfect en bevat, heeft en zal fouten blijven bevatten. Autotests zijn vereist om deze fouten te vinden. Als dit niet het geval is, dan zijn we ofwel slechte autotests aan het schrijven, ofwel zijn we in een dood gebied beland dat in principe niet wordt ontwikkeld. In beide gevallen doen we iets verkeerd en is onze aanpak eenvoudigweg niet logisch.
  2. Er moeten autotests worden gebruikt. Het heeft geen zin om veel tijd en moeite te besteden aan het schrijven van een softwareproduct, het in een repository te stoppen en het te vergeten. Er moeten tests worden uitgevoerd en deze moeten zo regelmatig mogelijk worden uitgevoerd.
  3. Autotests zouden stabiel moeten werken. Ongeacht het tijdstip, de lanceerbasis en andere systeeminstellingen moeten testruns tot hetzelfde resultaat leiden. In de regel wordt dit verzekerd doordat autotests werken met speciale testgegevens met vaste systeeminstellingen.
  4. Autotests moeten werken met een snelheid die acceptabel is voor uw project. Deze tijd wordt voor elk systeem individueel bepaald. Sommige mensen kunnen het zich veroorloven om de hele dag te werken, terwijl anderen het van cruciaal belang vinden om het binnen enkele seconden te doen. Ik zal u later vertellen welke snelheidsnormen we in ons project hebben bereikt.
  5. De ontwikkeling van autotests moet flexibel zijn. Het is niet raadzaam om het testen van functionaliteit te weigeren simpelweg omdat we dit nog niet eerder hebben gedaan of om een ​​andere reden. utPLSQL legt geen beperkingen op aan de ontwikkeling, en met Oracle kunt u in principe een verscheidenheid aan dingen implementeren. De meeste problemen hebben een oplossing, het is gewoon een kwestie van tijd en moeite.
  6. Inzetbaarheid. We hebben verschillende stands waar we tests moeten uitvoeren. Op elke stand kan op elk moment een datadump worden bijgewerkt. Het is noodzakelijk om een ​​project met automatische tests zo uit te voeren dat u de volledige of gedeeltelijke installatie ervan pijnloos kunt uitvoeren.

En in de tweede post over een paar dagen zal ik je vertellen wat we hebben gedaan en welke resultaten we hebben bereikt.

Bron: www.habr.com

Voeg een reactie