Flutter UI Test Nasıl Yazılır?

Sevilay Ağıl
5 min readJan 30, 2021

--

Herkese merhaba 👋 Bu yazıda örnek bir Flutter uygulamasında nasıl UI test yapabiliriz onu inceleyeceğiz.

Günümüzde mobil uygulamalar hayatımızın olmazsa olmazı haline geldi. Bugun birçok kullanıcı günlük işlerini mobil uygulamalardan ve sosyal etkileşimlerini ise Twitter, Facebook, Instagram gibi uygulamalardan sağlıyor. Bu uygulamalar ise daha hızlı ve kaliteli arayüzler oluşturmak için son kullanıcıya ulaşmadan önce birçok süreç geliştiriyor.

Mobil geliştiriciler bu kaliteyi artırmak için yazdıkları kodları ,belli bir yöntemi ve sınıfı test etmek için genellikle unit testler yazarak kaliteye destek oluyorlar. Fakat bir kullanıcının uygulama boyunca yaptığı kaydırma, dokunma gibi etkileşimlerde uygulamanın nasıl tepki verdiğini anlamak için Unit testler tek başına yeterli değildir. Bu akışlar için uçtan uca bir akışın UI testini de yazmak gereklidir. Biz de bu yazımızda Flutterla geliştirilen bir uygulamanın UI testlerinin nasıl yazılacağını inceleyeceğiz.

Öncelikle Flutter nedir kısaca bahsedelim.

Mobil uygulama geliştirme dediğimizde aklımızda Android ve Ios tabanlı işletim sistemleri geliyor. Flutter ise bize sagladığı cross-platform altyapısı sayesinde uygulamalarımızın IOS ve Android işletim sistemlerine çıktılarını kolayca alabileceğimiz bir olanak sağlıyor. Flutter Google tarafından oluşturulan Açık kaynak kodlu mobil, web ve masaüstü uygulamaları geliştirmemize olanak sağlayan bir mobil UI frameworkudur. Flutter geliştirmesinde Dart denilen bir programlama dili kullanılır. Dokümantasyonu oldukça güzel olan bu frameworku daha fazla incelemek ve kurulumlara göz atmak isterseniz https://flutter.dev/docs/get-started/install linkinden detaylı bir inceleme sağlayabilirsiniz.

Şimdi biz Flutter’ın test tarafını inceleyelim.

Demo

Senaryomu geliştirmeden önce senaryoya uygun olması için bir demo app oluşturdum. Burada kedim Muhtar’ın mama kabında artma ve azalma oluşturacak, mevcut mama miktarını gösterecek şekilde bir UI oluşturdum. Şimdi aşama aşama hem UI tarafının hem de test tarafının nasıl yazıldığına geçelim.

Proje dizini ve görünümü

Projenin UI’ını main.dart altında yazdım. Burada Floating buttona her tıkladığımızda mama miktarı bir artarken mama miktarını azalt butonuna tıkladığımda da mama birer birer azalıyor. Show dialog methodu ile de mama miktarını göstere tıkladığımda ekranda bir popup açılarak mevcut mama miktarı görüntüleniyor.

Flutter Driver

Selenium Webdriver sayesinde Web UI testleri yazabildiğimiz gibi Flutter Driver sayesinde de Flutter uygulamalarının testlerini yazabiliyoruz. Projede öncelikle pubspec.yaml’a flutter driver’ımızı ekleyelim. Pubspec.yaml dosyasına assets altında yer alan image’ımızı da tanımlamayı unutmayalım.

dev_dependencies:flutter_driver:sdk: fluttertest: anyassets:- assets/images/cat.jpeg

Ekleyip kaydetme işleminden sonra packages altına paketimizin geldiğini kontrol edelim.

flutter_driver:file:///Users/sevilayagil/flutter/packages/flutter_driver/lib/

Flutter driver’ı kullanmadan önce oluşturdugumuz test_ driver package altına iki yeni test dosyası oluşturalım. İlk dosyamız flutter driver uzantısını etkinleştiren method ve testlerimizi çağırmamızı içeren ui.dart dosyasıdır.

import 'package:flutter_driver/driver_extension.dart';import 'package:flutter_automation/main.dart' as app;
void main() {// This line enables the extension.
enableFlutterDriverExtension();// Call the `main()` function of the app, or call `runApp` with// any widget you are interested in testing.
app.main();}

Bu dosyaların içeriğini aşağıdaki Flutter dokümantasyonunu referans alarak oluşturdum. Detaylı inceleme için : https://flutter.dev/docs/cookbook/testing/integration/introduction

İkinci dosyamız ise test scriptlerimizin yer aldığı ui_test.dart dosyasıdır. Burada driver sürücüsüne bağlanma, bağlantıyı kapatma ve test scriptlerini içerir.

