Integrationstestning kontrollerar korrektheten i interaktionen mellan komponenter i en mobilapplikation — moduler, tjänster, databaser och externa API:er. Till skillnad från enhetstester som isolerar varje komponent, upptäcker integrationstester fel i gränssnitten: inkompatibla dataformat, fel vid parameteröverföring och felaktig bearbetning av svar från servern. Enligt uppgifter från Martin Fowler, 2018 täcker integrationstester upp till 40% av kritiska defekter som missats av enhetstester och ger förtroende för systemets stabilitet inför lansering.
Huvudpunkter
Integrationstestning — är fasen av mjukvaruverifiering där korrektheten i interaktionen mellan enskilda moduler eller delsystem i applikationen utvärderas. Medan enhetstester kontrollerar varje komponent isolerat, sammanför integrationstester dessa komponenter och kontrollerar hur de fungerar tillsammans. Typiska scenarier inkluderar dataöverföring mellan nätverkslagret och datalagret, skrivning till databasen via ORM och bearbetning av svar från tredjeparts-API:er.
I sammanhanget av mobilutveckling täcker integrationstester interaktionen mellan UI-lagret, affärslogiken och datakällorna. Till exempel kan ett test kontrollera att efter att ha tryckt på knappen “Logg in” skickar applikationen en förfrågan till servern, tar emot en token och sparar den i lokal lagring. En sådan kontroll bekräftar att komponentkedjan fungerar utan fel.
Enligt rapporten World Quality Report 2023 minskar företag som regelbundet tillämpar integrationstestning antalet produktionsincidenter med 35% jämfört med projekt som endast förlitar sig på enhetstester. Detta gör integrationskontroller till ett obligatoriskt inslag i kvalitetssäkringsstrategin inom kommersiell utveckling.
Mobila applikationer består av många sammankopplade komponenter: nätverksförfrågningar, lokala databaser, push-notiser, systemtjänster och tredjeparts-SDK:er. Var och en av dessa komponenter utvecklas separat, men vid körning utbyter de data i realtid. Integrationstestning upptäcker defekter som inte kan hittas vid isolerad modulkontroll.
Bland typiska problem som upptäcks av integrationstester finns datatypsoverensstämmelse mellan API och applikationsmodell, JSON-serialiseringsfel, felaktig hantering av nätverkstimeouter och fel vid parallell databastillgång via Room eller Core Data. Utan integrationskontroller hamnar sådana defekter i produktion och visar sig bara hos verkliga användare.
Forskning från Google Testing Blog (2021) visar att kostnaden för att åtgärda en defekt som upptäcks i integrationstestningsfasen är 5 gånger lägre än efter lansering. Detta beror på att utvecklaren i tidiga skeden har full felkontext och kan åtgärda det utan en akut hotfix-cykel. Tidsinvestering i att skriva integrationstester lönar sig genom minskade underhållskostnader och ökat användarförtroende.
Det finns tre huvudsakliga metoder för att organisera integrationstester: Big Bang, Bottom-Up och Top-Down. Valet av strategi beror på projektstorlek, applikationsarkitektur och tillgänglighet av komponenter vid testskrivningstillfället. Varje metod har sina fördelar och begränsningar som är viktiga att beakta vid planering av testtäckning.
Big Bang — metod där alla systemkomponenter ansluts samtidigt, varefter en allmän testkörning utförs. Denna metod är enkel att implementera: kräver inga stubs eller emulering av enskilda moduler. Vid upptäckt av ett fel är det dock svårt att avgöra vilken komponent som är källan. Big Bang är motiverat i små projekt med enkel arkitektur, där antalet moduler inte överstiger fem.
Bottom-Up — strategi där integrationstestningen börjar med lågnivåkomponenter: databas, nätverkslager, systemtjänster. Efter kontroll av varje nivå ansluter testerna successivt högre moduler — datalager, Use Case-klasser och ViewModel. Den främsta fördelen är tidig upptäckt av defekter i applikationens grundläggande lager, vilket minskar risken för kaskadfel i senare utvecklingsskeden.
Top-Down — metod där testningen börjar med komponenter på hög nivå — UI-skärmar och navigering, medan lägre moduler imiteras med stubs eller mockar. Detta möjliggör kontroll av användarscenarier innan serverdelen eller databasen är fullt implementerade. Top-Down är särskilt användbar vid parallell utveckling av klient- och serverdelar, när backend ännu inte är redo för verklig integration.
För integrationstestning av mobila applikationer används en rad specialiserade verktyg som delas in i tre kategorier: bibliotek för serveremulering, ramverk för databashantering och verktyg för kontroll av systemtjänster. Valet av specifikt verktyg beror på plattform — Android eller iOS — och projektets teknikstack.
Låt oss titta på praktiska exempel på integrationstester för Android och iOS. För Android-plattformen använder vi MockWebServer tillsammans med JUnit, för iOS — XCTest med OHHTTPStubs-biblioteket. Båda exemplen kontrollerar scenariot att hämta data från ett API och lagra det i ett lokalt datalager.
Detta test kontrollerar att en Retrofit-förfrågan till den emulerade servern returnerar korrekt JSON, och att datalagret omvandlar svaret till en domänmodell. MockWebServer fångar upp förfrågan och returnerar den angivna JSON, varefter testet jämför förväntat resultat med faktiskt resultat.
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()
}
}
För iOS använder ett liknande test OHHTTPStubs för att fånga upp URL-förfrågningar. Biblioteket ersätter serversvaret på systemramverksnivån URL Loading System, vilket möjliggör testning av vilket nätverksbibliotek som helst — URLSession, Alamofire eller Moya.
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)
}
}
Effektiv integrationstestning kräver efterlevnad av ett antal praxis som ökar teststabiliteten och minskar underhållskostnaderna. Isolera externa beroenden: använd in-memory-databaser istället för produktionsinstanser och emulera externa API:er via teststubbibliotek. Detta eliminerar icke-deterministiska fel orsakade av nätverkstillgänglighet eller tillståndet hos externa tjänster.
Upprätthåll testoberoende: varje integrationstest måste fungera isolerat, utan beroende av andra testresultat. Använd @Before- och @After-annoteringar i JUnit eller setUp och tearDown i XCTest för förberedelse och rengöring av testmiljön. Detta förhindrar ömsesidig påverkan av tester och förenklar feldiagnostik.
Täck gränsfall: integrationstester bör kontrollera inte bara framgångsrika scenarier (happy path), utan även felhantering — timeouter, HTTP-koder 4xx och 5xx, tomma svar, skadad JSON. Enligt uppgifter från Google Testing Blog (2022) är 60% av produktionsincidenter relaterade till felaktig hantering av gränsfall som inte täcktes av tester.
Vanliga frågor
Enhetstester kontrollerar en klass eller funktion isolerat och ersätter beroenden med stubs. Integrationstester kontrollerar interaktionen mellan flera verkliga komponenter — till exempel nätverksanslutning och databas samtidigt.
Att köra integrationstester tar vanligtvis 2 till 15 minuter beroende på antalet tester och miljöns komplexitet. För stora projekt rekommenderas att dela upp testerna i parallella jobb i CI-systemet för att minska den totala kontrolltiden före merge.
I första hand skrivs integrationstester för nätverkslagret, databasen och systemtjänster — notiser, kamera, geolokalisering. API-förfrågningar till backend och operationer med lokal lagring ger högst ROI, eftersom dessa komponenter oftast blir källor till regressioner.
För en enda skärm räcker enhetstester av ViewModel och UI-tester. Integrationstester för en enda skärm är motiverade endast om skärmen interagerar med flera datakällor — till exempel kombinerar svar från två olika API:er eller skriver data samtidigt till nätverket och den lokala databasen.
Integrationstester körs vid varje pull request i CI-pipelinen och före större lanseringar. Det rekommenderas också att köra hela uppsättningen integrationstester på natten (nightly build) för att upptäcka defekter relaterade till förändringar i beroenden eller testmiljö.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också