Az integrációs tesztelés ellenőrzi a mobil alkalmazás komponensei — modulok, szolgáltatások, adatbázisok és külső API-k — közötti interakció helyességét. Ellentétben az egységtesztekkel, amelyek elkülönítik az egyes komponenseket, az integrációs tesztek a csatlakozási pontokon fedezik fel a hibákat: adatformátumok összeférhetetlensége, paraméterátviteli hibák és a szerverválaszok helytelen feldolgozása. Martin Fowler, 2018 adatai szerint az integrációs tesztek az egységellenőrzések által kihagyott kritikus hibák akár 40%-át is lefedik, és biztosítják a rendszer stabilitásába vetett bizalmat a kiadás előtt.
Főbb pontok
Az integrációs tesztelés — a szoftverellenőrzés azon szakasza, amelyben az alkalmazás egyes moduljai vagy alrendszerei közötti interakció helyességét értékelik. Míg az egységtesztek minden komponenst elkülönítve ellenőriznek, az integrációs tesztek összekapcsolják ezeket a komponenseket, és ellenőrzik, hogyan működnek együtt. Tipikus forgatókönyvek közé tartozik az adatok átvitele a hálózati réteg és a repository között, adatbázisba írás ORM-en keresztül, valamint külső API-k válaszainak feldolgozása.
A mobilfejlesztés kontextusában az integrációs tesztek lefedik az UI-réteg, az üzleti logika és az adatforrások közötti interakciót. Például egy teszt ellenőrizheti, hogy a ‛ejelentkezés” gomb megnyomása után az alkalmazás kérést küld a szervernek, tokent kap, és elmenti azt a helyi tárolóba. Az ilyen ellenőrzés megerősíti, hogy a komponenslánc hibamentesen működik.
A World Quality Report 2023 jelentése szerint azok a vállalatok, amelyek rendszeresen alkalmazzák az integrációs tesztelést, 35%-kal csökkentik a termelési incidensek számát azokhoz a projektekhez képest, amelyek csak egységtesztekre támaszkodnak. Ez az integrációs ellenőrzéseket a minőségbiztosítási stratégia kötelező elemévé teszi a kereskedelmi fejlesztésben.
A mobil alkalmazások számos egymással összefüggő komponensből állnak: hálózati kérések, helyi adatbázisok, push értesítések, rendszerszolgáltatások és külső SDK-k. Mindegyik komponens külön-külön kerül kifejlesztésre, de futásidőben valós időben cserélnek adatokat. Az integrációs tesztelés olyan hibákat tár fel, amelyek a modulok elkülönített ellenőrzése során nem fedezhetők fel.
A tipikus, integrációs tesztek által felfedezett problémák közé tartozik az adattípusok eltérése az API és az alkalmazásmodell között, JSON-szerializációs hibák, a hálózati időtúllépések helytelen kezelése, valamint a Room vagy Core Data segítségével történő párhuzamos adatbázis-hozzáférés során fellépő hibák. Integrációs ellenőrzések nélkül az ilyen hibák éles környezetbe kerülnek, és csak a valódi felhasználóknál jelentkeznek.
A Google Testing Blog (2021) kutatása azt mutatja, hogy az integrációs tesztelés szakaszában felfedezett hiba javítási költsége ötször alacsonyabb, mint a kiadás után. Ennek oka, hogy a korai szakaszban a fejlesztő teljes hibakontextussal rendelkezik, és sürgős hotfix-ciklus nélkül kijavíthatja azt. Az integrációs tesztek írásába fektetett idő megtérül a karbantartási költségek csökkenése és a felhasználói bizalom növekedése révén.
Három fő megközelítés létezik az integrációs tesztek szervezésére: Big Bang, Bottom-Up és Top-Down. A stratégia kiválasztása a projekt méretétől, az alkalmazás architektúrájától és a komponensek rendelkezésre állásától függ a tesztek írásakor. Minden megközelítésnek megvannak a maga előnyei és korlátai, amelyeket fontos figyelembe venni a tesztlefedettség tervezésekor.
Big Bang — megközelítés, ahol a rendszer összes komponensét egyszerre kapcsolják össze, majd egy általános tesztfuttatást végeznek. Ez a módszer egyszerűen implementálható: nem igényel stubok írását vagy egyes modulok emulálását. Azonban hiba észlelésekor nehéz meghatározni, hogy melyik komponens a forrása. A Big Bang egyszerű architektúrájú kis projektekben indokolt, ahol a modulok száma nem haladja meg az ötöt.
Bottom-Up — stratégia, ahol az integrációs tesztelés az alacsony szintű komponensekkel kezdődik: adatbázis, hálózati réteg, rendszerszolgáltatások. Az egyes szintek ellenőrzése után a tesztek fokozatosan csatlakoztatják a magasabb modulokat — repository-kat, Use Case osztályokat és ViewModel-t. A fő előny a hibák korai felismerése az alkalmazás alapvető rétegeiben, ami csökkenti a kaszkádhibák kockázatát a fejlesztés későbbi szakaszaiban.
Top-Down — megközelítés, ahol a tesztelés a felső szintű komponensekkel — UI-képernyők és navigáció — kezdődik, az alsóbb modulokat pedig stubokkal vagy mockokkal imitálják. Ez lehetővé teszi a felhasználói forgatókönyvek ellenőrzését még mielőtt a szerveroldal vagy az adatbázis teljesen implementálva lenne. A Top-Down különösen hasznos a kliens és szerver párhuzamos fejlesztésekor, amikor a backend még nem áll készen a valódi integrációra.
A mobil alkalmazások integrációs teszteléséhez számos speciális eszközt használnak, amelyek három kategóriába sorolhatók: szerveremulációs könyvtárak, adatbázis-keretrendszerek és rendszerszolgáltatások ellenőrző eszközei. A konkrét eszköz kiválasztása a platformtól — Android vagy iOS — és a projekt technológiai stack-jétől függ.
Tekintsük át az integrációs tesztek gyakorlati példáit Androidra és iOS-re. Az Android platformhoz MockWebServer-t használunk JUnit-tel együtt, iOS-hez pedig XCTest-et az OHHTTPStubs könyvtárral. Mindkét példa az API-tól adatok lekérésének és helyi repository-ban történő tárolásának forgatókönyvét ellenőrzi.
Ez a teszt ellenőrzi, hogy az emulált szervernek küldött Retrofit kérés helyes JSON-t ad-e vissza, és a repository átalakítja-e a választ domain modellé. MockWebServer elfogja a kérést és visszaadja a megadott JSON-t, majd a teszt összehasonlítja a várt eredményt a tényleges eredménnyel.
class UserRepositoryTest {
private val mockServer = MockWebServer()
@Before
fun setup() {
mockServer.start()
}
@Test
fun fetchUser_returnsCorrectData() {
val json = "{ \`"id\`": 1, \`"name\`": \`"Alice\`" }"
mockServer.enqueue(MockResponse()
.setBody(json)
.setResponseCode(200))
val repository = UserRepository(
createRetrofit(mockServer.url("/").toString()))
val user = repository.fetchUser(1)
assertEquals(1, user.id)
assertEquals("Alice", user.name)
}
@After
fun tearDown() {
mockServer.shutdown()
}
}
iOS esetében egy hasonló teszt az OHHTTPStubs-t használja az URL kérések elfogására. A könyvtár az URL Loading System rendszerkeretrendszer szintjén helyettesíti a szerver válaszát, lehetővé téve bármely hálózati könyvtár — URLSession, Alamofire vagy Moya — tesztelését.
import XCTest
import OHHTTPStubs
import OHHTTPStubsSwift
class UserRepositoryTests: XCTestCase {
func testFetchUser_returnsCorrectData() {
stub(condition: isPath("/users/1")) { _ in
return HTTPStubsResponse(
jsonObject: ["id": 1, "name": "Alice"],
statusCode: 200,
headers: nil
)
}
let repository = UserRepository()
let expectation = expectation(description: "fetch user")
repository.fetchUser(id: 1) { user in
XCTAssertEqual(user.id, 1)
XCTAssertEqual(user.name, "Alice")
expectation.fulfill()
}
waitForExpectations(timeout: 2.0)
}
}
A hatékony integrációs tesztelés olyan gyakorlatok betartását igényli, amelyek növelik a tesztek stabilitását és csökkentik karbantartási költségeiket. Szigetelje el a külső függőségeket: használjon in-memory adatbázisokat éles példányok helyett, és emulálja a külső API-kat teszt stub könyvtárak segítségével. Ez kiküszöböli a hálózat elérhetősége vagy a külső szolgáltatások állapota által okozott nemdeterminisztikus meghibásodásokat.
Tartsa fenn a tesztek függetlenségét: minden integrációs tesztnek elkülönítve kell működnie, más tesztek eredményeitől függetlenül. Használja a @Before és @After annotációkat JUnit-ban vagy a setUp és tearDown függvényeket XCTest-ben a tesztkörnyezet előkészítéséhez és tisztításához. Ez megakadályozza a tesztek egymásra hatását és leegyszerűsíti a hibadiagnosztikát.
Fedje le a határeseteket: az integrációs teszteknek nem csak a sikeres forgatókönyveket (happy path) kell ellenőrizniük, hanem a hibakezelést is — időtúllépések, HTTP 4xx és 5xx kódok, üres válaszok, sérült JSON. A Google Testing Blog (2022) adatai szerint a termelési incidensek 60%-a olyan határesetek helytelen kezelésével kapcsolatos, amelyeket nem fedtek le a tesztek.
Gyakran ismételt kérdések
Az egységtesztek egy osztályt vagy függvényt ellenőriznek elkülönítve, a függőségeket stubokkal helyettesítve. Az integrációs tesztek több valós komponens — például a hálózati kapcsolat és az adatbázis — egyidejű interakcióját ellenőrzik.
Az integrációs tesztek futtatása általában 2 és 15 perc között tart a tesztek számától és a környezet összetettségétől függően. Nagy projektek esetén ajánlott a teszteket párhuzamos feladatokra bontani a CI-rendszerben a teljes ellenőrzési idő lerövidítése érdekében a merge előtt.
Elsősorban az integrációs teszteket a hálózati rétegre, adatbázisra és rendszerszolgáltatásokra — értesítések, kamera, geolokáció — írják. A backend felé irányuló API-kérések és a helyi tárolóval végzett műveletek adják a legmagasabb ROI-t, mivel ezek a komponensek válnak leggyakrabban regressziók forrásává.
Egyetlen képernyőhöz elegendőek a ViewModel egységtesztjei és az UI-tesztek. Az integrációs tesztek egyetlen képernyőhöz csak akkor indokoltak, ha a képernyő több adatforrással interakcióba lép — például két különböző API válaszait kombinálja, vagy egyszerre ír adatokat a hálózatra és a helyi adatbázisba.
Az integrációs tesztek minden pull request esetén a CI pipeline-ban és a fő kiadások előtt futnak. Ajánlott továbbá a teljes integrációs teszt készletet éjszaka (nightly build) is futtatni, hogy feltárják a függőségek vagy a tesztkörnyezet változásaival kapcsolatos hibákat.
Összegzés
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is