void main() {
group('Counter App', () {

FlutterDriver driver;
//Testler öncesinde Flutter drivera bağlanır setUpAll(() async {
driver = await FlutterDriver.connect();
});

// Test bitiminde driverı kapatır
tearDownAll(() async {
if (driver != null) {
driver.close();
}
});

Şimdi test scriptlerimizi yazalım. Scriptlerin son hali aşağıdaki gibi olacaktır.

Şimdi sırayla ne yaptığımızı inceleyelim.

Burada scriptleri yazarken main.dart’ta kullandığımız alanların value’larını, key’lerini, tooltip’lerini kullanarak ,yani ayırt edici özellikleriyle, aşağıdaki gibi driver’ın bu alanları tanımasını sağlıyoruz. Tıpkı Selenium Webdriver kullanırken elementlerin path’lerini tanımlamamız gibi ✌🏻

final counterTextFinder = find.byValueKey('counterText');final buttonFinder = find.byTooltip('increment');final buttonAdd = find.byValueKey('add');final buttonSubtract = find.byValueKey('subtract');final alertText = find.byValueKey('alert_text');final btnClose = find.byValueKey('close_button');final textBoxName = find.byValueKey('inputKey');

İlk scriptimizde driver’ın durumunu kontrol ediyoruz. Bu bize çalıştığında driver’ın HealthStatus.ok şeklinde durumunu verecektir.

test('Flutter Driver Durum Kontrol', () async {Health health = await driver.checkHealth();print(health.status);});

İkinci scriptimizde mama miktarını arttıralım. Burada tap(), getText() methodlarını kullanıyoruz. Tanımladığımız buttonfinder’a tıklayarak sonrasında counterTextFinder alanındaki miktarın artışını kontrol ediyoruz.

test('Mama Miktarı Arttır', () async {// First, tap the button.
await driver.tap(buttonFinder).then((value) async {expect(await driver.getText(counterTextFinder), "1");print('Buttona bir kez tıklandı mama miktarı 1 oldu');});
// Then, verify the counter text is incremented by 1.
await driver.tap(buttonFinder).then((value) async {expect(await driver.getText(counterTextFinder), "2");print('Buttona bir kez daha tıklandı mama miktari 2 oldu');});});

Üçüncü scriptimizde mama göster butonuna yani buttonAdd alanına tıklatarak çıkan popup alertText’indeki mevcut mama sayısının beklenen değerimizi karşıladığını görüntülüyoruz.

test('Mevcut mama miktarı alert kontrol', () async {await driver.tap(buttonAdd).then((value) async {expect(await driver.getText(alertText), "Mevcut mama sayisi :2");print('Mevcut mama sayisi 2 oldu');});});

Dördüncü scriptimizde ise popup’ı kapatarak mama miktarını bir azaltıyoruz. Sonrasında mama miktarını kontrol ediyoruz.

test('Mama Miktarı Azalt', () async {await driver.tap(btnClose).then((value) async {await driver.tap(buttonSubtract).then((value) async {expect(await driver.getText(counterTextFinder), "1");print('Mama azalta 1 kez tıklandı mama sayısı 1 azaldı');});});});

Son scriptimizde ise textboxname alanına tıklatarak bu alana sevilay ismini giriyoruz ve sonrasında waitfor ile driver’ı bekleterek o alandaki text’in sevilay olduğunu kontrol ediyoruz. Burada diğerlerinden farklı olarak waitFor() ve enterText methodunu kullandık.

test('Textbox Girilen Isim Kontrol', () async {await driver.tap(textBoxName).then((value) async {await driver.enterText('Sevilay').then((value) async {await driver.waitFor(find.text('Sevilay'));print('Girilen isim kontrol edildi');});});});});

Scriptlerimizi de oluşturduğumuza göre şimdi testimizi çalıştıralım. Bunun için terminale aşağıdaki komutu yazıyoruz.

flutter driver --target=test_driver/ui.dart

Test bitiminde terminalde aşağıdaki log görüntünecektir. Bütün testlerimiz başarılı 👌🏻

00:01 +0: Counter App Flutter Driver Durum KontrolHealthStatus.ok00:01 +1: Counter App Mama Miktarı ArttırButtona bir kez tıklandı mama miktarı 1 olduButtona bir kez  daha tıklandı mama miktari 2 oldu00:01 +2: Counter App Mevcut mama miktarı alert kontrolMevcut mama sayisi 2 oldu00:01 +3: Counter App Mama Miktarı AzaltMama azalta 1 kez tıklandı mama sayısı 1 azaldı00:02 +4: Counter App Textbox Girilen Isim KontrolGirilen isim kontrol edildi00:02 +5: Counter App (tearDownAll)00:02 +5: All tests passed!

Bu yazımda örnek bir demo ile Flutter Driver’la UI testlerimizi yazdık. Ben uğraşırken çok keyif aldım umarım sizler için de öyle olur 💕 Bir sonraki yazılarda görüşmek dileğiyle😻

Projenin kaynak kodları: https://github.com/sevilayagil/Flutter_automation

--

--