Aplikacje mobilne komunikujące się z urządzeniami IoT potrafią nastręczyć unikalnych wyzwań podczas automatyzacji testów. Moją rolą, jako architekta rozwiązań, było przygotowanie frameworka umożliwiającego kompleksowe testy automatyczne aplikacji mobilnej wymieniającej komunikaty za pomocą NFC (Near Field Communication) z urządzeniem fizycznym. W omawianym przypadku standardowe, gotowe rozwiązania testowania aplikacji mobilnych nie mają zastosowania przez ograniczenie, jakie wprowadza ten sposób komunikacji.
W niniejszym case study opiszę napotkane problemy i zastosowane rozwiązania podczas tworzenia tak niestandardowego środowiska testowania.
Czym jest NFC?
Zanim zacznę omówienie frameworka, chciałbym przybliżyć, czym jest NFC. Jest to technologia łączności krótkiego zasięgu (do ~4 cm) umożliwiająca wymianę danych między smartfonem a tagiem lub drugim urządzeniem.
Istnieją 3 tryby pracy:
- reader/writer – smartfon odczytuje i zapisuje tagi,
- card emulation – telefon udaje kartę lub tag,
- peer-to-peer – bezpośrednia wymiana danych między smartfonami/urządzeniami.
W projektach IoT służy do identyfikacji urządzeń, bezdotykowego uruchamiania czy przekazywania parametrów i konfiguracji. Nasz przypadek dotyczy właśnie takich zdarzeń. Ze względu na fizyczne ograniczenie zasięgu komunikacji, w testach automatycznych istotne jest precyzyjne sterowanie momentem skanowania, co bezpośrednio wpływa na architekturę rozwiązania.
Środowisko testowe i wyzwania konfiguracji

