Entwicklung einer mobilen Anwendung ohne Server

Sehr oft befinden sich Entwickler bei der Entwicklung mobiler Anwendungen (möglicherweise dasselbe Problem wie bei Webanwendungen) in einer Situation, in der das Backend nicht funktioniert oder die erforderlichen Methoden nicht zur Verfügung stellt.

Diese Situation kann aus verschiedenen Gründen auftreten. Am häufigsten wird jedoch zu Beginn der Entwicklung das Backend einfach nicht geschrieben und der Client startet ohne es. In diesem Fall verzögert sich der Entwicklungsbeginn um 2-4 Monate

Manchmal fährt der Server nur herunter (stürzt ab), manchmal hat er keine Zeit, die erforderlichen Methoden zu implementieren, manchmal gibt es Datenprobleme usw. All diese Probleme haben dazu geführt, dass wir einen kleinen Mocker-Service geschrieben haben, mit dem Sie das echte Backend ersetzen können.



Wie bin ich dazu gekommen?
Wie bin ich dazu gekommen? Mein erstes Jahr bei der Firma war zu Ende und sie haben mich in ein brandneues E-Commerce-Projekt gesteckt. Der Manager sagte, dass das Projekt in 4 Monaten abgeschlossen sein muss, aber das Backend-Team (auf Kundenseite) wird erst nach 1,5 Monaten mit der Entwicklung beginnen. Und in dieser Zeit müssen wir schon viele UI-Features werfen.

Ich schlug vor, ein Moch-Backend zu schreiben (bevor ich iOS-Entwickler wurde, spielte ich mit .NET in der Uni). Die Implementierungsidee war einfach: Gemäß einer bestimmten Spezifikation mussten Stub-Methoden geschrieben werden, die Daten aus vorbereiteten JSON-Dateien entnehmen. Sie entschieden sich dafür.

