Sunteți pe pagina 1din 10

Calculatoare şi Tehnologia Informaţiei / Ingineria Informaţiei (CTI – INF)

Electronică Aplicată şi Ingineria Informaţiei


Prof. Dr. Ing. Sever Paşca

Proiect de diplomă – Implementare de instrumente de


asigurare a calității (QA) pentru proiecte software

Cuprins:

1.Instrumente folosite
2.Aplicarea CI pe proiectul student supervisor
3.Concluzii
4.Referinte
Introducere
Scopul acestei lucrări îl reprezintă ilustrarea optimizării procesului de integrare și testare aplicat
la un proiect software dezvoltat în java: Aplicație de supervizare a studentului în laborator. Va fi
explicat și aplicat conceptul de Continuous Integration care facilitează detectarea problemelor chiar în
etapa dezvoltării în care acestea apar, și nu la finalul proiectului, prin efectuarea testării la fiecare nouă
centralizare a modificărilor aduse la proiect de către programatori. Pentru a scoate în evidență
avantajele față de abordarea clasică a integrării, în cele ce urmează se va defini conceptul de integrare,
iar cu ajutorul unei scheme vor fi definite câteva concepte cheie din acest domeniu. Integrarea software
prin definiția cea mai generala, reprezintă conectarea tuturor părților componente ale soft-ului. Cu cât
lucrează mai multe persoane la un proiect, cu atât aceasta devine mai dificilă și impune o organizare
mai strictă.

1. Instrumente folosite

1.1
Concepte cheie ce țin de integrare:

• Branch (ramură in engleza)

-In branch-ul master se află proiectul in varianta finită la momentul actual al


dezvoltării;

-Branch-ul master, pentru a nu se altera conținutul, se copiază intr-un branch


development, procedeu numit PULL;
-Fiecare programator, atunci când are un update de făcut, iși creează un branch
feature in care face PULL din development; La sfârsitul task-ului, acesta
adaugă conținutul in branch-ul development;

-La sfârsitul unei etape de dezvoltare, conținutul din development este adăugat in
master printr-un procedeu numit PUSH;

• Build:
- Comanda prin care se realizează centralizarea tuturor fișierelor de cod,
compilarea și crearea unui executabil;
• Deployment:
-Upload-ul conținutului din master la care s-a facut build spre serverul de
producție (accesibil de către utilizator);

• Repository:
-Un spațiu dintr-un server al unui sistem de versionare git (in cazul acestui proiect
GitLab) în care se păstrează toate fișierele proiectului, versiunile, modificarile si
branch-urile;

• Commit:
-Comanda prin care un update asupra soft-ului este salvat in Repository;

În mod tradițional, procedeul de build și deployment se efectua doar la sfârșitul unei etape de
dezvoltare din cauza gradului crescut de dificultate al gestionării multiplelor ramificații. Trebuiau
evitate interferențele între branch-uri ( suprascrierile,modificările la proiect care nu mai erau necesare
etc.), ceea ce făcea ca întreaga procedură să fie lungă, dificilă și supusă riscurilor. Dat fiind că avea loc
la sfârșitul unei întregi etape de dezvoltare, se descopereau deodată toate bug-urile existente ceea ce
complica și mai mult lucrurile.
Marea inovație a procedeului Continuous integration o reprezintă posibilitatea de a înlătura
toate problemele expuse mai sus. Astfel, la fiecare commit căruia programatorul îi da push, pe un
server de continuous integration se face build, obținând astfel o varianta executabila căruia i se pot
aplica testările automate.
Un rol foarte important în facilitarea acestei tehnici îl are tehnologia Docker. Un server accesibil
publicului-Docker Hub conține entități virtuale numite imagini care sunt foarte avantajoase din punct
de vedere al gestionării resurselor software. Asftel, o imagine poate conține pur și simplu numai un
pachet de dezvoltare sau aplicație software așa cum este lansată de firma producătoare, ori pe lângă
acestea pot să se afle și o serie de fișiere, dependențe, executabile, orice dezvoltator putând să adapteze
o imagine existența la propriile nevoi și să creeze o nouă imagine pe care să o pună în Docker Hub.
Beneficiile sunt foarte mari atât din punct de vedere al costurilor cât și ca timp: orice computer dintr-o
firmă poate să facă build pe un proiect în orice mediu, fără a fi necesar să îl instaleze local. De
asemenea fișierele de care depinde un proiect nu mai trebuie instalate local, ele putând fi accesibile
într-o imagine creată. Un alt avantaj este că se poate testa pe orice mediu independent de mediile
existente local.
Schemă Continuous Integration cuprinde serverul git (Gitlab), un Gitlab Runner, cu un executor
asociat, și Docker Hub, cu imaginea sau imaginile create de cel care se ocupă de deployment.
Gitlab Runner execută operațiunile descrise în limbajul YAML și trimite rezultatele înapoi spre Gitlab.

