Kundenspezifische Instrumente: Wenn der Wegweiser nicht ausreicht

Instruments for Apples Xcode ist ein Tool zur Analyse der Leistung einer iOS-Anwendung. Sie werden zum Sammeln und Anzeigen von Daten verwendet, die beim Debuggen von Code benötigt werden. Im vergangenen Jahr hat Apple Custom Instruments eingeführt. Dies ist eine Gelegenheit, den Standardsatz von Tools für die Profilerstellung von Anwendungen zu erweitern. Wenn vorhandene Tools nicht ausreichen, können Sie selbst neue erstellen. Sie erfassen, analysieren und zeigen die Daten nach Bedarf an.

Ein Jahr ist vergangen, und es gibt fast keine neuen öffentlichen Tools und Informationen zu ihrer Erstellung im Netzwerk. Deshalb haben wir uns entschlossen, die Situation zu korrigieren und zu teilen, wie wir unser eigenes benutzerdefiniertes Instrument erstellt haben, das den Grund für die schwache Isolation von Komponententests ermittelt. Es basiert auf der Wegweisertechnologie (darüber haben wir im vorherigen Artikel geschrieben ) und ermöglicht es Ihnen, schnell und genau zu bestimmen, wo der Test blinkt.



Theoretisches Minimum


Um ein neues Tool für Xcode zu erstellen, müssen Sie zwei theoretische Blöcke verstehen. Für diejenigen, die es selbst herausfinden wollen, werden wir sofort die notwendigen Links geben:


Im Übrigen finden Sie unten eine kurze Zusammenfassung der erforderlichen Themen.

Wählen Sie zuerst Datei -> Neu -> Projekt -> macOS-Kategorie -> Instrumente. Das erstellte Projekt enthält eine Datei mit der Erweiterung .instrpkg, in der ein neues Tool deklarativ im XML-Format deklariert wird. Machen wir uns mit den Markup-Elementen vertraut:

WasAttributeBeschreibung
Datenschemata
Intervallschema, Punktschema usw.
Beschreibt die Datenstruktur als Tabelle wie SQL-Schemata. Schemata werden in anderen Markup-Elementen verwendet, um den Datentyp am Eingang und Ausgang des Modells zu bestimmen, beispielsweise bei der Beschreibung eines Mappings (UI).
Datenschemas importieren
Import-Schema
Importieren Sie vorgefertigte Schemata. Sie können Datenstrukturen verwenden, die von Apple definiert wurden.
Werkzeugmodell
Modellierer
Ordnet das Tool einer CLP-Datei zu, in der die Logik des Tools definiert ist, und kündigt das erwartete Datenschema bei der Eingabe und Ausgabe des Modells an.
Werkzeugbeschreibung
Instrument
Beschreibt das Datenmodell und bestimmt, wie Ereignisse in der Benutzeroberfläche angezeigt werden. Das Datenmodell wird mit den Attributen create-table, create-parameter usw. beschrieben. Werkzeugdiagramme werden durch Diagrammattribute definiert, und die Teiletabelle wird durch Liste, Erzählung usw. definiert.

Wenn wir die Logik des neuen Tools ergänzen möchten, erstellen Sie eine CLP-Datei mit CLIPS-Code. Grundlegende Sprachentitäten:

  • "Fakt" ist ein bestimmtes Ereignis, das mit dem Befehl assert im System registriert wird.
  • "Regel" ist ein if-Block mit einer bestimmten Syntax, die eine Bedingung enthält, unter der eine Reihe von Aktionen ausgeführt wird.

Welche Regeln und in welcher Reihenfolge aktiviert werden, bestimmt der CLIPS selbst anhand der eingehenden Fakten, der Prioritäten der Regeln und des Konfliktlösungsmechanismus.

Die Sprache unterstützt die Erstellung von Datentypen basierend auf Grundelementen, die Verwendung von arithmetischen, logischen Operationen und Funktionen. Sowie vollwertige objektorientierte Programmierung (OOP) mit der Definition von Klassen, Senden von Nachrichten, Mehrfachvererbung.

Betrachten Sie die grundlegende Syntax einer Sprache, mit der Sie Logik für benutzerdefinierte Tools erstellen können.

1. Um eine fact zu erstellen, verwenden Sie das assert Konstrukt:

 CLIPS> (assert (duck)) 

So erhalten wir den duck in der Faktentabelle, der mit dem Befehl fact angezeigt werden kann:

 CLIPS> (facts) 

Verwenden Sie den Befehl zum retract um die Tatsache zu beseitigen: (retract duck)

2. Um eine rule zu erstellen, verwenden Sie das defrule Konstrukt:

 CLIPS> (defrule duck) —     duck (animal-is duck)</i> —  animal-is duck     => (assert (sound-is quack))) —     sound-is quack 