Mając komunikację NFC jako jeden z celów testowania, trzeba wykluczyć użycie wszelkiego rodzaju gotowych chmur urządzeń. Wszystkie chmury, zarówno prywatne jak i współdzielone, a nawet te dedykowane fizyczne poza siedzibą klienta, mają jedno wspólne ograniczenie – brak dostępu fizycznego do telefonu. To pociąga za sobą brak możliwości połączenia telefonu z urządzeniem, które musi znajdować się w odległości nie dalej niż 4 cm.
Pierwszym krokiem było więc zbudowanie lokalnego laboratorium testowego. Aplikacja jest dostępna zarówno na Androida, jak i iOS, co stawia dodatkowe wymagania wobec architektury projektu. Ponieważ automatyzacja testów aplikacji na iPhone’a jest możliwa wyłącznie na komputerach z systemem macOS, konieczne jest użycie takiego sprzętu.
Pocieszający jest fakt, że Android również jest wspierany, dzięki czemu można użyć tylko jednego komputera do obsługi obu systemów. Przed rozpoczęciem prac skonfigurowano oba urządzenia poprzez włączenie trybów deweloperskich i debugowania czy zainstalowaniu odpowiednich certyfikatów.
Robot Framework i Appium
Do automatyzacji wybrano Robot Framework, który to jest zakorzeniony w organizacji, w połączeniu z Appium zdolnym za pomocą driverów obsłużyć obie platformy.
Robot Framework zapewnia czytelność scenariuszy testowych w formie BDD, co pozwala analitykom i kadrze managerskiej przeglądać wyniki. Appium pełni rolę serwera automatyzującego – testy wysyłają komendy do serwera, który to przekazuje odpowiednie instrukcje do urządzeń mobilnych.
Przy tym, wydawałoby się prostym, setupie napotyka się na pierwsze problemy natury konfiguracyjnej:
- stabilne połączenie kablowe do komputera uruchamiającego testy,
- konfiguracja automatycznych update’ów,
- zapewnienie stałego zasilania.
Prawdziwym wyzwaniem okazała się, mimo wszystko, obsługa NFC.
Problem fizycznego zbliżenia urządzeń
Największym wyzwaniem stworzenia frameworka była obsługa działania mechanizmu NFC.
Poza oczywistymi ustawieniami telefonu jak wyłączenie wibracji przy wykryciu taga, wyłączeniu domyślnej akcji czy wprost zabezpieczeniu telefonu w uchwycie tam, gdzie wibracji nie da się wyłączyć, pozostaje problem odległości. Do wymiany danych trzeba zasymulować tapnięcie telefonem o tag, żeby wymusić wzbudzenie i działanie mechanizmu.
Podejście pierwsze
Istnieje kilka podejść, w zależności od testowanego systemu oraz potrzeb. Jednym z nich jest wykorzystanie programowalnych czytników NFC podłączanych do komputera za pomocą USB. Czytnik może symulować tag (w moim przypadku urządzenie), a programowo mógłby się pojawiać i znikać w polu NFC telefonu. Jeśli celem testowania jest sprawdzenie poprawności stworzenia i wysłania komunikatu NFC przez aplikację, takie podejście będzie wystarczające. Daje ono pełną kontrolę nad wysłaną przez telefon ramką, jak również nad jej odpowiedzią.
Niestety, w przypadku testów E2E taki test nie odpowie, czy software urządzenia poprawnie interpretuje komunikaty i generuje odpowiedzi przy okazji oczekiwanego zachowania.
Podejście drugie
Kolejnym podejściem jest użycie serwomechanizmu lub programowalnego ramienia odsuwającego i przysuwającego telefon i tag do siebie. Wybór ten znacząco podnosi złożoność infrastruktury testowej, jak i kodu utrzymującego całe rozwiązanie. Samo rozwiązanie nie jest pozbawione wad, ponieważ musi zostać spełniony warunek odpowiedniej szybkości ruchu taga w polu NFC, a całość musi być zsynchronizowana z przebiegiem testu.
Skuteczne rozwiązanie
Najprostszym rozwiązaniem, które okazało się równie skuteczne, jest programowe wyłączanie i włączanie modułu NFC telefonu, będącego w stałym zasięgu taga.
Testowany telefon fizycznie styka się z anteną NFC urządzenia, ale jego moduł zostaje wyłączony do momentu potrzeby wymiany danych. Włączenie modułu w telefonie powoduje wykrycie taga analogicznie, jak w przypadku zbliżenia telefonu. Wyłączenie modułu symuluje oddalenie urządzenia i eliminuje problem ciągłego skanowania, czy też znajdowania taga przez telefon.
Ta metoda pozwoli zrealizować automatyzację komunikacji NFC zarówno bez udziału człowieka, jak i eliminując symulację ruchu urządzeń, sprowadzając problem do kontrolowania modułu w urządzeniu mobilnym.
Programowe sterowanie NFC
Przeprowadzony test manualny podejścia sterowania modułem zakończył się sukcesem, potwierdzając tym samym, że włączenie modułu wywoła komunikację. Trzeba to było zatem zautomatyzować.
Android jest stosunkowo otwartą platformą, co pozwoliło na zdalne sterowanie ustawieniami telefonu z poziomu testów. ADB (Android Debug Bridge) udostępnia komendy systemowe, które posłużyły do sterowania stanem NFC.
{code}
adb shell svc nfc enable # włączenie NFC
adb shell svc nfc disable # wyłączenie NFC
{/code}
Powyższe polecenia, wywołane na Androidzie z uprawnieniami debuggera, aktywują bądź dezaktywują NFC. W ramach frameworka wywołanie komendy następuje dynamicznie w trakcie testu za pomocą dedykowanego keyworda dostarczonego przez bibliotekę Appium Robot Framework. Dodatkowych zaskoczeń po stronie Androida nie było.
Apple way
Automatyzacja byłaby za prosta, gdyby jedno rozwiązanie działało out-of-the-box dla wielu platform. Dopiero sprytnie ukryta customizacja będzie sprawiała wrażenie jednolitego kodu obsługującego obie platformy. W systemie iOS mamy dodatkowe wyzwania oczekujące rozwiązania, z uwagi na inaczej zaprojektowany model NFC.
Apple udostępnia korzystanie z NFC przez aplikację za pomocą Core NFC. To poprzez ten framework aplikacja inicjuje sesję skanowania taga i oczekuje na jego wykrycie. Problemem jest jednak to, że iOS nie oferuje wyłączenia NFC. Nie istnieje tu żaden mechanizm sterowania, a dodatkowo nowsze telefony Apple posiadają tzw. Background Tag Reading, który sprawia, że NFC „nasłuchuje” cały czas.
Idea rozwiązania polega na ciągłym, fizycznym kontakcie telefonu z tagiem, więc NFC znajduje tag, o czym powiadamia za pomocą pop-upu. Wyskakujące pop-upy potrafią przesłonić niektóre elementy UI i dać fałszywie negatywny wynik testu.
Rozwiązanie
Jak temu zaradzić? Otóż okazuje się, że BTR jest powiązany z niektórymi funkcjami systemu, więc aktywując tryb samolotowy, nie tylko dezaktywuje się sieć komórkową, ale wyłączany jest również BTR. Core NFC natomiast w dalszym ciągu pozwala na korzystanie z NFC w trybie offline i aplikacja może wywołać inicjalizację sesji celem wymiany danych.
Tym samym udało się osiągnąć identyczny efekt jak w przy telefonie z Androidem. Znając dokładny moment, w którym NFC musi zostać uruchomiony, dostajemy możliwość wywołania i przygotowania telefonu z wzbudzeniem IoT do wymiany informacji na obu platformach.

Podsumowanie
Automatyzacja testów w systemach IoT niesie ze sobą wiele niestandardowych wyzwań oraz ich rozwiązań. Framework obsługujący całe rozwiązanie zazwyczaj jest dużo bardziej skomplikowany, przez co również rosną koszty jego utrzymania.
Ostatecznie framework spełnił swoje zadanie, a przede wszystkim pozwolił na pełną obsługę potrzebną do automatyzacji. Case study ukazuje, że nawet tak wydawałoby się proste zadanie jak interakcja poprzez NFC, potrafi wymusić nieszablonowe rozwiązania, a czasem prosty trick zapewni stabilność egzekucji.
Zostaw komentarz