Nach 2 Wochen fuhr ich in den Urlaub und dachte: "Warum erstelle ich das nicht automatisch?" Für zwei Wochen Urlaub habe ich einen Anschein eines Interpreters geschrieben, der die APIBlueprint-Spezifikation verwendet und daraus die .NET-Webanwendung (C # -Code) generiert.

Als Ergebnis erschien die erste Version dieses Dings und wir lebten fast 2,5 Monate davon. Ich kann keine reellen Zahlen nennen, wie sehr uns das geholfen hat, aber ich erinnere mich, wie sie im Nachhinein gesagt haben, dass es ohne dieses System keine Veröffentlichung geben würde.

Jetzt, nach einigen Jahren, habe ich die Fehler, die ich gemacht habe (und es gab viele), berücksichtigt und das Instrument komplett neu geschrieben.

Nutzen Sie diese Gelegenheit - vielen Dank an Kollegen, die mit Feedback und Ratschlägen zur Seite standen. Und auch an die Führer, die all meine „technischen Beliebigkeiten“ ertragen haben.

Einleitung


In der Regel sieht jede Client-Server-Anwendung folgendermaßen aus:



Jeder Bildschirm hat mindestens 1 Abfrage (und oft mehr). Wenn wir tief in die Bildschirme vordringen, müssen wir immer mehr Anfragen stellen. Manchmal können wir den Übergang erst dann durchführen, wenn der Server uns mitteilt, dass die Schaltfläche angezeigt werden soll. Das heißt, die mobile Anwendung ist nicht nur während ihrer unmittelbaren Arbeit, sondern auch in der Entwicklungsphase stark an den Server gebunden. Betrachten Sie den abstrakten Produktentwicklungszyklus:



  1. Zuerst entwerfen wir. Wir zerlegen, beschreiben und diskutieren.
  2. Nachdem wir die Aufgaben und Anforderungen erhalten haben, beginnen wir mit der Entwicklung. Wir schreiben den Code, den Schriftsatz usw.
  3. Nachdem wir etwas implementiert haben, wird eine Baugruppe vorbereitet, die manuell getestet wird und in der die Anwendung auf verschiedene Fälle überprüft wird.
  4. Wenn bei uns alles in Ordnung ist und die Prüfer die Montage testen, geht es an den Kunden, der die Abnahme vornimmt.

Jeder dieser Prozesse ist sehr wichtig. Vor allem letzteres, da der Kunde verstehen muss, in welchem ​​Stadium wir wirklich sind, und manchmal dem Management oder den Investoren über die Ergebnisse Bericht erstatten muss. Solche Meldungen erfolgen in der Regel auch in Form einer Demonstration einer mobilen Anwendung. In meiner Praxis gab es einen Fall, in dem ein Kunde nur die Hälfte des MVP vorführte, der nur mit Mokas funktionierte. Die Mok-App sieht aus wie die Gegenwart und quakt wie die Gegenwart. Es ist also real (:
Dies ist jedoch ein rosa Traum. Schauen wir uns an, was wirklich passiert, wenn wir keinen Server haben.



  1. Der Entwicklungsprozess wird langsamer und schmerzhafter, da wir normalerweise keine Dienste schreiben können und auch nicht alle Fälle überprüfen können. Wir müssen Stubs schreiben, die später entfernt werden müssen.
  2. Nachdem wir die Montage mit Kummer in zwei Hälften geschafft haben, kommt es zu Testern, die sich das ansehen und nicht verstehen, was sie damit anfangen sollen. Sie können nichts überprüfen, die Hälfte funktioniert überhaupt nicht, da kein Server vorhanden ist. Infolgedessen verpassen sie viele Fehler: sowohl logische als auch visuelle.
  3. Nun, nachdem "wie sie ausgesehen haben könnten", müssen Sie die Montage dem Kunden übergeben und dann beginnt die unangenehmste. Der Kunde kann das Werk nicht wirklich bewerten, er sieht 1-2 Fälle von allen möglichen und kann es sicher nicht seinen Investoren zeigen.

Im Allgemeinen geht alles bergab. Und solche Situationen kommen leider fast immer vor: Manchmal ist für einige Monate, manchmal für ein halbes Jahr kein Server vorhanden, manchmal kommt der Server gerade erst zu spät, oder Sie müssen schnell die Grenzfälle überprüfen, die mithilfe von Datenmanipulationen auf einem realen Server reproduziert werden können.

Zum Beispiel möchten wir überprüfen, wie sich die Anwendung verhält, wenn die Zahlung des Benutzers länger als das Fälligkeitsdatum ist. Es ist sehr schwierig (und lang), eine solche Situation auf dem Server zu reproduzieren, und wir müssen dies künstlich tun.

Daher gibt es folgende Probleme:

  1. Der Server fehlt vollständig. Aus diesem Grund ist es unmöglich zu entwerfen, zu testen und zu präsentieren.
  2. Der Server hat keine Zeit, was die Entwicklung stört und das Testen beeinträchtigen kann.
  3. Wir möchten Grenzfälle testen, und der Server kann dies nicht ohne lange Gesten zulassen.
  4. Beeinflussen Sie das Testen und die Präsentation von Bedrohungen.
  5. Der Server stürzt ab (einmal, während der stabilen Entwicklung, haben wir den Server für 3,5 Tage verloren).

Um diese Probleme zu bekämpfen, wurde Mocker erstellt.

Arbeitsprinzip


Mocker ist ein kleiner Webdienst, der irgendwo gehostet wird, den Datenverkehr auf einem bestimmten Port überwacht und mit vorbereiteten Daten auf bestimmte Netzwerkanforderungen antworten kann.

Die Reihenfolge ist wie folgt:

1. Der Client sendet eine Anfrage.
2. Mocker erhält die Anfrage.
3. Mocker findet den gewünschten Spott.
4. Mocker gibt den gewünschten Mock zurück.

Wenn mit den Punkten 1,2 und 4 alles klar ist, wirft 3 Fragen auf.

Um zu verstehen, wie der Service das für den Kunden notwendige Mock findet, betrachten wir zunächst die Struktur des Mocks selbst.

Mock ist eine JSON-Datei im folgenden Format:

{ "url": "string", "method": "string", "statusCode": "number", "response": "object", "request": "object" } 

Lassen Sie uns jedes Feld separat analysieren.

url


Dieser Parameter wird verwendet, um die URL der Anforderung anzugeben, auf die der Client zugreift.

Wenn eine mobile Anwendung beispielsweise eine Anforderung an die URL host.dom/path/to/endpoint , müssen Sie im Feld url host.dom/path/to/endpoint .
Das heißt, dieses Feld speichert den relativen Pfad zum Endpunkt .

Dieses Feld sollte im URL-Vorlagenformat formatiert sein, dh die folgenden Formate sind zulässig:

  1. /path/to/endpoint - normale URL-Adresse. Wenn die Anfrage eingeht, vergleicht der Dienst die Zeilen zeichenweise.
  2. /path/to/endpoint/{number} - URL mit Pfadmuster. Ein Mock mit einer solchen URL antwortet auf jede Anfrage, die diesem Muster entspricht.
  3. /path/to/endpoint/data?param={value} - URL mit Parameter-Pattern. Ein Mock mit einer solchen URL löst eine Anfrage mit den angegebenen Parametern aus. Wenn einer der Parameter nicht in der Anforderung enthalten ist, stimmt er außerdem nicht mit der Vorlage überein.

Indem Sie die URL-Parameter steuern, können Sie eindeutig festlegen, dass ein bestimmter Mock zu einer bestimmten URL zurückkehrt.

Methode


Dies ist die erwartete http-Methode. Zum Beispiel POST oder GET .
Die Zeichenfolge darf nur Großbuchstaben enthalten.

statusCode


Dies ist der http-Statuscode für die Antwort. Das heißt, durch Anfordern dieses Mocks erhält der Client eine Antwort mit dem im Feld statusCode aufgezeichneten Status.

Antwort


Dieses Feld enthält das JSON-Objekt, das im Hauptteil der Antwort auf seine Anforderung an den Client gesendet wird.

Anfrage


Dies ist der Hauptteil der Anforderung, von dem erwartet wird, dass er vom Client empfangen wird. Dies wird verwendet, um die gewünschte Antwort abhängig vom Hauptteil der Anforderung zu geben. Zum Beispiel, wenn wir die Antworten in Abhängigkeit von den Anforderungsparametern ändern möchten.

 { "url": "/auth", "method": "POST", "statusCode": 200, "response": { "token": "cbshbg52rebfzdghj123dsfsfasd" }, "request": { "login": "Tester", "password": "Valid" } } 

 { "url": "/auth", "method": "POST", "statusCode": 400, "response": { "message": "Bad credentials" }, "request": { "login": "Tester", "password": "Invalid" } } 

Wenn der Client eine Anfrage an den Body sendet:

 { "login": "Tester", "password": "Valid" } 

Dann erhält er als Antwort:

 { "token": "cbshbg52rebfzdghj123dsfsfasd" } 

Und falls wir überprüfen möchten, wie die Anwendung funktioniert, wenn das Passwort falsch eingegeben wurde, wird eine Anfrage mit dem Text gesendet:

 { "login": "Tester", "password": "Invalid" } 

Dann erhält er als Antwort:
 { "message": "Bad credentials" } 

Und wir können den Fall mit dem falschen Passwort überprüfen. Und so auch in allen anderen Fällen.

Und jetzt werden wir herausfinden, wie das Gruppieren und Suchen nach dem gewünschten MOQ funktioniert.



Um schnell und einfach nach dem gewünschten Mok zu suchen, lädt der Server alle Mokas in den Speicher und gruppiert sie richtig. Das Bild oben zeigt ein Beispiel für die Gruppierung.

Der Server kombiniert verschiedene Mokas nach URL und Methode . Dies ist unter anderem notwendig, damit wir auf einer URL viele verschiedene Moks erstellen können.

Zum Beispiel möchten wir, dass durch ständiges Ziehen von Pull-To-Refresh unterschiedliche Antworten kommen und sich der Status des Bildschirms ständig ändert (um alle Grenzfälle zu überprüfen).

Dann können wir mit der gleichen Methode und den gleichen URL- Parametern viele verschiedene Moks erstellen, die der Server (wiederum) iterativ an uns zurückgibt.
Lassen Sie uns zum Beispiel solche Mokas haben:

 { "url": "/products", "method": "GET", "statusCode": 200, "response": { "name": "product", "currency": 1, "value": 20 } } 

 { "url": "/products", "method": "GET", "statusCode": 200, "response": { "name": "gdshfjshhkfhsdgfhshdjgfhjkshdjkfsfgbjsfgskdf", "currency": 5, "value": 100000000000 } } 

 { "url": "/products", "method": "GET", "statusCode": 200, "response": null } 

 { "url": "/products", "method": "GET", "statusCode": 400, "response": null } 

Wenn wir dann zum ersten Mal die Methode GET / products aufrufen, erhalten wir zuerst die Antwort:

 { "name": "product", "currency": 1, "value": 20 } 

Wenn wir das zweite Mal aufrufen, wechselt der Iteratorzeiger zum nächsten Element und kehrt zu uns zurück:

 { "name": "gdshfjshhkfhsdgfhshdjgfhjkshdjkfsfgbjsfgskdf", "currency": 5, "value": 100000000000 } 

Und wir können überprüfen, wie sich die Anwendung verhält, wenn wir große Werte erhalten. Usw.

Wenn wir zum letzten Element gelangen und die Methode erneut aufrufen, wird das erste Element wieder zu uns zurückkehren, da der Iterator zum ersten Element zurückkehrt.

Proxy zwischenspeichern


Mocker kann im Caching-Proxy-Modus arbeiten. Das heißt, wenn ein Dienst eine Anfrage von einem Client empfängt, entnimmt er die Adresse des Hosts, auf dem sich der reale Server befindet, und das Schema (zur Bestimmung des Protokolls). Dann nimmt es die empfangene Anfrage (mit all ihren Headern, wenn die Methode eine Authentifizierung erfordert, ist es in Ordnung, dass Ihre Authorization: Bearer ... übertragen wird) und schneidet die Serviceinformationen daraus (derselbe host und das selbe scheme ) aus und sendet die Anfrage an den realen Server.

Nach Erhalt der Antwort mit dem 200. Code speichert Mocker die Antwort in der Mock-Datei (ja, Sie können sie dann kopieren oder ändern) und gibt an den Client zurück, was er vom realen Server erhalten hat. Darüber hinaus wird die Datei nicht nur an einem zufälligen Ort gespeichert, sondern auch so organisiert, dass Sie sie manuell bearbeiten können. Mocker sendet beispielsweise eine Anfrage an die folgende URL: hostname.dom/main/products/loans/info . Dann wird ein hostname.dom Ordner erstellt, und in diesem wird ein Hauptordner erstellt, in dem sich ein Produktordner befindet.

Um doppelte Mocks zu vermeiden, wird der Name auf Basis der http-Methode (GET, PUT ...) und eines Hashes aus dem Antworttext des realen Servers gebildet . In diesem Fall wird eine bestimmte Antwort einfach überschrieben, wenn bereits eine falsche Antwort vorliegt.

Diese Funktion kann für jede Anforderung einzeln aktiviert werden. Fügen Sie dazu der Anfrage drei Header hinzu:

 X-Mocker-Redirect-Is-On: "true", X-Mocker-Redirect-Host: "hostaname.ex:1234", X-Mocker-Redirect-Scheme: "http" 

Explizite Angabe des Pfades zu den Mocks


Manchmal möchten Sie, dass Mocker nur die Mokas zurückgibt, die wir möchten, und nicht alle, die im Projekt enthalten sind.

Besonders relevant für Tester. Es wäre für sie praktisch, für jeden der Testfälle einen vorbereiteten Satz von Mokas zu haben. Und dann wählt QA während des Tests nur den Ordner aus, den es benötigt, und arbeitet leise, da keine Geräusche mehr von den Mocks von Drittanbietern zu hören sind.

Das ist jetzt möglich. Um diese Funktion zu aktivieren, müssen Sie einen speziellen Header verwenden:

 X-Mocker-Specific-Path: path 

Lassen Sie beispielsweise Mocker eine solche Ordnerstruktur im Stammverzeichnis haben

 root/ block_card_test_case/ mocks.... main_test_case/ blocked_test_case/ mocks... 

Wenn Sie einen Testfall über gesperrte Karten ausführen müssen, dann
X-Mocker-Specific-Path: block_card_test_case
Wenn Sie einen Testfall ausführen müssen, der mit dem Sperren des Hauptbildschirms zusammenhängt, dann
X-Mocker-Specific-Path: main_test_case/blocked_test_case

Schnittstelle


Zuerst haben wir mit Mokas direkt über ssh gearbeitet, aber mit der Zunahme der Anzahl von Mokas und Benutzern haben wir auf eine bequemere Option umgestellt. Jetzt verwenden wir CloudCommander.
Im Docker-Compose-Beispiel wird eine Bindung zum Mocker-Container hergestellt.

Es sieht ungefähr so ​​aus:



Nun, der Bonus ist ein Web-Editor, mit dem Sie Moki direkt über den Browser hinzufügen / ändern können.



Dies ist auch eine vorübergehende Lösung. In den Plänen, von der Arbeit mit Moks über das Dateisystem auf irgendeine Datenbank zu verzichten. Dementsprechend ist es möglich, die Mokas selbst von der GUI zu dieser DB zu steuern.

Bereitstellung


Die einfachste Methode zum Bereitstellen von Mocker ist die Verwendung von Docker. Darüber hinaus wird durch die Bereitstellung des Dienstes über den Docker automatisch eine webbasierte Schnittstelle bereitgestellt, über die die Arbeit mit Mokas bequemer ist. Dateien, die für die Bereitstellung über Docker benötigt werden, befinden sich im Repository.

Wenn Ihnen diese Option jedoch nicht zusagt, können Sie den Service unabhängig von der Quelle zusammenstellen. Genug dafür:

 git clone https://github.com/LastSprint/mocker.git cd mocker go build . 

Dann müssen Sie eine Konfigurationsdatei ( Beispiel ) schreiben und den Dienst starten:

 mocker config.json 

Bekannte Probleme


  • Nach jeder neuen Datei müssen Sie curl mockerhost.dom/update_models damit der Dienst die Dateien erneut liest. Ich habe keine schnelle und elegante Möglichkeit gefunden, es anders zu aktualisieren
  • Manchmal treten in CloudCommander Fehler auf (oder ich habe etwas falsch gemacht), und die Bearbeitung von Moki, die über die Weboberfläche erstellt wurden, ist nicht möglich. Es wird durch Löschen des Browser-Cache behandelt.
  • Der Dienst funktioniert nur mit application/json . Die Pläne unterstützen die form-url-encoding .

Zusammenfassung


Mocker ist ein Webdienst, der die Probleme bei der Entwicklung von Client-Server-Anwendungen löst, wenn der Server aus irgendeinem Grund nicht bereit ist.

Mit dem Dienst können Sie viele verschiedene Mocks zu einer einzelnen URL erstellen, Request und Response durch explizite Angabe von Parametern in der URL miteinander verbinden oder den erwarteten Anforderungshauptteil direkt festlegen. Der Dienst verfügt über eine webbasierte Oberfläche, die das Leben der Benutzer erheblich vereinfacht.

Jeder Benutzer des Dienstes kann unabhängig den erforderlichen Endpunkt und die von ihm benötigte Anforderung hinzufügen. In diesem Fall ist es auf dem Client ausreichend, die Konstante durch die Hostadresse zu ersetzen, um zu einem echten Server zu wechseln.

Ich hoffe, dieser Artikel wird Menschen helfen, die unter ähnlichen Problemen leiden, und vielleicht werden wir zusammenarbeiten, um dieses Tool zu entwickeln.

GitHub-Repository .

Source: https://habr.com/ru/post/de477506/


All Articles