3. Zum Erstellen und Verwenden von Variablen wird die folgende Syntax verwendet (vor dem Variablennamen steht ein Pflichtzeichen "?"):

 ?<variable-name> 

4. Sie können neue Datentypen erstellen mit:

 CLIPS> (deftemplate prospect (slot name (type STRING) (default ?DERIVE)) (slot assets (type SYMBOL) (default rich)) (slot age (type NUMBER) (default 80))) 

Daher haben wir eine Struktur mit dem Namen "Interessent" und den drei Attributen "Name", "Assets" und "Alter" des entsprechenden Typs sowie einem Standardwert definiert.

5. Arithmetische und logische Operationen haben eine Präfixsyntax. Das heißt, um 2 und 3 hinzuzufügen, müssen Sie die folgende Konstruktion verwenden:

 CLIPS> (+ 2 3) 

Oder um zwei Variablen x und y zu vergleichen:

 CLIPS> (> ?x ?y) 

Praktisches Beispiel


In unserem Projekt verwenden wir die OCMock- Bibliothek, um Stub-Objekte zu erstellen. Es gibt jedoch Situationen, in denen ein Mok länger lebt als der Test, für den er erstellt wurde, und die Isolation anderer Tests beeinflusst. Dies führt zum „Blinken“ (Instabilität) von Unit-Tests. Um die Lebensdauer von Tests und Verspottungen zu verfolgen, werden wir unser eigenes Tool erstellen. Das Folgende ist ein Algorithmus von Aktionen.

Schritt 1. Markup für Wegweiserereignisse erstellen


Um problematische Moxes zu erkennen, werden zwei Kategorien von Intervallereignissen benötigt - der Zeitpunkt der Erstellung und Zerstörung des Moxas, die Start- und Endzeit des Tests. Um diese Ereignisse OCMock die OCMock Bibliothek auf und OCMock Sie sie mit einem signpost in den Methoden init und stopMocking der Klasse stopMocking .





Gehen Sie als Nächstes zum untersuchten Projekt und führen Sie das Markup in Unit-Tests, setUp und tearDown :



Schritt 2. Erstellen Sie ein neues Werkzeug aus der Instrumentenpaketvorlage




Zunächst bestimmen wir den Datentyp der Eingabe. Dazu importieren .instrpkg das signpost in die signpost . Jetzt fallen Ereignisse, die vom signpost erstellt wurden, in das Tool:



Als nächstes bestimmen wir den Datentyp in der Ausgabe. In diesem Beispiel werden simultane Ereignisse ausgegeben. Jede Veranstaltung hat eine Zeit und eine Beschreibung. Deklarieren Sie dazu das Schema:



Schritt 3. Wir beschreiben die Logik des Werkzeugs


Wir erstellen eine separate Datei mit der Erweiterung .clp , in der wir die Regeln mithilfe der CLIPS-Sprache festlegen. modeler Sie den modeler hinzu, um dem neuen Tool mitzuteilen, in welcher Datei die Logik definiert ist:



Geben Sie in diesem Block mithilfe des production-system den relativen Pfad zur Datei mit der Logik an. In den Attributen output und required-input definieren required-input die Datenschemata für Eingabe bzw. Ausgabe.



Schritt 4. Wir beschreiben die Besonderheiten der Präsentation des Tools (UI).


In der .instrpkg Datei muss das Tool selbst beschrieben werden, .instrpkg die Ergebnisse werden .instrpkg . Erstellen Sie eine Tabelle für die Daten im Attribut " create-table Verwendung des zuvor deklarierten schema-ref detected-mocks-narrative im Attribut " schema-ref . Und richten Sie die Art der Informationsausgabe ein - narrativ (beschreibend):



Schritt 5. Wir schreiben den Logikcode


.clp wir mit der .clp Datei fort, in der die Logik des Expertensystems definiert ist. Die Logik lautet wie folgt: Wenn sich die Startzeit des Tests mit dem Intervall des Lebens des Moka überschneidet, glauben wir, dass dieser Mok aus einem anderen Test „stammt“ - was die Isolation des aktuellen Unit-Tests verletzt. Um schließlich ein Ereignis mit interessanten Informationen zu erstellen, müssen Sie die folgenden Schritte ausführen:

1. Definieren Sie die Strukturen mock und unitTest mit Feldern - dem Zeitpunkt des Ereignisses, der Ereigniskennung, dem Namen des Tests und der Klasse des Mok.



2. Wir definieren die Regeln, die Fakten mit den Typen mock und unitTest basierend auf den eingehenden Ereignissen des signpost erstellen:



Diese Regeln können wie folgt gelesen werden: Wenn wir bei der Eingabe einen Fakt vom Typ os-signpost mit dem gewünschten subsystem , der gewünschten category , dem gewünschten name und dem gewünschten event-type , erstellen Sie einen neuen Fakt mit dem oben definierten Typ (unitTest oder mock) und füllen Sie ihn mit Werten. Hierbei ist zu beachten, dass bei CLIPS zwischen Groß- und Kleinschreibung unterschieden wird und die Werte für Subsystem, Kategorie, Name und Ereignistyp mit den Werten im Code des untersuchten Projekts übereinstimmen müssen.



Variablen von Wegweiserereignissen werden wie folgt übergeben:



3. Wir definieren die Regeln, die abgeschlossene Ereignisse freigeben (sie sind redundant, da sie das Ergebnis nicht beeinflussen).



Schritt 6. Definieren Sie die Regel, die die Ergebnisse generiert.


Sie können die Regel so lesen.

Wenn

1) es gibt unitTest und mock;

2) in diesem Fall erfolgt der Beginn des Tests später als der vorhandene Moka;

3) es gibt eine Tabelle zum Speichern von Ergebnissen mit dem Schema der erkannten Verspottungserzählung;

dann

4) einen neuen Datensatz erstellen;

5) mit der Zeit ausfüllen;

6) ... und eine Beschreibung.



Als Ergebnis sehen wir das folgende Bild, wenn Sie das neue Tool verwenden:



Der Quellcode für ein benutzerdefiniertes Instrument und ein Beispielprojekt für die Verwendung des Instruments können auf GitHub angezeigt werden.

Tool-Debugging


Der Debugger wird zum Debuggen benutzerdefinierter Tools verwendet.



Er erlaubt

1. Siehe kompilierten Code basierend auf der Beschreibung in instrpkg.
2. Sehen Sie sich detaillierte Informationen darüber an, was zur Laufzeit mit dem Tool passiert.



3. Zeigen Sie eine vollständige Liste und Beschreibung der Systemdatenschemata an, die als Eingabe in neue Tools verwendet werden können.



4. Führen Sie beliebige Befehle in der Konsole aus. Zeigen Sie beispielsweise eine Liste von Regeln mit dem Befehl list-defrules oder Fakten mit dem Befehl fact an



Einrichtung auf dem CI-Server


Sie können Tools über die Befehlszeile ausführen, um die Anwendung während der Ausführung von Unit- oder UI-Tests auf dem CI-Server zu profilieren. So kann beispielsweise ein Speicherverlust so früh wie möglich erkannt werden. Verwenden Sie die folgenden Befehle, um Tests in der Pipeline zu profilieren:

1. Ausführen von Tools mit Attributen:

 xcrun instruments -t <template_name> -l <average_duration_ms> -w <device_udid> 

  • Dabei ist template_name der Pfad zur Vorlage mit den Werkzeugen oder der Name der Vorlage. Sie können den Befehl xcrun instruments -s ;
  • average_duration_ms - Die Aufnahmezeit in Millisekunden sollte größer oder gleich der Testlaufzeit sein.
  • device_udid - Simulator- device_udid . Sie können den Befehl xcrun Instrumente -s erhalten. Muss mit der Kennung des Simulators übereinstimmen, auf dem die Tests ausgeführt werden.

2. Ausführen von Tests auf demselben Simulator mit dem folgenden Befehl:

 xcodebuild -workspace <path_to_workspace>-scheme <scheme_with_tests> -destination <device> test-without-building 

  • Dabei ist path_to_workspace der Pfad zum Xcode-Arbeitsbereich.
  • scheme_with_tests - Schema mit Tests;
  • device - Simulator-ID.

Als Ergebnis wird im Arbeitsverzeichnis ein Bericht mit der Erweiterung .trace erstellt, der von der Anwendung Instruments oder durch Klicken mit der rechten Maustaste auf die Datei und Auswahl von Paketinhalt anzeigen geöffnet werden kann.

Schlussfolgerungen


Wir haben uns ein Beispiel für das Upgrade eines Wegweisers auf ein vollwertiges Tool angesehen und erklärt, wie es automatisch auf die "Läufe" des CI-Servers angewendet und zur Lösung des Problems "blinkender" (instabiler) Tests verwendet werden kann.

Wenn Sie sich mit den Möglichkeiten kundenspezifischer Instrumente befassen, werden Sie besser verstehen, in welchen anderen Fällen Sie die Instrumente verwenden können. Sie helfen uns beispielsweise auch dabei, die Probleme des Multithreading zu verstehen - wo und wann der thread-sichere Datenzugriff verwendet werden soll.
Das Erstellen eines neuen Tools war recht einfach. Die Hauptsache ist jedoch, dass Sie nach mehreren Tagen, in denen Sie die Mechanik und Dokumentation studiert haben, um sie heute zu erstellen, mehrere schlaflose Nächte vermeiden können, wenn Sie versuchen, Fehler zu beheben.

Quellen



Der Artikel wurde mit @regno , Anton Vlasov, einem iOS-Entwickler, geschrieben.

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


All Articles