Executorii cei mai comuni sunt Shell și Docker. Pentru Shell însă trebuie ca Development Kit-ul să fie
instalat local, ceea ce creează un dezavantaj din punct de vedere al efortului, în cazul în care se dorește
rularea codului în diverse versiuni ale Development Kit-ului, lucru foarte accesibil prin intermediul
imaginilor Docker. Pentru crearea imaginii Docker se poate face local un build și push pe Docker Hub,
imaginea fiind extrasă în Gitlab din Docker Hub, ori se poate crea un fișier dockerfile, acesta conținând
instrucțiunile necesare creerii imaginii, care să fie pus în repository. Nefiind foarte multe modificări
asupra imaginii docker, am creeat imaginea local și am exportat-o in Docker Hub.

1.2

2. Aplicarea CI pe proiectul student supervisor


Primul pas în realizarea proiectului l-a reprezentat crearea imaginii Docker. Pentru aceasta întâi
am instalat un Git Bash pe windows. Acest pachet permite folosirea comenzilor UNIX și pe windows,
comenzi care sunt mai familiare celor care au lucrat cu fișierele și directoarele în acest mod text. Am
creeat un folder “project” și am modificat calea către acest folder pentru a scrie acolo comanda Docker.

2.1

2.2
Apoi, dat fiind că proiectul este realizat în java, a trebuit să fac build și push la o imagine care
să conțînă JDK (Java Development Kit). Există varianta de a folosi o imagine care să aibă Java instalat
sau să folosesc o imagine cu sistemul de operare Ubuntu pe care să adaug o comandă de instalare a
pachetului Java. Am ales cea de-a două varianta pentru a experimenta mai mult din opțiunile Docker.
Instrucțiunile pentru crearea imaginii se scriu într-un fișier Dockerfile. Fișierul a fost salvat in
directorul “project”. Specificațiile RUN apt-get sunt cele care instalează Java. FROM preia imaginea
Ubuntu din Docker HUB.

2.3
Apoi am făcut comanda pentru build. Caracterul “.” neînsoțit de nimic semnifică faptul că se
face build cu Dockerfile-ul salvat în directorul curent. Numele imaginii este “imagine_proiect”.

2.4
Apoi, pentru a face push, a trebuit să mă loghez la repository-ul creat pentru acest proiect cu
comandă docker login din partea de sus a schemei. Se observă cum fiecare imagine are un
IMAGE_ID. Ultima imagine, cea creată local, nu are un repository deocamdată. În prealabil, am folosit
comandă docker login pentru a putea accesa repository-ul de Docker Hub.
Cu docker tag atribui IMAGE ID-ului imaginii create repository-ul și cu “:” numele din acesta.
Apoi am adăugat imaginea cu “docker push” în repository.

2.5

Următorul pas a fost acela de a testa dacă se poate face build local cu ajutorul tool-ului de build
Maven. Proiectul inițial se baza pe Ant, însă Maven este mai facil din punct de vedere al specificarii
dependențelor (de ex. Cu tool-ul de testare). Pentru această a trebuit să aduc în local proiectul aflat în

2.6
După instalarea Maven, pentru ca tool-ul să poată fi executat de oriunde din Windows, în cazul acestui
proiect din command line, trebuie să se definească niște variabile numite Environment Variables.
Astfel, JAVA_HOME ia valoarea căii Development kit-ului Java, M2_HOME și MAVEN_HOME iau
valoarea căii unde se află folderul Maven.

2.7

Fișierul pom.xml este parte obligatorie a oricărui build cu Maven. În el se specifică parametrii
obligatorii groupId, artifactId, parametri de identificare a proiectului, plug-in-uri, dependențe și
versiuni. Cel mai ușor de creat este prin intermediul unui IDE (Integrated Development Environment),

2.8
Prin acest panou se creează fișierul pom.xml cu parametri groupID și artficatId. Specificația jar din tag-
ul packiging:

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-
4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.project</groupId>
<artifactId>project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>project</name>
<url>http://maven.apache.org</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

Fișierul basic, generat automat conține doar câteva tag-uri. Am adăugat tag-ul “properties” pentru a
preciza versiunea JDK-ului folosit, și “dependencies” pentru a preciza că trebuie integrare cu tool-ul de
testare Junit.
Pentru a putea face build pe Maven, proiectul Java trebuie să respecte structura de foldere de tip
src/main/java. Întrucât proiectul a fost dezvoltat neurmand această structura, a fost nevoie să copiez
fișierele java din proiectul inițial în folderul java din src/main:neurmand această structura, a fost nevoie
să copiez fișierele java din proiectul inițial în folderul java din src/main:

2.9
Astfel am putut să lansez comanda de compilare, din folder-ul în care se află proiectul Maven. Trebuie
ca în folder-ul respectiv sa existe pom.xml, altfel comanda returnează eroare.
2.10
După finalizarea cu succes a build-ului local, am început procedurile necesare pentru a putea face build
în repository. Am creeat un branch nou, “tools”(cu comanda git branch), din branch-ul master, pentru a
adăuga acolo fișierele pom.xml și Gilab-ci.yml( cu comenzile add si commit). Modificarea în cadrul
branchului va fi reținută în istoria modificărilor din repository cu numele “Fisiere CI”.

2.12
Apoi cu comanda push am adaugăt modificarea din branch în repository.

2.13

Aceeași modificare a locației fișierelor java din local, pentru a respecta structura src/main/java,
am efectuat-o și în repository, prin comenzi Bash, astfel încât modificările să apară înregistrate în

2.14
Apoi fișierul yaml transmis către Gitlab Runner se numește Gitlab-ci.yml, cu următorul conținut:

image: george3002/repo_licenta:imagine_proiect
job:
tags:
- docker
stage: build
script:

- JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 mvn package

Imaginea docker a suferit diverse modificări pentru că nu conținea inițial tot ce era necesar efectuării
build-ului. Voi include, în cele ce urmează, detalierea acestor modificări. Fiecare acțiune care trebuie
efectuată în Gitlab poartă denumirea de job. Cuvântul “stage” specifică ce tip de job este acesta. În
cazul acestui proiect, am urmărit efectuarea unui build. Tags specifică care Runnere au dreptul să
execute acest fișier. Fiecare Runner are unul sau mai multe tag-uri. Vor fi executate acelea care au tag-
ul sau tag-urile specificate aici.
Calea JAVA_HOME a fost adăugată pentru că inițial build-ul a eșuat din cauză că nu era recunoscut
pachetul jdk, astfel că a trebuit să adaug pachetul openjdk. Nici acesta nu a fost recunoscut fără a seta
calea. Mvn package face același lucru ca și mvn compile, adică realizează build-ul prin intermediul lui
Maven.

De asemenea, atât local cât și în repository, a trebuit să import librariile opencv în fișierul App.java.
Astfel le-am importat local:
import org.opencv.core.Core;

import org.opencv.core.CvType;

import org.opencv.core.Mat;

În repository, întrucât nu există la îndemână un pachet opencv de instalat în Docker, a trebuit să scriu
comenzi de Git Bash pentru instalarea acestuia:
docker run -it george3002/repo_licenta:imagine_completa bin/bash

În prima fază, comanda a generat următoarea eroare: git: command not found. Ceea ce a făcut necesar
să instalez Git în imaginea de docker, (apt install -y git)
Scriptul necesar instalării OpenCv este acesta:
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON ..
make -j6
make install

Scrierea acestui script a generat alte erori. A trebuit instalat cmake și compilatorul de C++; Apoi, pentru
ca build-ul să funcționeze, a trebuit căutată calea jar-ului OpenCv și adăugată în Pom.xml. Jar-ul
reprezintă un singur fișier de tip pachet conținând mai multe fișiere java. Astfel, în Pom.xml a mai fost
adăugată această secvență:

<dependency>
<groupId>com.opencv</groupId>
<artifactId>opencv</artifactId>
<version>4.1.0</version>
<scope>system</scope>
<systemPath>/usr/local/share/java/opencv4/opencv-410.jar</systemPath>
</dependency>

Calea a fost gasită cu ajutorul comenzii find /usr -name "*opencv*jar" în cadrul imaginii Docker.

2.15

Build-ul a fost efectuat în cele din urmă cu succes. Se observă tag-ul docker.
3. Concluzii
Acest proiect a fost foarte util din punct de vedere al dobândirii cunoștințelor practice în
domeniul integrării. Am constat experimental, ceea ce citisem în teorie, și anume că este foarte facilă
adaptarea mediului la cel necesar realizării build-ului, doar printr-o schimbare de imagine docker,
economisind astfel timp și resurse software. Cea mai elocventă observație în acest sens este aceea că la
orice modificare carea I se da commit, automat se realizează build-ul, fără altă comandă.
De asemenea, ar mai trebui adăugate părțile de packaging și testare continuă.
4. Referinte
Documente online:
[1] https://www.workspaceit.com/blog/how-to-run-an-existing-java-project-
using-maven-without-any-ide/

[2] https://www.mkyong.com/maven/how-to-install-maven-in-windows/
[3] https://ropenscilabs.github.io/r-docker-tutorial/04-Dockerhub.html
[4] https://www.presslabs.com/docs/development/git/git-tutorial/

S-ar putea să vă placă și