<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://doc.expecco.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Matilk</id>
	<title>expecco Wiki (Version 26.x) - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://doc.expecco.de/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Matilk"/>
	<link rel="alternate" type="text/html" href="https://doc.expecco.de/wiki/Spezial:Beitr%C3%A4ge/Matilk"/>
	<updated>2026-08-25T19:43:03Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Expecco_API/en&amp;diff=31734</id>
		<title>Expecco API/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Expecco_API/en&amp;diff=31734"/>
		<updated>2026-08-18T10:30:31Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Interaction with Expecco (Python) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== How to Program ==&lt;br /&gt;
&lt;br /&gt;
You can write elementary actions (actions with program code) in many languages. Actions can be executed as:&lt;br /&gt;
==== Builtin Languages ====&lt;br /&gt;
Smalltalk and Javascript&amp;lt;br&amp;gt;these are executed directly inside expecco (i.e. expecco contains a compiler for those languages); when defined, they are compiled to a bytecode intermediate language and compiled to machine code when first executed (JIT - &amp;quot;just in time&amp;quot; compilation). The compilation to bytecode happens when the code is &amp;quot;accepted&amp;quot; or loaded from the &amp;quot;.ets&amp;quot; file. And jitted to machine code when first executed. Calls are fast and pin values are passed in and out by reference. These are executed with the lowest overhead.&lt;br /&gt;
&lt;br /&gt;
==== Bridged Languages ====&lt;br /&gt;
Python, Groova (Java), Ruby, NodeJS (Javascript), C, C#, Scheme, Octave (Matlab)&amp;lt;br&amp;gt;the are loaded into a running language interpreter which remains running between actions. Frameworks and packages can be loaded/imported, allowing for any existing code to be executed. Execution incurs a larger overhead compared to internally executed actions, because pin values have to be interchanged via interprocess communication mechanisms.&lt;br /&gt;
&lt;br /&gt;
==== Scripted Languages ====&lt;br /&gt;
Shell, Batch, Powershell, Python, Ruby, Octave/Matlab, TCL, etc. Basically any other language is even possible by calling it via a shell or batch script.&amp;lt;br&amp;gt;The code is stored as a script file on which an interpreter is started. For every such script action, the interpreter is started anew. Existing scripts can be called with minimal porting effort (and even automatically imported). These incur a higher call overhead.&lt;br /&gt;
&lt;br /&gt;
This document describes builtin and bridged language actions. Scripted actions are described [[ElementaryBlock_Element/en#Script_Action_Blocks | elsewhere]].&lt;br /&gt;
&lt;br /&gt;
=== Builtin Smalltalk and Javascript ===&lt;br /&gt;
Before you start programming in the builtin Smalltalk or builtin Javascript, please read the [[How_to_Program/en | &amp;quot;How to Program&amp;quot;]] document, which describes how program code is handled in expecco.&lt;br /&gt;
Unless you are familiar with the dynamics of a Smalltalk development environment, some of it may be unknown to you, and you will have more fun and be more productive, if you know the power of the tools. For the best development experience, take a look at the debugger, workspace (notepad) and data inspectors.&lt;br /&gt;
&lt;br /&gt;
The rest of this document describes the syntax and semantics of the elementary action languages. For tool usage, please read the [[How_to_Program/en | HowTo]] document.&lt;br /&gt;
&lt;br /&gt;
== expecco API ==&lt;br /&gt;
&lt;br /&gt;
The expecco API provides functions and access to the underlying class library for the use in [[Elementary Block|elementary blocks]] written in Smalltalk and JavaScript (i.e. for code which is executed inside expecco itself). This API is not available for elementary blocks written in other languages which are executed by external script engines (Shell, Batch, Python, Node.js etc.) or inside a different Java or CLR Virtual Machine (Groovy, VBScript, IronPython). However, a subset of the functions are supported as RPC (remote procedure calls) in bridged elementary actions.&lt;br /&gt;
&lt;br /&gt;
For a short introduction to the Smalltalk programming language,&lt;br /&gt;
please read the [http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk tutorial in the Smalltalk/X online manual].&lt;br /&gt;
For a full book on learning Smalltalk, read [http://live.exept.de/doc/books/JoyOfST/JoyOfST.pdf &amp;quot;The joy of Smalltalk, An introduction to Smalltalk&amp;quot; by Ivan Tomek].&lt;br /&gt;
&lt;br /&gt;
The [[#Groovy Elementary Blocks|API for Groovy elementary blocks]] is different and described below.&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Node.js actions is described [[#Node.js_.28Bridged.29_Elementary_Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Python and Jython actions is described [[#Bridged Python Elementary Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged Ruby actions is described [[#Bridged Ruby Elementary Blocks|here]].&lt;br /&gt;
&amp;lt;br&amp;gt;The API for bridged C actions is described [[#Bridged C Elementary Blocks|here]].&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Smalltalk_Elementary_Blocks&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;span id=&amp;quot;JavaScript_Elementary_Blocks&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;JavaScript and Smalltalk Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The expecco JavaScript and the Smalltalk API consist of the same functions - both call into the underlying [http://www.smalltalk-x.de Smalltalk/X] system, for which extensive documentation is available as &lt;br /&gt;
[http://live.exept.de/doc/online/english/TOP.html Online Documentation] and&lt;br /&gt;
as [http://live.exept.de/ClassDoc Class Reference].&lt;br /&gt;
&lt;br /&gt;
The Smalltalk/X language and class library are [http://wiki.squeak.org/squeak/uploads/172/standard_v1_9-indexed.pdf ANSI compatible]; therefore the official ANSI documents, Smalltalk literature and tutorials are also valuable sources of information (for example, the online tutorials you may find in youtube).&lt;br /&gt;
&lt;br /&gt;
:- If you wonder &amp;quot;why Smalltalk?&amp;quot;, you should know that [https://insights.stackoverflow.com/survey/2017#most-loved-dreaded-and-wanted Smalltalk ranked nr. 2 in a 2017 survey of &amp;quot;most loved languages&amp;quot;] - admittedly, this ranking may be subjective (in that Smalltalk programmers might be more loyal), but it should at least raise your eyebrows.&lt;br /&gt;
:- It is not among the most used languages - but that decision is usually made by people who do not even know Smalltalk or who think that language does not matter.  &lt;br /&gt;
:- If you think it is outdated, be reminded that Smalltalk has the most consistent object model and reflection facilities of all OO languages, and that modern clones like Ruby and Python only provide a subset of Smalltalk&#039;s facilities. If you don&#039;t know it, don&#039;t judge it.&lt;br /&gt;
:- The underlying virtual machine (VM) is feature rich and provides many mechanisms which are not possible in most &#039;modern&#039; languages. For example, in most (if not all) of the current languages it is not possible to interrupt a thread which blocks in a system call (eg. in a read). In none of them, are exceptions proceedable. In none of them can you interrupt other threads in any situation (again: especially not if it is inside a blocking read).&lt;br /&gt;
:- The set of integrated tools is massive in Smalltalk: full access to classes, threads, semaphores, any object&#039;s internals are all provided by graphical tools which can be opened by double clicks or via menus.&lt;br /&gt;
&lt;br /&gt;
Expecco&#039;s JavaScript is implemented by compiling JavaScript syntax to the underlying Smalltalk bytecode. It is not fully compatible with a &amp;quot;real&amp;quot; JavaScript: it is class based, and the underlying object model and class library are actually the Smalltalk/X object model and class library. Thus, expecco&#039;s JavaScript can be seen as &amp;quot;&amp;lt;I&amp;gt;a Smalltalk with JavaScript syntax&amp;lt;/I&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Please be not confused by two JavaScript-based elementary actions: the builtin JavaScript described here is executed within expecco itself whereas Node-actions are executed in a separate Node.js virtual machine. These Node actions are &amp;quot;real JavaScript&amp;quot; and are described in a separate [[#Node.js_.28Bridged.29_Elementary_Blocks |chapter below]].&lt;br /&gt;
&lt;br /&gt;
===Smalltalk / JavaScript Short Syntax Overview===&lt;br /&gt;
Expecco&#039;s builtin JavaScript and Smalltalk only differ in their syntax - semantically they are very similar:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|this&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|self&lt;br /&gt;
| the current activity (inside an elementary action)&lt;br /&gt;
|-&lt;br /&gt;
|this.&amp;lt;I&amp;gt;functionName&amp;lt;/I&amp;gt;()&lt;br /&gt;
|self &amp;lt;I&amp;gt;functionName&amp;lt;/I&amp;gt;&lt;br /&gt;
| a call without arguments&lt;br /&gt;
|-&lt;br /&gt;
|this.&#039;&#039;functionName&#039;&#039;(&#039;&#039;arg&#039;&#039;)&lt;br /&gt;
|self &#039;&#039;functionName&#039;&#039;:&#039;&#039;arg&#039;&#039;&lt;br /&gt;
| a call with one argument&lt;br /&gt;
|-&lt;br /&gt;
|this.&#039;&#039;namePart1_part2&#039;&#039;(&#039;&#039;arg1&#039;&#039;,&#039;&#039;arg2&#039;&#039;)&lt;br /&gt;
|self &#039;&#039;namePart1&#039;&#039;:&#039;&#039;arg1&#039;&#039; &#039;&#039;part2&#039;&#039;:&#039;&#039;arg2&#039;&#039;&lt;br /&gt;
| two arguments&amp;lt;br&amp;gt;Notice that in Smalltalk, the arguments are &#039;&#039;sliced&#039;&#039; into the name parts, and that the concatenation of the parts is the actual name (incl. the colons).&amp;lt;br&amp;gt;Thus, in &amp;quot;&amp;lt;code&amp;gt;x at:5 put:10&amp;lt;/code&amp;gt;&amp;quot; the name of the called method is &amp;quot;at:put:&amp;quot; and it gets two arguments: 5 and 10. Whereas &amp;quot;&amp;lt;code&amp;gt;(x at:5) put:10&amp;lt;/code&amp;gt;&amp;quot; would first send an &amp;quot;at:&amp;quot; message, then send a&amp;quot;put:&amp;quot; message to the object returned from &amp;quot;at:&amp;quot;.&amp;lt;br&amp;gt;In JavaScript, &amp;quot;:&amp;quot; is not a valid character in a function name, and a translation mechanism is applied which replaces &amp;quot;:&amp;quot; by underline, and drops the final colon.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;functionName&#039;&#039;(...)&lt;br /&gt;
| self &#039;&#039;functionName&#039;&#039;...&lt;br /&gt;
| implicit &#039;&#039;this&#039;&#039; receiver in JS&amp;lt;br&amp;gt;explicit in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;accessor&#039;&#039;&lt;br /&gt;
| self &#039;&#039;accessor&#039;&#039;&lt;br /&gt;
| slot access - implicit this receiver in JS&amp;lt;br&amp;gt;explicit in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;stat1&#039;&#039; ; &#039;&#039;stat2&#039;&#039; ;&lt;br /&gt;
| &#039;&#039;stat1&#039;&#039; . &#039;&#039;stat2&#039;&#039;&lt;br /&gt;
| statement terminator / separator&amp;lt;br&amp;gt;in ST: to &#039;&#039;&#039;separate&#039;&#039;&#039; statements&amp;lt;br&amp;gt;in JS: to &#039;&#039;&#039;terminate&#039;&#039;&#039; a statement.&amp;lt;br&amp;gt;In Smalltalk, the last period &amp;quot;.&amp;quot; inside a method or block can be and often is omitted.&lt;br /&gt;
|-&lt;br /&gt;
| if (&#039;&#039;cond&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;ifStats&#039;&#039;&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;elseStats&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;cond&#039;&#039; ifTrue:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;ifStats&#039;&#039;&amp;lt;br&amp;gt;] ifFalse:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;elseStats&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| conditional execution.&amp;lt;br&amp;gt;Notice the square brackets in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| while (&#039;&#039;cond&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| [ &#039;&#039;cond&#039;&#039; ] whileTrue:[&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| while-loop.&amp;lt;br&amp;gt;Notice the brackets around the condition in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| for (i=&#039;&#039;start&#039;&#039;; i&amp;amp;lt;=&#039;&#039;end&#039;&#039;; i++) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using i&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;end&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using i&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| counting-loop.&amp;lt;br&amp;gt;Seldom used in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| foreach (&#039;&#039;el&#039;&#039; in &#039;&#039;collection&#039;&#039;) {&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using el&#039;&#039;&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;collection&#039;&#039; do:[:el &amp;amp;#124;&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;stats using el&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
| loop over collection elements.&amp;lt;br&amp;gt;Very often used in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| function () { &#039;&#039;stats&#039;&#039; }&lt;br /&gt;
| [ &#039;&#039;stats&#039;&#039; ]&lt;br /&gt;
| an anonymous (inner) function (called &amp;quot;block&amp;quot; in ST).&amp;lt;br&amp;gt;JS: return value via explicit return&amp;lt;br&amp;gt;ST: return value is last expression&#039;s value&lt;br /&gt;
|-&lt;br /&gt;
| function (&#039;&#039;a1&#039;&#039;, &#039;&#039;a2&#039;&#039;,...) { &#039;&#039;stats&#039;&#039; }&lt;br /&gt;
| [:&#039;&#039;a1&#039;&#039; :&#039;&#039;a2&#039;&#039; ...&amp;amp;#124; &#039;&#039;stats&#039;&#039; ]&lt;br /&gt;
| in ST: blocks are references to anonymous function&lt;br /&gt;
|-&lt;br /&gt;
| var &#039;&#039;v1&#039;&#039;, &#039;&#039;v2&#039;&#039;, ... ;&lt;br /&gt;
| &amp;amp;#124; &#039;&#039;v1&#039;&#039; &#039;&#039;v2&#039;&#039; ... &amp;amp;#124;&lt;br /&gt;
| local variables inside a function (or block). Semantically, these are &amp;quot;let&amp;quot; variables (i.e. only seen in the current scope)&lt;br /&gt;
|-&lt;br /&gt;
| return &#039;&#039;expr&#039;&#039;;&lt;br /&gt;
| ^ &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| return a value.&amp;lt;br&amp;gt;In ST: a return from within a block returns the enclosing &#039;&#039;&#039;top-level&#039;&#039;&#039; method&amp;lt;br&amp;gt;In JS: a return returns from the &#039;&#039;&#039;inner&#039;&#039;&#039; function&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &#039;...&#039;&lt;br /&gt;
| String constant without c-escapes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;...&amp;quot;&amp;lt;br&amp;gt;or&amp;lt;br&amp;gt;&#039;...&#039;&lt;br /&gt;
| c&#039;...&#039;&lt;br /&gt;
| String constant with c-escapes (\n, \t, etc.)&lt;br /&gt;
|-&lt;br /&gt;
| `...${ expr1 } .. ${ expr2 } ...`&lt;br /&gt;
| e&#039;..{ expr1 } .. { expr2 } ...&#039;&lt;br /&gt;
| String with sliced in expressions (exprs will be converted to string). Also known as &#039;&#039;TemplateStrings&#039;&#039;.&lt;br /&gt;
|-&lt;br /&gt;
| 0xXXX, 0bXXX, 0XXX&lt;br /&gt;
| 0xXXX, 0bXXX, 0oXXX&amp;lt;br&amp;gt;or&amp;lt;br&amp;gt;16rXXX, 2rXXX, 8rXXX &amp;lt;br&amp;gt;(notice: 0177 is a decimal in Smalltalk, but octal in JS)&lt;br /&gt;
| Integer constants (hex, binary, octal)&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| #(el1 ... el2)&lt;br /&gt;
| literal (constant) array constructed at compile time.&amp;lt;br&amp;gt;Notice that elements are separated by spaces&lt;br /&gt;
|-&lt;br /&gt;
| [ex1 , ex2 , ... , exN]&lt;br /&gt;
| {ex1 . ex2 . ... . exN}&lt;br /&gt;
| literal (constant) array constructed at execution time.&amp;lt;br&amp;gt;Notice that in Smalltalk, expressions are separated by periods (must be, because &amp;quot;,&amp;quot; is an operator to concatenate collections)&lt;br /&gt;
|-&lt;br /&gt;
| /* ... */&lt;br /&gt;
| &amp;quot; ... &amp;quot;&lt;br /&gt;
| comment&lt;br /&gt;
|-&lt;br /&gt;
| // ...&lt;br /&gt;
| &amp;quot;/ ...&lt;br /&gt;
| end of line comment&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &amp;quot;&amp;lt;&amp;lt;TOKEN&amp;lt;br&amp;gt; ... &amp;lt;br&amp;gt;TOKEN&lt;br /&gt;
| token comment&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk Operator Precedence ====&lt;br /&gt;
Smalltalk beginners may be irritated by the missing binary operator precedence rules: in Smalltalk, all operators have the same precedence and are evaluated left to right.&amp;lt;br&amp;gt;Thus if you write: &lt;br /&gt;
 a + b * 5 &lt;br /&gt;
the JavaScript semantic is: &lt;br /&gt;
 a + (b * 5) &lt;br /&gt;
whereas in Smalltalk, it is evaluated as:&lt;br /&gt;
 (a + b) * 5&lt;br /&gt;
(i.e. left to right). &lt;br /&gt;
&lt;br /&gt;
Therefore, as a guideline (and actually a good convention), all Smalltalk binary expressions with more than one operator should be parenthesized to make the intention clear. It make clear that it is intended, that should be done even if the left-to-right order matches the mathematical precedences.&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk Operators ====&lt;br /&gt;
Another uncommon feature of the Smalltalk language is that there are only 6 keywords in the language&lt;br /&gt;
(&amp;quot;&amp;lt;code&amp;gt;self&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;thisContext&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&amp;lt;br&amp;gt;Every other word is either the name of a variable or the name of a message to be sent to an object (aka a &amp;quot;&#039;&#039;virtual function call&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;method invocation&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Every sequence of special characters (except &amp;quot;&amp;lt;code&amp;gt;:&amp;lt;/code&amp;gt;&amp;quot; (colon), &amp;quot;&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;&amp;quot; (period), &amp;quot;&amp;lt;code&amp;gt;(&amp;lt;/code&amp;gt;&amp;quot; (left), &amp;quot;&amp;lt;code&amp;gt;)&amp;lt;/code&amp;gt;&amp;quot; (right parenthesis), &amp;quot;&amp;lt;code&amp;gt;[&amp;lt;/code&amp;gt;&amp;quot; (left), &amp;quot;&amp;lt;code&amp;gt;]&amp;lt;/code&amp;gt;&amp;quot; (right bracket), &amp;lt;code&amp;gt;{&amp;lt;/code&amp;gt;&amp;quot; (left),&amp;lt;code&amp;gt;}&amp;lt;/code&amp;gt;&amp;quot; (right brace), &amp;quot;&amp;lt;code&amp;gt;:=&amp;lt;/code&amp;gt;&amp;quot; (assign), &amp;quot;&amp;lt;code&amp;gt;^&amp;lt;/code&amp;gt;&amp;quot; (return) and &amp;quot;&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;&amp;quot; (semicolon) ) is interpreted as operator (or in other words: as the name of a message/virtual function call).&lt;br /&gt;
&lt;br /&gt;
Thus, the sequences &amp;quot;&amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;=&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;&amp;lt;-&amp;lt;/code&amp;gt;&amp;quot; and especially the comma (&amp;quot;&amp;lt;code&amp;gt;,&amp;lt;/code&amp;gt;&amp;quot;) are operators which are treated like &amp;quot;&amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;-&amp;lt;/code&amp;gt;&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
Finally, message sends (&amp;quot;&#039;&#039;function calls&#039;&#039;&amp;quot;) with arguments are always written with keyword arguments. I.e. the arguments are prefixed by a keyword (which is an identifier with a colon). Smalltalk does not allow positional arguments in a message send.&lt;br /&gt;
&lt;br /&gt;
==== Calling Functions and Invoking Methods (aka &amp;quot;Sending Messages&amp;quot;) ====&lt;br /&gt;
All functions are actually implemented in Smalltalk and follow the standard Smalltalk naming conventions. The same function names are used for JavaScript. As seen above, this scheme works well for functions without or with a single argument, but requires a name translation for functions with more than one argument. This translation is done by the JavaScript compiler by replacing every colon (:) of the Smalltalk name by an underline (_) character, except for the last colon if there are more than one. Thus for example, the Smalltalk name &amp;quot;&amp;lt;code&amp;gt;at:put:&amp;lt;/code&amp;gt;&amp;quot; will be named &amp;quot;&amp;lt;code&amp;gt;at_put&amp;lt;/code&amp;gt;&amp;quot; in JavaScript.&lt;br /&gt;
&lt;br /&gt;
In JavaScript, a function-name alone (i.e. without explicit receiver) is translated into a self-send; thus &amp;quot;&amp;lt;code&amp;gt;this.foo()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;foo()&amp;lt;/code&amp;gt;&amp;quot; are equivalent.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- not recommended and bad style&lt;br /&gt;
Also, for non-argument accessor functions (getters), the empty argument list can be omitted in JavaScript; therefore, &amp;quot;foo&amp;quot; and &amp;quot;this.foo&amp;quot;, &amp;quot;foo()&amp;quot; and &amp;quot;this.foo()&amp;quot; are all equivalent.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, the JavaScript call:&lt;br /&gt;
 this.&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;quot;foo&amp;quot;)&lt;br /&gt;
is written in Smalltalk as:&lt;br /&gt;
 self &#039;&#039;&#039;environmentAt:&#039;&#039;&#039;&#039;foo&#039;&lt;br /&gt;
&lt;br /&gt;
and, to demonstrate the multi-argument translation rule, the Smalltalk code:&lt;br /&gt;
 self &#039;&#039;&#039;environmentAt:&#039;&#039;&#039;&#039;foo&#039; &#039;&#039;&#039;put:&#039;&#039;&#039;1234&lt;br /&gt;
is written in JavaScript as:&lt;br /&gt;
 this.&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039;(&amp;quot;foo&amp;quot;, 1234)&lt;br /&gt;
or (because of the implicit receiver being &amp;quot;this&amp;quot;), alternatively:&lt;br /&gt;
 &#039;&#039;&#039;environmentAt_put&#039;&#039;&#039;(&amp;quot;foo&amp;quot;, 1234)&lt;br /&gt;
&lt;br /&gt;
=== Syntax Summary ===&lt;br /&gt;
For a formal specification of the JavaScript and Smalltalk languages, see the appendixes below.&lt;br /&gt;
The following gives a rough overview over the most common syntactic constructs.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 10em&amp;quot;| this&lt;br /&gt;
|style=&amp;quot;width: 10em&amp;quot;| self&lt;br /&gt;
| the current activity&lt;br /&gt;
|-&lt;br /&gt;
| null&lt;br /&gt;
| nil&lt;br /&gt;
| a null reference (UndefinedObject)&lt;br /&gt;
|-&lt;br /&gt;
| ;&lt;br /&gt;
| .&lt;br /&gt;
| statement terminator/separator&amp;lt;br&amp;gt;In JavaScript it is a terminator, meaning that every statement (except brace-blocks) must be terminated by a semicolon.&amp;lt;br&amp;gt;In Smalltalk, it is a separator, meaning that the last statement in a block or method does not need one.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;quot;...&amp;quot;&lt;br /&gt;
| &#039;...&#039;&lt;br /&gt;
| a String constant (JavaScript allows single quotes too);&amp;lt;br&amp;gt;no C-escapes in Smalltalk&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| c&#039;...&#039;&lt;br /&gt;
| a Smalltalk String constant with c-escapes&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| e&#039;..{ expr } ..&#039;&lt;br /&gt;
| a Smalltalk String with embedded expressions (sliced-in)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #&#039;...&#039;&lt;br /&gt;
| a Symbol constant&amp;lt;br&amp;gt;(not available in JavaScript; use &amp;quot;xxx&amp;quot;.asSymbol() in JS)&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #...&lt;br /&gt;
| also a Symbol constant&amp;lt;br&amp;gt;(not available in JavaScript; use &amp;quot;xxx&amp;quot;.asSymbol() in JS)&lt;br /&gt;
|-&lt;br /&gt;
| [ el1 , el2 , ... ]&lt;br /&gt;
| #( el1 el2 ... )&lt;br /&gt;
| an Array constant&amp;lt;br&amp;gt;(elements must be constant literals)&amp;lt;br&amp;gt;Notice the separating comma in JS, but space-separated elements in Smalltalk.&amp;lt;br&amp;gt;In Smalltalk, the array is created at compile time (i.e. runtime cost is zero); the array is immutable,&amp;lt;br&amp;gt;whereas in JS it is created mutable at runtime&lt;br /&gt;
|-&lt;br /&gt;
| [ expr1 , expr2 , ... ]&lt;br /&gt;
| { expr1 . expr2 . ... }&lt;br /&gt;
| a computed Array&amp;lt;br&amp;gt;(elements are expressions)&amp;lt;br&amp;gt;notice the expression terminators in ST (periods),&amp;lt;br&amp;gt;and that &amp;quot;,&amp;quot; (comma) is an operator in ST.&amp;lt;br&amp;gt;The array is created at runtime; the array is mutable&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| #[ el1 el2 ... ]&lt;br /&gt;
| an immutable ByteArray constant&amp;lt;br&amp;gt;(not available in JavaScript)&lt;br /&gt;
|-&lt;br /&gt;
| 1234&lt;br /&gt;
| 1234&lt;br /&gt;
| an Integer constant&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0x1234&lt;br /&gt;
| 0x1234 or 16r1234&lt;br /&gt;
| a hexadecimal Integer constant (radix is 16)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0b10001010&lt;br /&gt;
| 0b10001010 or 2r10001010&lt;br /&gt;
| a binary Integer constant (radix is 2)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| 0177&lt;br /&gt;
| 8r177&lt;br /&gt;
| an octal Integer constant (radix is 8)&amp;lt;br&amp;gt;(arbitrary precision)&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| 3r10001010&lt;br /&gt;
| a ternary Integer constant (radix is 3);&amp;lt;br&amp;gt;not available in JavaScript&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &amp;amp;lt;N&amp;amp;gt;rxxxx&lt;br /&gt;
| an N-ary Integer constant (radix is N);&amp;lt;br&amp;gt;not available in JavaScript&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| ( num / den )&lt;br /&gt;
| a Fraction constant (not available in JavaScript);&amp;lt;br&amp;gt;both numerator and denominator must be integers&lt;br /&gt;
|-&lt;br /&gt;
| 1.234&amp;lt;br&amp;gt;1e5&lt;br /&gt;
| 1.234&amp;lt;br&amp;gt;1e5&lt;br /&gt;
| Floating Point constants&amp;lt;br&amp;gt;(double precision)&lt;br /&gt;
|-&lt;br /&gt;
| v = expression&lt;br /&gt;
| v := expression&lt;br /&gt;
| assignment to a variable&lt;br /&gt;
|-&lt;br /&gt;
| expr1 == expr2&lt;br /&gt;
| expr1 = expr2&lt;br /&gt;
| compare for equal value&lt;br /&gt;
|-&lt;br /&gt;
| expr1 === expr2&lt;br /&gt;
| expr1 == expr2&lt;br /&gt;
| compare for identity&amp;lt;br&amp;gt;be careful: 1.0 (the float) is NOT identical to 1 (the integer)&amp;lt;br&amp;gt;However, they are equal in value.&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.f ()&lt;br /&gt;
| rcvr f&lt;br /&gt;
| function call (always a &amp;quot;virtual function call&amp;quot;)&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.f (arg)&lt;br /&gt;
| rcvr f: arg&lt;br /&gt;
| with 1 arg&lt;br /&gt;
|-&lt;br /&gt;
| rcvr.a_b (arg1, arg2)&lt;br /&gt;
| rcvr a: arg1 b: arg2&lt;br /&gt;
| with args&amp;lt;br&amp;gt;notice the different names of the function&amp;lt;br&amp;gt;&amp;quot;a_b&amp;quot; vs.&amp;quot;a:b:&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| return;&lt;br /&gt;
| ^ self&lt;br /&gt;
| without return value&amp;lt;br&amp;gt;ST: from enclosing method;&amp;lt;br&amp;gt;JS: from current function&lt;br /&gt;
|-&lt;br /&gt;
| return expr;&lt;br /&gt;
| ^ expr&lt;br /&gt;
| with return value&amp;lt;br&amp;gt;ST: from enclosing method;&amp;lt;br&amp;gt;JS: from current function&lt;br /&gt;
|-&lt;br /&gt;
| return from execute;&lt;br /&gt;
| ^ self&lt;br /&gt;
| return from execute activity from within an inner function&lt;br /&gt;
|-&lt;br /&gt;
| ! expr&lt;br /&gt;
| expr not&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| e1 &amp;amp;&amp;amp; e2&lt;br /&gt;
| (e1 and:[ e2 ])&lt;br /&gt;
| non evaluating and&amp;lt;br&amp;gt;(e2 is not evaluated if e1 is false)&lt;br /&gt;
|-&lt;br /&gt;
| e1 &amp;amp;#124;&amp;amp;#124; e2&lt;br /&gt;
| (e1 or:[ e2 ])&lt;br /&gt;
| non evaluating or&amp;lt;br&amp;gt;(e2 is not evaluated if e1 is true)&lt;br /&gt;
|-&lt;br /&gt;
|  &lt;br /&gt;
| pin &amp;lt;- value&lt;br /&gt;
| only for output pins: writes value to the pin (same as &amp;quot;pin value(val)&amp;quot;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Syntactic Sugar ===&lt;br /&gt;
&lt;br /&gt;
Some syntactic constructs of the JavaScript language are implemented as library functions in Smalltalk. Among others, most noteworthy are conditional execution (if-the-else) and loops.&lt;br /&gt;
&lt;br /&gt;
Non-Smalltalkers should be aware that in Smalltalk all control structures are implemented as library functions (i.e. method invocations) to corresponding receiver objects. They get a block (=closure or anonymous function) as argument, which is then possibly evaluated. The Smalltalk block syntax &amp;quot;&amp;lt;code&amp;gt;[...]&amp;lt;/code&amp;gt;&amp;quot; makes this extremely convenient and easy to use.&lt;br /&gt;
&lt;br /&gt;
It is the responsibility of the Smalltalk compiler and runtime system, to care for optimized execution of such code (typically by inlining the code). However, it is still possible to put a block into a variable, to pass it as argument, or to return it as value from a method or block. Thus, in Smalltalk, variables or computed blocks may also be used as arguments to messages like &amp;quot;&amp;lt;code&amp;gt;ifTrue:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;whileTrue:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;do:&amp;lt;/code&amp;gt;&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;The JavaScript syntax for control structures is mapped to corresponding Smalltalk library functions as follows:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|if (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
|style=&amp;quot;width: 15em&amp;quot;|  (&#039;&#039;expr&#039;&#039;) ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
| Notice the square brackets&lt;br /&gt;
|-&lt;br /&gt;
|if (! &#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| if (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| if (!&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} else {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| (&#039;&#039;expr&#039;&#039;) ifFalse:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ifTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| while (&#039;&#039;expr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&#039;&#039;expr&#039;&#039;] whileTrue:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
| Notice the square brackets around the condition&lt;br /&gt;
|-&lt;br /&gt;
| for (&#039;&#039;expr1&#039;&#039;;&#039;&#039;expr2&#039;&#039;;&#039;&#039;expr3&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;expr1&#039;&#039;. [&#039;&#039;expr2&#039;&#039;] whileTrue:[&amp;lt;br&amp;gt;... .&amp;lt;br&amp;gt;&#039;&#039;expr3&#039;&#039;&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| for (var i=&#039;&#039;start&#039;&#039;; i&amp;lt;=&#039;&#039;stop&#039;&#039;; i++) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;stop&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| for (var i=&#039;&#039;start&#039;&#039;; i&amp;lt;=&#039;&#039;stop&#039;&#039;; i+=&#039;&#039;incr&#039;&#039;) {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;}&lt;br /&gt;
| &#039;&#039;start&#039;&#039; to:&#039;&#039;stop&#039;&#039; by:&#039;&#039;incr&#039;&#039; do:[:i &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} finally {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ensure:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} catch(e) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] on:Error do:[:e &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| try {&amp;lt;br&amp;gt;..&amp;lt;br&amp;gt;} catch(e) {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;} finally {&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;}&lt;br /&gt;
| [&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] on:Error do:[:e &amp;amp;#124;&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;] ensure:[&amp;lt;br&amp;gt;...&amp;lt;br&amp;gt;]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;var&#039;&#039;++&lt;br /&gt;
| &#039;&#039;var&#039;&#039; := &#039;&#039;var&#039;&#039; + 1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;var&#039;&#039;--&lt;br /&gt;
| &#039;&#039;var&#039;&#039; := &#039;&#039;var&#039;&#039; - 1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ]&lt;br /&gt;
| &#039;&#039;arr&#039;&#039; at:&#039;&#039;idx&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ]&lt;br /&gt;
| Array and Dictionary indexed fetch&amp;lt;br&amp;gt;Notice that real JavaScript uses 0-based indexing, whereas Smalltalk and expecco JavaScript is 1-based.&amp;lt;br&amp;gt;Smalltalk/X also allows the bracket notation for indexed access.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ] = &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| &#039;&#039;arr&#039;&#039; at:&#039;&#039;idx&#039;&#039; put:&#039;&#039;expr&#039;&#039;&amp;lt;br&amp;gt;&#039;&#039;arr&#039;&#039;[ &#039;&#039;idx&#039;&#039; ] := &#039;&#039;expr&#039;&#039;&lt;br /&gt;
| Array and Dictionary indexed store&amp;lt;br&amp;gt;Smalltalk/X also allows the bracket notation for indexed access.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operators ===&lt;br /&gt;
{|  Border&lt;br /&gt;
! JavaScript&lt;br /&gt;
! Smalltalk&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| %&lt;br /&gt;
| \\&amp;lt;br&amp;gt;%&lt;br /&gt;
| modulu operator&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;lt;&amp;amp;lt;&lt;br /&gt;
| leftShift:&lt;br /&gt;
| left-shift&amp;lt;br&amp;gt;negative shift count is right-shift&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;gt;&amp;amp;gt;&lt;br /&gt;
| rightShift:&lt;br /&gt;
| right-shift&amp;lt;br&amp;gt;negative shift count is left-shift&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| bitShift:&lt;br /&gt;
| left or right shift;&amp;lt;br&amp;gt;negative shift count is right-shift&amp;lt;br&amp;gt;positive is left shift&amp;lt;br&amp;gt;(not available in JavaScript)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
More details are in the [[Smalltalk Syntax Cheat Sheet]].&lt;br /&gt;
&lt;br /&gt;
=== Array Indexing ===&lt;br /&gt;
&lt;br /&gt;
A big potential pitfall is the different indexing base used in Smalltalk vs. (standard) JavaScript: in Smalltalk, array indices start at 1 and end at the array&#039;s size. In (standard) JavaScript, indices start at 0 and end at the array&#039;s size minus 1.&lt;br /&gt;
&lt;br /&gt;
This also affects some character- and substring search functions, which return 0 (zero) in Smalltalk, whereas some of the standard JavaScript functions return -1 if nothing is found.&lt;br /&gt;
&lt;br /&gt;
The following functions expect or return 0-based indices if used in JavaScript:&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;indexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;)&amp;lt;br&amp;gt;attention: there exists a corresponding Smalltalk method, which returns a 1-based index&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;)&amp;lt;br&amp;gt;attention: there exists a corresponding Smalltalk method, which returns a 1-based index&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;indexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039;)&amp;lt;br&amp;gt;the corresponding Smalltalk method &amp;quot;&amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt;&#039;&#039;element&#039;&#039; &amp;lt;code&amp;gt;startingAt:&amp;lt;/code&amp;gt;&#039;&#039;startIndex&#039;&#039;&amp;quot; uses 1-based indices&lt;br /&gt;
* &#039;&#039;collection&#039;&#039;.&amp;lt;code&amp;gt;&#039;&#039;&#039;lastIndexOf:&#039;&#039;&#039;&amp;lt;/code&amp;gt;(&#039;&#039;element&#039;&#039;, &#039;&#039;startIndex&#039;&#039;)&amp;lt;br&amp;gt;ditto&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
We admit that this is a little confusing at times, but there is no easy solution to this: and we decided to neither change the Smalltalk nor the JavaScript scripting languages inside expecco.&lt;br /&gt;
&lt;br /&gt;
To make your intentions explicit, you can use variants of the &amp;quot;&amp;lt;code&amp;gt;indexOf&amp;quot;/&amp;quot;lastIndexOf&amp;lt;/code&amp;gt;&amp;quot; functions which make these implicit differences more explicit: &amp;quot;&amp;lt;code&amp;gt;indexOf0()&amp;lt;/code&amp;gt;&amp;quot; / &amp;quot;&amp;lt;code&amp;gt;lastIndexOf0()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;indexOf1()&amp;lt;/code&amp;gt;&amp;quot; / &amp;quot;&amp;lt;code&amp;gt;lastIndexOf1()&amp;lt;/code&amp;gt;&amp;quot; are available for both languages.&lt;br /&gt;
&lt;br /&gt;
Shame on us:&amp;lt;br&amp;gt;&lt;br /&gt;
the above array indexing behavior was changed for &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; between 2.7 and 2.8 (due to a missing translation, the 2.7 versions used 1-based indices in both languages).&lt;br /&gt;
This leads to a problem, if you run any old 2.7 suite in newer expecco versions without reimporting the StandardLibrary or if you used those functions in your own elementary code.&lt;br /&gt;
To avoid a need to touch those old suites, we have added a backward-bug-compatibility mode, which is described in a separate note of the release notes.&lt;br /&gt;
&lt;br /&gt;
=== Inner Functions ===&lt;br /&gt;
==== Inner Functions in JavaScript ====&lt;br /&gt;
&lt;br /&gt;
It is possible to create functions within the elementary block&#039;s code. This example shows how to do so:&lt;br /&gt;
 execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    function f(arg1, arg2) {&lt;br /&gt;
      return(arg1 + arg2);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
An inner function &amp;quot;f&amp;quot; is created with two arguments (&amp;quot;arg1&amp;quot; and &amp;quot;arg2&amp;quot;), which returns the sum of both. The function is called like this:&lt;br /&gt;
   f(3,5)&lt;br /&gt;
Inner functions can be used for example to filter specific elements from collections, as in:&lt;br /&gt;
   function isEven(n) { return n.even(); }&lt;br /&gt;
 &lt;br /&gt;
   var numbers = [1,2,3,4,5,6,7];&lt;br /&gt;
   var evenNumbers = numbers.select( isEven );&lt;br /&gt;
&lt;br /&gt;
Inner functions are &#039;&#039;&#039;first class objects&#039;&#039;&#039;: they can be stored in variables, collections, passed as argument or returned from functions. They can even be passed to other blocks via input- and output pins or via environment variables. Functions can be anonymous; the above example could also be written as:&lt;br /&gt;
 execute() {&lt;br /&gt;
    var f;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    f = function (arg1, arg2) {&lt;br /&gt;
      return(arg1 + arg2);&lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
(notice the missing function name after the &amp;quot;function&amp;quot; keyword).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notice, that there is a difference in the behavior of the return statement between JavaScript inner functions and Smalltalk blocks:&lt;br /&gt;
a JavaScript &amp;quot;return&amp;quot; statement inside an inner function returns from that inner function only, whereas a return in Smalltalk always returns from the outer-most method.&lt;br /&gt;
&lt;br /&gt;
To return from the outermost function in JavaScript, use the &amp;quot;&amp;lt;CODE&amp;gt;return from &amp;amp;lt;&#039;&#039;fnName&#039;&#039;&amp;amp;gt;&amp;lt;/CODE&amp;gt;&amp;quot; statement form.&lt;br /&gt;
&lt;br /&gt;
In expecco, where the outermost function is always named &amp;quot;&#039;&#039;execute&#039;&#039;&amp;quot;, write:&lt;br /&gt;
    execute() {&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
       function myFunction() {&lt;br /&gt;
           &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
           return from execute;&lt;br /&gt;
       }&lt;br /&gt;
       &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;...&amp;lt;/span&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
(notice that the execute function is not supposed to return a value)&lt;br /&gt;
&lt;br /&gt;
===== Lambda Expressions in JavaScript =====&lt;br /&gt;
&lt;br /&gt;
JavaScript functions can also be written in a slightly shorter lambda notation as:&lt;br /&gt;
    (arg1, ... argN) =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
or (with a single argument) as:&lt;br /&gt;
    arg =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
or (without arguments) as:&lt;br /&gt;
    () =&amp;gt; { statement; ... return expression; }&lt;br /&gt;
and results in a function object comparable to:&lt;br /&gt;
    function (arg1, ... argN) { statement; ... return expression; }&lt;br /&gt;
&lt;br /&gt;
The function&#039;s body may also be a single expression (without braces), as:&lt;br /&gt;
    arg =&amp;gt; expression&lt;br /&gt;
For example:&lt;br /&gt;
    aCollection.map( el =&amp;gt; el ** 2 )&lt;br /&gt;
returns a collection of squared numbers,&lt;br /&gt;
the same as the corresponding Smalltalk code:&lt;br /&gt;
    aCollection map:[:el | el ** 2 ]&lt;br /&gt;
This is plain &amp;quot;syntactic sugar&amp;quot; - it does not give any new semantic functionality, but makes the code shorter and possibly easier to read.&lt;br /&gt;
&lt;br /&gt;
==== Inner Functions in Smalltalk (Blocks) ====&lt;br /&gt;
&lt;br /&gt;
In Smalltalk, inner functions are called &amp;quot;&#039;&#039;block&#039;&#039;&amp;quot;, and are defined as:&lt;br /&gt;
   f := [:arg1 :arg2 | arg1 + arg2 ].&lt;br /&gt;
This block can be called by sending at a &amp;quot;&amp;lt;code&amp;gt;value:value:&amp;lt;/code&amp;gt;&amp;quot; message (i.e. one &amp;quot;&amp;lt;code&amp;gt;value:&amp;lt;/code&amp;gt;&amp;quot; for each argument) &amp;lt;sup&amp;gt;(1)&amp;lt;/sup&amp;gt;:&lt;br /&gt;
   f value:3 value:5&lt;br /&gt;
or by passing an array of argument values with &amp;quot;&amp;lt;code&amp;gt;valueWithArguments:&amp;lt;/code&amp;gt;&amp;quot; as in:&lt;br /&gt;
   args := #(3 5).   &amp;quot;/ an array constant&lt;br /&gt;
   f valueWithArguments:args&lt;br /&gt;
or:&lt;br /&gt;
   args := { 3 . 5 }. &amp;quot;/ a computed array&lt;br /&gt;
   f valueWithArguments:args&lt;br /&gt;
&lt;br /&gt;
The returned value is the value of the last expression inside the block. Thus, blocks can contain multiple expressions separated by a period:&lt;br /&gt;
   f := [:arg1 :arg2 | &lt;br /&gt;
             Transcript showCR: e&#039;my first arg is: {arg1}&#039;.&lt;br /&gt;
             Transcript showCR: e&#039;my second arg is: {arg2}&#039;.&lt;br /&gt;
             arg1 + arg2 &amp;quot;/ the block&#039;s return value&lt;br /&gt;
        ].&lt;br /&gt;
This is in contrast to a JavaScript inner function, where an explicit &amp;quot;return&amp;quot; statement is needed. The return value of JavaScript inner function without an explicit return will be void.&lt;br /&gt;
Therefore, the above inner function in JavaScript has to have a return:&lt;br /&gt;
   f = function(arg1, arg2) { &lt;br /&gt;
             Transcript.showCR(&#039;my first arg is: &#039;+arg1);&lt;br /&gt;
             Transcript showCR(&#039;my second arg is: &#039;+arg2);&lt;br /&gt;
             return (arg1 + arg2); // the function&#039;s return value&lt;br /&gt;
       };&lt;br /&gt;
&lt;br /&gt;
Blocks without argument are defined as:&lt;br /&gt;
   f := [ Transcript showCR:&#039;blabla: Euler was great&#039; ].&lt;br /&gt;
and invoked with a simple &amp;quot;&amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
In both JavaScript and Smalltalk code, it is an error to invoke an inner function/block with a wrong number of arguments &amp;lt;sup&amp;gt;(2)&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Smalltalk blocks and JavaScript inner functions can be used interchangeable - i.e. it is possible to pass a JS inner function to a collection method such as &amp;quot;&amp;lt;code&amp;gt;collect:&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;select:&amp;lt;/code&amp;gt;&amp;quot;. It is also possible, to pass either via input/output pins to other activities (which is not considered good style, as it could make the program quite hard to understand, if not used with caution).&lt;br /&gt;
&lt;br /&gt;
Notice again, that the behavior of the Smalltalk return (&amp;quot;^&amp;quot;) is different from a JavaScript return (&amp;quot;&#039;&#039;return-Statement&#039;&#039;&amp;quot;) inside inner functions. The JavaScript return returns a value from the inner function, whereas the Smalltalk return forces a return from the containing method (the block&#039;s &amp;quot;execute&amp;quot; method). The Smalltalk return always behaves like the &amp;quot;&amp;lt;I&amp;gt;return from execute&amp;lt;/I&amp;gt;&amp;quot; JavaScript special form.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt; Smalltalk/X allows for a non-standard block evaluation message using the &amp;quot;normal&amp;quot; parentheses notation. I.e. you can call a block with its arguments in parentheses as in &amp;quot;&amp;lt;code&amp;gt;f(1, 2, 3)&amp;lt;/code&amp;gt;. This is syntactic sugar for the standard &amp;lt;code&amp;gt;f value:1 value:2 value:3&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt; in Smalltalk, you can define &amp;quot;&#039;&#039;varargs blocks&#039;&#039;&amp;quot; with the &amp;quot;&amp;lt;code&amp;gt;asVarArgBlock&amp;lt;/code&amp;gt;&amp;quot; message. The block will then receive its arguments as a vector, and fetch them using collection protocol (i.e. &amp;quot;size&amp;quot;, &amp;quot;at:&amp;quot; or enumeration messages like &amp;quot;do:&amp;quot;). For example,&lt;br /&gt;
 b := [:args | Transcript showCR: e&#039;my arguments are {args}&#039; ] asVarArgBlock&lt;br /&gt;
can be called with any number of arguments.&lt;br /&gt;
&lt;br /&gt;
==== Example uses for Inner Functions ====&lt;br /&gt;
&lt;br /&gt;
In Smalltalk, blocks are very often used when enumerating collections.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, code corresponding to a C# 3.0 collection &amp;quot;&amp;lt;code&amp;gt;select (where(x =&amp;gt; ...))&amp;lt;/code&amp;gt;&amp;quot; is written in Smalltalk as:&lt;br /&gt;
    |names namesStartingWithA|&lt;br /&gt;
 &lt;br /&gt;
    names := #( &#039;Alice&#039; &#039;Ann&#039; &#039;Bob&#039; &#039;Mallory&#039; ).&lt;br /&gt;
    namesStartingWithA := names select:[:n | n startsWith:&#039;A&#039;].&lt;br /&gt;
&lt;br /&gt;
or in JavaSript as:&lt;br /&gt;
    var names, namesStartingWithA;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    namesStartingWithA = names.select( function(n) { n.startsWith(&amp;quot;A&amp;quot;); } );&lt;br /&gt;
or alternative using lambda expressions as:&lt;br /&gt;
    var names, namesStartingWithA;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    namesStartingWithA = names.select( n =&amp;gt; n.startsWith(&amp;quot;A&amp;quot;) );&lt;br /&gt;
&lt;br /&gt;
To find the first element in a collection, for which some condition is true, use:&lt;br /&gt;
    |names firstNameContainingAnO|&lt;br /&gt;
 &lt;br /&gt;
    names := #( &#039;Alice&#039; &#039;Ann&#039; &#039;Bob&#039; &#039;Mallory&#039; ).&lt;br /&gt;
    firstNameContainingAnO:= names detect:[:n | n includesString:&#039;o&#039;].&lt;br /&gt;
&lt;br /&gt;
or in JavaSript as:&lt;br /&gt;
    var names, firstNameContainingAnO;&lt;br /&gt;
 &lt;br /&gt;
    names = [ &amp;quot;Alice&amp;quot; , &amp;quot;Ann&amp;quot; , &amp;quot;Bob&amp;quot; , &amp;quot;Mallory&amp;quot; ];&lt;br /&gt;
    firstNameContainingAnO = names.detect( function(n) { n.includesString(&amp;quot;o&amp;quot;); } );&lt;br /&gt;
&lt;br /&gt;
For more information on the Smalltalk syntax, see [[http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk Basics]] in the [[http://live.exept.de/doc/online/english/getstart/tutorial.html Smalltalk Online Tutorial]].&lt;br /&gt;
&lt;br /&gt;
=== Builtin Data Types ===&lt;br /&gt;
&lt;br /&gt;
The builtin types below and user defined primary types are mapped to corresponding classes of the underlying Smalltalk runtime system.&lt;br /&gt;
An introductory overview and links to the detailed documentation of individual classes is found in the&lt;br /&gt;
[http://live.exept.de/doc/online/english/classDoc/TOP.html Smalltalk Class Documentation] of the [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation]. The following gives a rough summary of the main concepts. A good entry point for further learning is the [http://live.exept.de/doc/online/english/overview/basicClasses/TOP.html Smalltalk/X Basic Classes Overview Document], which provides links to the most heavily used classes and more detailed information.&lt;br /&gt;
&lt;br /&gt;
==== Numeric Types ====&lt;br /&gt;
&lt;br /&gt;
The underlying numeric type implementation supports multiple number representations. These can be used transparently in mixed-operations, and values are automatically converted as required. For example, the division of two integers returns another integer iff the division does not produce a remainder. Otherwise, a fraction object is returned.&lt;br /&gt;
Although very very rarely required in practice,&lt;br /&gt;
values can be converted explicitly, via one of the &amp;quot;&amp;lt;code&amp;gt;asXXX&amp;lt;/code&amp;gt;&amp;quot; messages:&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat64()&amp;lt;/code&amp;gt; - to convert to a double precision IEEE 64bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat32()&amp;lt;/code&amp;gt; - to convert to a single precision IEEE 32bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat80()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 80bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat128()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 128bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asInteger()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;asFraction()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;asScaledDecimal(scale)&amp;lt;/code&amp;gt;&lt;br /&gt;
the older API is still supported, but less self explanatory:&lt;br /&gt;
* &amp;lt;code&amp;gt;asFloat()&amp;lt;/code&amp;gt; - to convert to a double precision IEEE 64bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asShortFloat()&amp;lt;/code&amp;gt; - to convert to a single precision IEEE 32bit float&lt;br /&gt;
* &amp;lt;code&amp;gt;asLongFloat()&amp;lt;/code&amp;gt; - to convert to an extended precision IEEE 80bit float&lt;br /&gt;
&lt;br /&gt;
Thus, if you want to avoid fractions (why would you?), process the result of an integer division using one of the &amp;lt;code&amp;gt;asFloat()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;truncated()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;floor()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ceiling()&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;rounded()&amp;lt;/code&amp;gt; functions. But be aware that fractions provide an exact result, whereas float arithmetic is inherently imprecise, rounds on the the last bit and that such rounding errors accumulate.&lt;br /&gt;
&lt;br /&gt;
===== Integer =====&lt;br /&gt;
&lt;br /&gt;
This represents arbitrary precision integral numbers. Conversion and memory allocation is completely automatic.&lt;br /&gt;
&amp;lt;br&amp;gt;Thus, without danger of overflow, you can write:&lt;br /&gt;
 x = 1234567890 * 12345678901234567890 / 10&lt;br /&gt;
to get: &lt;br /&gt;
 1524157875171467887501905210&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
 x = 100.factorial();&lt;br /&gt;
to get the huge number:&lt;br /&gt;
 933262154439441526816992388562667004907159682643816214685929638952175999932299156089&lt;br /&gt;
 41463976156518286253697920827223758251185210916864000000000000000000000000&lt;br /&gt;
&lt;br /&gt;
Small integer values (smaller than 32 or 64bit, depending in the underlying hardware&#039;s native word length) are stored more efficiently than large integers - however, the conversion and representation as used by the system is transparent and automatic.&lt;br /&gt;
The same is true for mixed mode arithmetic between small and large integers.&lt;br /&gt;
&lt;br /&gt;
Occasionally it is required to perform modulo arithmetic in 32 or 64bit; for example to reproduce or check values as generated by C or Java programs. For this, use methods from the &amp;quot;&#039;&#039;special modulo&#039;&#039;&amp;quot; category, such as &amp;quot;&amp;lt;code&amp;gt;add_32()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;add_32u()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;mul_32()&amp;lt;/code&amp;gt;&amp;quot; etc. Use a [[Tools_ClassBrowser|class browser]] to find those methods.&lt;br /&gt;
&lt;br /&gt;
Integer constants (of arbitrary size) can be given in hexadecimal (Smalltalk: 16rxxx, JavaScript 0xXXXX), octal (Smalltalk: 8rxxx, JavaScript 0XXXX), and binary (Smalltalk: 2rxxx, JavaScript 0bXXXX). In fact, Smalltalk supports any base from 2 to 36 written as &amp;amp;lt;b&amp;amp;gt;rxxx, where &amp;amp;lt;b&amp;amp;gt; is the base. Thus 3r100 is the ternary representation of the integer 9.&lt;br /&gt;
For ease of use, Smalltalk also supports 0x, 0o and 0b radix prefixes (hex, octal and binary).&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#INTEGER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Integer Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Float =====&lt;br /&gt;
&lt;br /&gt;
Float represents double precision IEEE floating point numbers (64bit).&lt;br /&gt;
Although seldom needed, conversion to single precision (32bit) and high precision (80bit/128bit, depending on the underlying hardware) is possible via the &#039;&#039;asShortFloat()&#039;&#039; and &#039;&#039;asLongFloat()&#039;&#039; conversion functions.&amp;lt;br&amp;gt;Notice that the actual precision of longFloat numbers depends on the CPU: x86 and x86_64 provide 80bits, Sparc and a few other CPUs provide 128 bits.&lt;br /&gt;
&lt;br /&gt;
For more precision, additional classes called &amp;quot;&amp;lt;code&amp;gt;QDouble&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;LargeFloat&amp;lt;/code&amp;gt;&amp;quot; are provided: QDouble provides roughly 200 bits (70 digits) of precision, and LargeFloat offers an arbitrary (configurable) precision. Both are described in the [[Numeric Limits/en|Numeric Limits]] and [[Number_API_Functions|Number API Functions]] documents. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;[[Number_API_Functions|Number API Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FLOAT More Info] in the Smalltalk/X online documentation&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Float Class Documentation]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ShortFloat ShortFloat],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,LongFloat LongFloat],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,QDouble QDouble]&lt;br /&gt;
&amp;lt;!-- [http://live.exept.de/ClassDoc/classDocOf:,LargeFloat LargeFloat ] --&amp;gt;&lt;br /&gt;
Class Documentation&lt;br /&gt;
&amp;lt;br&amp;gt;Details on QDoubles in [https://www.davidhbailey.com/dhbpapers/qd.pdf https:/www.davidhbailey.com/dhbpapers/qd.pdf].&lt;br /&gt;
 &lt;br /&gt;
====== Float Rounding Errors ======&lt;br /&gt;
Be reminded that floating point arithmetic is inherently inaccurate: there will almost always be rounding errors on the last bit. The reason is inherent in that most rational numbers simply cannot be represented as the sum of powers of two. For example, 0.1 and 0.3 are two of them: no sum of powers of two (1/2, 1/4, 1/8, ...) is able to represent these numbers exactly. Thus, there will definitely be an error in the last bit of the stored float value.&lt;br /&gt;
&lt;br /&gt;
Typically, print functions (which convert floating point values to a string representation) will &amp;quot;cheat&amp;quot; and round on the last bit. However, if you operate with such numbers (i.e. add, multiply, etc.) these rounding errors will accumulate and may finally add up to more than one bit of error. When this happens, the print function will no longer round up, and you will get the typical &amp;quot;.999999&amp;quot; result strings.&lt;br /&gt;
&lt;br /&gt;
As an example, try adding 0.3 a thousand times, as in:&lt;br /&gt;
&lt;br /&gt;
 |t|&lt;br /&gt;
 t := 0.3.&lt;br /&gt;
 1000 timesRepeat:[t := t + 0.3].&lt;br /&gt;
 t print&lt;br /&gt;
may give &amp;quot;300.300000000006&amp;quot; as a result.&lt;br /&gt;
&lt;br /&gt;
As a consequence, NEVER ever compare floating point values for equality. In the above case, the comparison with &amp;quot;300.3&amp;quot; would return false!&lt;br /&gt;
&lt;br /&gt;
Floating point numbers should always be compared by giving a range (i.e. between x-delta and x+delta) or by giving a number of valid digits or bits, by which to compare.&lt;br /&gt;
expecco provides a number of action blocks for this kind of &amp;quot;&#039;&#039;almost-equal&#039;&#039;&amp;quot; comparisons.&lt;br /&gt;
&lt;br /&gt;
Of course, there are also similar functions in the Float class, in case you need this in elementary Smalltalk or JavaScript code.&lt;br /&gt;
&lt;br /&gt;
And also: NEVER ever compute monetary values using floating point - or your legal advisor will blame you for missing Cents in the invoice. Monetary values should never be processed with floats (expecco provides a ScaledDecimal number type for that, as described below).&lt;br /&gt;
&lt;br /&gt;
Problems with numbers are discussed in detail in &amp;quot;[[Numeric Limits/en|Numeric Limits]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== Fraction =====&lt;br /&gt;
&lt;br /&gt;
Fractions are arbitrary-precision rational numbers. You will get them when dividing two integers and the result is not integral. Fractions represent an exact result, in contrast to floats, which are only approximations.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
 1 / 3&lt;br /&gt;
returns a fractional result with a numerator of 1 and a denominator of 3 (as opposed to the Smalltalk // operator, which truncates the result of the division to an integer).&lt;br /&gt;
&lt;br /&gt;
Fractions have the advantage of avoiding rounding errors. Thus, when the above fraction is divided by 3, you will get &#039;&#039;(1/9)&#039;&#039;, which we can multiply by 9 to get the exact &#039;&#039;1&#039;&#039; (an integer) without any rounding error. Be reminded that this is typically not the case with Float or Double precision numbers. Due to rounding errors on the last bit, you will often get 0.9999999 as a result there (even though printf may &amp;quot;cheat&amp;quot; and round it to &amp;quot;1.0&amp;quot;, as long as the error is in the last bit only; however, when doing multiple operations in a row, these errors accumulate into the next bit, and rounding will no longer generate a &amp;quot;nice looking&amp;quot; output).&lt;br /&gt;
&lt;br /&gt;
Fraction results are automatically reduced - therefore, when adding &#039;&#039;(1/3) + (2/6)&#039;&#039;, you will get &#039;&#039;(2/3)&#039;&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;And if you add another &#039;&#039;(1/3)&#039;&#039; to it, you will get an exact &#039;&#039;1&#039;&#039;.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
Be aware that fractional arithmetic is done by software, whereas floating point arithmetic is done by CPU instructions.&lt;br /&gt;
Therefore, floating point arithmetic is usually faster.&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FRACTION More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Fraction Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ScaledDecimal =====&lt;br /&gt;
&lt;br /&gt;
ScaledDecimal (also called &amp;quot;&#039;&#039;FixedPoint&#039;&#039;&amp;quot;) numbers are decimals, with a configurable number of post-decimal digits. They are typically used when dealing with money. Like fractions, they avoid rounding errors. When printed, they round in their last digit, however, the exact information is always kept for further processing. ScaledDecimal numbers are perfect to represent money and other fractional data, which must be represented with a fixed number of post-decimal digits. Internally, fixed point numbers are represented as fractions with a power-of-10 denominator.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
ScaledDecimal numbers are also great to print tabular data; for example: &amp;lt;code&amp;gt;someNumber as ScaledDecimal:3&amp;lt;/code&amp;gt; will print the number with and rounded to 3 post-decimal digits.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#FIXEDPOINT More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FixedPoint Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Complex=====&lt;br /&gt;
&lt;br /&gt;
Complex numbers with real and imaginary part are sometimes used in technical/physical applications.&lt;br /&gt;
They can be read as &amp;quot;&amp;lt;code&amp;gt;a * b i&amp;lt;/code&amp;gt;&amp;quot;, for example: &amp;quot;&amp;lt;code&amp;gt;5 + 3i&amp;lt;/code&amp;gt;&amp;quot; represents the complex number with 5 as real and 3 as imaginary part.&lt;br /&gt;
&lt;br /&gt;
Complex numbers can result from math functions such as sqrt and log (by default, these raise an error, which can be ignored for a complex result)&lt;br /&gt;
&amp;lt;!-- &amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#COMPLEX More Info] --&amp;gt;&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Complex Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Number =====&lt;br /&gt;
&lt;br /&gt;
The Number type is an abstract union type which includes all of the above types. Thus, a variable or pin declared as being of &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot; type can take any of the above values. Due to the polymorphic implementation of the underlying numeric class library, most operations can be passed any of the above values (even mixing arguments is possible). For example, the &amp;quot;[Add]&amp;quot; elementary block, which is implemented by simply calling the Smalltalk &amp;quot;+&amp;quot; operation, is able to deal with any combination of argument types.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/numeric.html#NUMBER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Number Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== String Types ====&lt;br /&gt;
&lt;br /&gt;
Strings can come in three flavours (subclasses of CharacterArray), depending on how many bits are required to encode the character&#039;s code point. In general, Unicode is used internally as the encoding. However, converters are available to translate into other encodings, such as JIS or ISO 8859-x.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|16px]] Notice that ASCII (0..127) and ISO 8859-1 (0..255) are proper subsets of the Unicode set.&lt;br /&gt;
Do not confuse Unicode with UTF-8: Unicode is the numeric value associated to a character and used everywhere within expecco.&lt;br /&gt;
UTF-8 is an encoding format for data interchange of Unicode characters. UTF-8 is NOT used inside expecco, only for data exchange with the external world (see &amp;quot;[[String_API_Functions#Encoding_.2F_Decoding|Encoding and Decoding]]&amp;quot; in the String API doc).&lt;br /&gt;
&lt;br /&gt;
In most situations, you do not need to care for the actual number of bits required to store the characters, and expecco/Smalltalk takes care of the actual representation in memory. However, when dealing with the external world (files, sockets, devices), it may be required to perform explicit conversions to/from wider formats or different encodings (UTF-8, UTF-16, etc.)&lt;br /&gt;
&lt;br /&gt;
===== String=====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where each individual character has a one-byte encoding. I.e. the values are 0..255.&lt;br /&gt;
Individual characters of a string can be accessed by an integral index starting with 1 in both Smalltalk and JavaScript. The String class provides many useful functions for substring searching, matching, concatenation/replacing etc.&lt;br /&gt;
Also, because String inherits all functions from the Collection superclass hierarchy, all enumeration, mapping, filtering functions are also applicable to strings.&lt;br /&gt;
&amp;lt;br&amp;gt;See also: [[String API Functions | &#039;&#039;Most Useful String Functions&#039;&#039;]] and [[Collection API Functions | &#039;&#039;Most Useful Collection Functions&#039;&#039;]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#STRING More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,String Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Unicode16String =====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where at least one character needs a two-byte encoding. I.e. any character&#039;s code point is in the range 0x0100 .. 0xFFFF. In fact, there is even a Unicode32String class (see below), which supports the full four-byte Unicode character set. But in practice, such strings are very rarely ever encountered or needed.&lt;br /&gt;
&lt;br /&gt;
===== Unicode32String =====&lt;br /&gt;
&lt;br /&gt;
This is used to represent character strings, where at least one character needs more than a two-byte encoding. I.e. any character&#039;s code point is above 0xFFFF. Such strings are very rarely ever encountered or needed.&lt;br /&gt;
&lt;br /&gt;
===== Character =====&lt;br /&gt;
Individual characters (as extracted from a string or possibly read from a file) are represented as instances of the Character class. Queries are available to ask the character for its type (isLetter, isDigit etc.) or its Unicode encoding (codePoint). There is virtually no limit and every character from the full Unicode set (e.g. even above 0xFFFF) can be represented by instances of the Character class.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#CHARACTER More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Character Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Collection Types ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk and therefore also expecco provides a very complete set of collection types which are tuned for different access patterns or memory consumption.&lt;br /&gt;
An introductory overview on the collection classes is found in the&lt;br /&gt;
&amp;lt;br&amp;gt;Most Useful API: [[Collection API Functions | Most Useful Collection Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html Collections Overview] of the [http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation].&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Collection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
The following paragraphs list the most used collection classes. &lt;br /&gt;
Notice, that Smalltalk provides many more container classes, so please take a look at the online documentation or take a life tour with the browser.&lt;br /&gt;
&lt;br /&gt;
===== Array =====&lt;br /&gt;
&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1 in both Smalltalk and JavaScript.&lt;br /&gt;
Can store any type of object, and storage requirements are 1 machine word per element (i.e. arrays store pointers to the elements). As the size is fixed (when created), adding and removing of&lt;br /&gt;
elements is not possible. Use one of the other collections (OrderedCollection, Set or Dictionary) if the number&lt;br /&gt;
of elements needs to change later or is not known in advance.&lt;br /&gt;
&amp;lt;br&amp;gt;When accessing elements by index, access time complexity is constant O(1).&amp;lt;br&amp;gt;A search for an element in an Array (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;findFirst:&amp;lt;/code&amp;gt; or similar methods) has O(N) time complexity (because the search is linear through all elements of the array).&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#ARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Array Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ByteArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;ByteArrays can only store very small byte-valued unsigned integers (0..255), and allocate 1 byte per element. Access time and complexity are like with ordinary arrays, but the required memory is much less. ByteArrays are used to represent the contents of binary data, binary files, bitmap images, protocol elements (data packets) or low level memory dumps.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt8Array is an alias for ByteArray.&lt;br /&gt;
&amp;lt;br&amp;gt; Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#BYTEARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ByteArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedByteArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store very small 8bit signed integer values (-128..127), requiring 1 byte of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int8Array is an alias for SignedByteArray.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedByteArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BitArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;BitArrays can only store tiny bit-valued unsigned integers (0..1), but only need one byte of storage for every 8 elements.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BitArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BooleanArray =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;BooleanArrays can only store booleans (false..true), but only need 1 byte for every 8 stored boolean elements.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BooleanArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== FloatArray (Float32Array) =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;FloatArrays store short IEEE floats (32bit) and allocate 4 bytes per element.&lt;br /&gt;
Access times and complexity are like those of regular arrays, but they require much less memory. FloatArrays are often used for data interchange with C language functions or in data acquisition scenarios (series of measurement values).&lt;br /&gt;
&amp;lt;br&amp;gt;Float32Array is an alias for FloatArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#FLOATARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FloatArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== DoubleArray (Float64Array) =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;DoubleArrays store IEEE doubles (64bit) and allocate 8 bytes per element.&lt;br /&gt;
These are used in similar situations as FloatArrays.&lt;br /&gt;
&amp;lt;br&amp;gt;Float64Array is an alias for DoubleArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#FLOATARRAY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,DoubleArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== HalfFloatArray (Float16Array) =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;HalfFloatArray can only store IEEE half floats (16bit) and allocate 2 bytes per element.&lt;br /&gt;
: [[Datei:bulb.png|16px]] Notice that half floats have a very low precision and are seldom used.&lt;br /&gt;
: Exceptions are game programs and 3D graphics accelerators which preserve memory by using this very compact format for depth information, texture attributes and some audio formats. They are also used with AI programs in neural networks.&lt;br /&gt;
Float16Array is an alias for HalfFloatArray , and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&lt;br /&gt;
===== IntegerArray / UInt32Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store small 32bit unsigned integer values (0..0xFFFFFFFF) and require 4 bytes of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt32Array is an alias for IntegerArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,IntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedIntegerArray / Int32Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 32bit signed integer values (-0x800000000..0x7FFFFFFF), requiring 4 bytes of storage per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int32Array is an alias for SignedIntegerArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== WordArray / UInt16Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 16bit unsigned integer values (0..0xFFFF), allocating 2 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt16Array is an alias for WordArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,WordArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedWordArray / Int16Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 16bit signed integer values (-0x8000..0x7FFF), allocating 2 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int16Array is an alias for SignedWordArray, and preferable, as it makes the precision explicit, und thus the code more readable.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedWordArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== LongIntegerArray / UInt64Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;They store small 64bit unsigned integer values (0..0xFFFFFFFFFFFFFF), allocating 8 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;UInt64Array is an alias. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,LongIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SignedLongIntegerArray / Int64Array =====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store small 64bit signed integer values (-0x80000000000000000..0x7FFFFFFFFFFFFFFF), allocating 8 bytes per element.&lt;br /&gt;
&amp;lt;br&amp;gt;Int64Array is an alias. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SignedLongIntegerArray Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== ComplexFloatArray / Complex32Array, &amp;lt;br&amp;gt;ComplexDoubleArray / Complex64Array, &amp;lt;br&amp;gt;ComplexHalfFloatArray / Complex16Array=====&lt;br /&gt;
Ordered, fixed size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;These store complex numbers as pairs of IEEE floats (32bit), doubles (64bit) or half floats (16bit). They allocate 8/16/4 bytes per element (4+4 / 8+8 / 2+2).&lt;br /&gt;
&amp;lt;br&amp;gt;These are used in similar situations as FloatArrays and DoubleArrays.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ComplexFloatArray] [http://live.exept.de/ClassDoc/classDocOf:,ComplexDoubleArray]&lt;br /&gt;
&lt;br /&gt;
===== OrderedCollection =====&lt;br /&gt;
Ordered, variable size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;OrderedCollections can store any type of object and are specifically tuned for adding/removing elements at either end.&lt;br /&gt;
&amp;lt;br&amp;gt;Access time to elements by index has a time complexity of O(1).&lt;br /&gt;
&amp;lt;br&amp;gt;Insertion and remove at either end approach O(1), but is O(n) for inner elements, because the elements are moved inside a linear container.&lt;br /&gt;
When searching for an element in an OrderedCollection (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; or similar methods), time complexity is O(n) (because a linear search is done).&lt;br /&gt;
&lt;br /&gt;
Java users will recognize the similarity to &amp;quot;&#039;&#039;ArrayLists&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note: For very big or lightly sparse collections, you can use a [http://live.exept.de/ClassDoc/classDocOf:,SegmentedOrderedCollection SegmentedOrderedCollection]. This uses a hierarchy of buckets and does not need storage for big unused regions inside the collection. However, due to the additional computations, the breakeven in performance compared to regular OrderedCollections is usually at around 100K to 1M elements.&lt;br /&gt;
&lt;br /&gt;
Note: For very very big collections (millions of elements) which are very lightly filled, use a [http://live.exept.de/ClassDoc/classDocOf:,SparseArray SparseArray]. This only keeps the filled slots, and is great, if you have only a few valid elements inside a virtually huge index space.&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#ORDCOLL More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,OrderedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== SortedCollection =====&lt;br /&gt;
Sorts itself, variable size, indexed by an integral index starting with 1.&lt;br /&gt;
&amp;lt;br&amp;gt;SortedCollections can store any type of object for which a order relationship is either implicit (i.e. the elements responds to the &amp;quot;&amp;lt;code&amp;gt;&amp;lt;&amp;lt;/code&amp;gt;&amp;quot; (less) message) or for which an explicit comparison block can is given (i.e. you provide a sort-block, which takes two elements and returns a boolean depending on the ordering).&lt;br /&gt;
&lt;br /&gt;
By default, sorting is by ascending order based on the &amp;quot;&amp;lt;code&amp;gt;&amp;lt;&amp;lt;/code&amp;gt;&amp;quot;-message. However, the sort order can be arbitrarily changed by setting the sortBlock, a two-argument JS-function or a two-argument Smalltalk block which should return true, if its first argument is to be &amp;quot;&#039;&#039;considered&#039;&#039;&amp;quot; smaller than the order&amp;lt;br&amp;gt;(i.e. the default sort block is &amp;quot;&amp;lt;code&amp;gt;[:a :b | a &amp;lt; b]&amp;lt;/code&amp;gt;&amp;quot; or in Javascript: &amp;quot;&amp;lt;code&amp;gt;(a,b) =&amp;gt; a &amp;lt; b&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Access time complexity by numeric index is O(1).&amp;lt;br&amp;gt;When searching for an element in a SortedCollection (using &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;indexOf:&amp;lt;/code&amp;gt; or similar methods); time complexity is O(log n), because a binary search can be done.&amp;lt;br&amp;gt;Insertion and remove is O(1) for the first and last element, O(log n + n) for inner elements, because the insert index is first searched, then elements are moved inside a linear container.&lt;br /&gt;
&lt;br /&gt;
When a big sorted collection is created, it is faster to first create it as a non-sorted collection (OrderedCollection) and then converting the whole collection via &amp;lt;code&amp;gt;asSortedCollection&amp;lt;/code&amp;gt;, instead of adding individual elements one-by-one. If elements are to be added individually, it is probably better to use a tree like collection.&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#SORTCOLL More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SortedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Set =====&lt;br /&gt;
Unordered, variable size, keeps a single reference only, per equal element.&lt;br /&gt;
&amp;lt;br&amp;gt;Sets can store any type of object.&lt;br /&gt;
When searching a Set for an element (eg. using the &amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt; method), time complexity approaches O(1), because the search can be done based on a hashing algorithm in asymptotic constant time (however, the time to compute the hash of an element may affect the effective execution time; it should not be too slow). For very small sets, the hash-computation time might be long compared to the time it takes to compare elements. It may then be faster to simply use an Array or OrderedCollection and do a sequential search (use eg. &amp;quot;includes:&amp;quot;, &amp;quot;indexOf:&amp;quot; or &amp;quot;anySatisfy:&amp;quot;).&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#SET More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Set Class Documentation]&lt;br /&gt;
&amp;lt;br&amp;gt;In addition to the unordered Set, useful classes are also &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,OrderedSet OrderedSet]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,SortedSet SortedSet]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Bag =====&lt;br /&gt;
Unordered, variable size, keeps a count, per equal element. Adding, removing and insertion check all run in O(1).&lt;br /&gt;
Can store any type of object.&lt;br /&gt;
&amp;lt;br&amp;gt;Bags are similar to Sets, but keep the number of occurrences of each element. Thus, bags are perfect to count the number of elements in a collection, for example words and word counts in a document. &lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Bag Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Dictionary =====&lt;br /&gt;
Unordered, variable size, implements arbitrary key-value mappings.&lt;br /&gt;
&amp;lt;br&amp;gt;Dictionaries can store any type of object and use any kind of object as key.&lt;br /&gt;
When accessing or searching an element in a Dictionary (using &amp;lt;code&amp;gt;at:&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;includesKey:&amp;lt;/code&amp;gt; and similar methods), the time complexity asymptotically approaches O(1), because the key search is based on a hashing algorithm. Notice, that the same value may be stored multiple times in a dictionary (i.e. stored under multiple keys).&lt;br /&gt;
Asking for the presence of a particular &#039;&#039;&#039;value&#039;&#039;&#039; in the dictionary (i.e. the reverse query without key) still has O(N) time complexity.&lt;br /&gt;
&lt;br /&gt;
If you need fast access both via the key and the value, either use an additional reverse mapping dictionary, or store&lt;br /&gt;
an additional &#039;&#039;value&#039;&#039;-&amp;gt;&#039;&#039;key&#039;&#039; mapping in the same dictionary (if the key and value spaces are disjoint).&lt;br /&gt;
&lt;br /&gt;
Java users will know a subset of the dictionary functionality as &amp;quot;&#039;&#039;Hashtable&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#DICTIONARY More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Dictionary Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== OrderedDictionary =====&lt;br /&gt;
Ordered, variable size, implements arbitrary key-value mappings.&lt;br /&gt;
Can store any type of object and use any kind of object as key.&lt;br /&gt;
Being similar to dictionaries, these remember the order by which elements were added. It provides both access by hash-key and access by index (which is the order in which elements have been added). When enumerated, elements are processed in that order. Creation of an OrderedDictionary is somewhat slower than for Dictionary or OrderedCollection, but access by either numeric or hashkey is fast with O(1) time complexity.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,OrderedDictionary Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== OrderedSet =====&lt;br /&gt;
This is very similar to a Set, but remembers the order in which elements were added, and provides index read access methods. When enumerated, the elements are generated in this order.&lt;br /&gt;
&lt;br /&gt;
===== Queue =====&lt;br /&gt;
Ordered, variable size.&lt;br /&gt;
Can store any type of object. Queues are especially tuned for adding elements at one end, and removing them at the other. The internal representation uses a buffer in round-robin fashion. Both adding and removal are done on O(1) time.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/collections.html#QUEUE More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Queue Class Documentation]&lt;br /&gt;
&lt;br /&gt;
If multiple processes are accessing the same queue concurrently, use a &amp;lt;code&amp;gt;[http://live.exept.de/ClassDoc/classDocOf:,SharedQueue SharedQueue]&amp;lt;/code&amp;gt;, which is implicitly synchronized.&lt;br /&gt;
&lt;br /&gt;
===== SharedCollection =====&lt;br /&gt;
Any collection can be wrapped into a &#039;&#039;SharedCollection&#039;&#039; to add synchronization locks around its access functions. These should be used if multiple processes (threads) are going to access (i.e: update) the collection simultaneously.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SharedCollection Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== BTree, AATree, BinaryTree =====&lt;br /&gt;
Combining the functionality of &amp;lt;code&amp;gt;Dictionary&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;SortedCollection&amp;lt;/code&amp;gt;, these keep their elements in a sorted order, indexed by a key, both of which can be arbitrary objects.&lt;br /&gt;
In contrast to dictionaries, which use hashing, these use a tree-like representation and guarantee both asymptotic O(log N) worst case and average runtime. (Dictionaries have a much better typical time complexity of O(C), but also a worst case of O(N), if the hash keys are badly distributed). These trees are self balancing to avoid the linear worst case access time of non balanced trees. [[http://live.exept.de/ClassDoc/classDocOf:,BTree Class Documentation]]&lt;br /&gt;
&lt;br /&gt;
There is also a non-balancing BinaryTree, which is slightly faster (by not balancing), but its worst case access times may degenerate to O(N), if elements are added non-randomly. &amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,BinaryTree Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Interval, GeometricSeries and NumberSet =====&lt;br /&gt;
&lt;br /&gt;
An interval represents a range of numbers as in &amp;quot;&amp;lt;CODE&amp;gt;(1 to:5)&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;(1 to:10 by:2)&amp;lt;/CODE&amp;gt;&amp;quot; or &amp;quot;&amp;lt;CODE&amp;gt;(7 to:4 by:-1)&amp;lt;/CODE&amp;gt;&amp;quot;; these represent collections of numbers [1,2,3,4,5], [1,3,5,7,9] and [7,6,5,4] respectively.&lt;br /&gt;
&lt;br /&gt;
GeometricSeries are similar, but have a constant factor between elements, instead of a constant difference. For example, the &amp;quot;&amp;lt;CODE&amp;gt;(GeometricSeries from:1 to:64 byFactor:2)&amp;lt;/CODE&amp;gt;&amp;quot; represents the collection [1,2,4,8,16,32,64].&lt;br /&gt;
&lt;br /&gt;
NumberSets are optimized for collections of integer number ranges.&amp;lt;br&amp;gt;For example &amp;quot;&amp;lt;CODE&amp;gt;(NumberSet new add:1; add:3; addAll:(10 to:13)&amp;lt;/CODE&amp;gt;&amp;quot; represents the collection [1,3,10,11,12,13].&lt;br /&gt;
&lt;br /&gt;
Intervals, GeometricSeries and NumberSets can be used wherever a readonly collection can be used.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Interval Interval Class Documentation] and [http://live.exept.de/ClassDoc/classDocOf:,GeometricSeries GeometricSeries Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Stream Types ====&lt;br /&gt;
&lt;br /&gt;
Streams are accessors for either internal collections or external files, sockets and other character oriented I/O devices.&lt;br /&gt;
They are created by either &amp;quot;&#039;&#039;opening&#039;&#039;&amp;quot; a file or device or by creation &amp;quot;&#039;&#039;on&#039;&#039;&amp;quot; a numerical indexable collection object (String, Array, OrderedCollection etc.).&lt;br /&gt;
Once created, readstreams deliver the next element via a &amp;quot;&#039;&#039;next&#039;&#039;()&amp;quot; operation, writestreams append elements via the &amp;quot;&#039;&#039;nextPut(e)&#039;&#039;&amp;quot; operation.&lt;br /&gt;
In addition to the above elementary functions, bulk read/write and linewise read/write and various other functionality is provided.&lt;br /&gt;
&lt;br /&gt;
An introductory overview on the stream classes is found in the &lt;br /&gt;
[[http://live.exept.de/doc/online/english/overview/basicClasses/streams.html Streams Overview]] of the [[http://live.exept.de/doc/online/english/TOP.html Smalltalk/X online documentation]].&lt;br /&gt;
&lt;br /&gt;
===== ExternalStream =====&lt;br /&gt;
A common superclass providing bytewise, blockwise and linewise access to any stream of the underlying operating system. Concrete subclasses are Socket, Filestream, Console Streams, PTYStream etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,ExternalStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== FileStream =====&lt;br /&gt;
Provide bytewise, blockwise or linewise access to the underlying file system.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,FileStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== CharacterWriteStream =====&lt;br /&gt;
A special stream usable for mixed single- and multibyte characters (i.e. Unicode). This stream starts to collect into a single byte string buffer, but switches automatically to a multibyte character string as required.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,CharacterWriteStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Socket =====&lt;br /&gt;
Provides low level bytewise, blockwise or linewise access to a communication socket. Typically, but not limited to TCP/IP connections.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/streams.html#FILESTREAM More Info]&lt;br /&gt;
&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Socket Class Documentation]&lt;br /&gt;
&lt;br /&gt;
There are a number of useful companion classes which deal with host addresses:&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,SocketAddress SocketAddress],&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,SocketAddress IPSocketAddress] and&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,SocketAddress IPv6SocketAddress].&lt;br /&gt;
&lt;br /&gt;
===== PipeStream =====&lt;br /&gt;
These are used to read/write from/to another program&#039;s standard input or standard output. For details, consult a Unix programmer&#039;s manual.&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,PipeStream Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Filename =====&lt;br /&gt;
Represents names of files in the filesystem. Provides many useful query functions for file size, access- and modification time, parent directory, children, path queries etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Most Useful API: [[Filename API Functions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Filename Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== Encoders / Decoders ====&lt;br /&gt;
&lt;br /&gt;
The &lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,CharacterEncoder CharacterEncoder] class provides a number of functions to encode/decode strings into various other encodings;&lt;br /&gt;
for example, to read an ISO 8859-7 encoded string,&lt;br /&gt;
use:&lt;br /&gt;
    decodedString := &lt;br /&gt;
        (CharacterEncoder encoderFor:#&#039;ISO8859-7&#039;) &lt;br /&gt;
            decodeFrom:encodedString.&lt;br /&gt;
and vice versa:&lt;br /&gt;
    encodedString := &lt;br /&gt;
        (CharacterEncoder encoderFor:#&#039;ISO8859-7&#039;)&lt;br /&gt;
            encodeFrom:originalString.&lt;br /&gt;
&lt;br /&gt;
By the time of writing, the following encodings are supported (many are aliases of others):&lt;br /&gt;
&lt;br /&gt;
adobe-fontspecific ansi_x3.4-1968 arabic ascii ascii7 asmo-708 &lt;br /&gt;
big5 &lt;br /&gt;
cns11643 cp-037 cp-37 cp-437 cp10000 cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp367 cp437 cp878 cyrillic &lt;br /&gt;
ebcdic ebcdic-037 ecma-114 ecma-118  &lt;br /&gt;
gb2312 gb2312.1980 gb2312.1980-0 greek &lt;br /&gt;
hangul hebrew &lt;br /&gt;
ibm-367 ibm-437 ibm-819 ibm-cp367 ibm-cp437 ibm-cp819 iso-10646-1 iso-8859-1 iso-8859-10 iso-8859-11 iso-8859-13 iso-8859-14 iso-8859-15 iso-8859-16 iso-8859-2 iso-8859-3 iso-8859-4 iso-8859-5 iso-8859-6 iso-8859-7 iso-8859-8 iso-8859-9 iso-ir-100 iso-ir-101 iso-ir-109 iso-ir-110 iso-ir-126 iso-ir-127 iso-ir-138 iso-ir-144 iso-ir-148 iso-ir-157 iso-ir-203 iso-ir-6 iso10646-1 iso10646_1 iso646-us iso8859 iso8859-1 iso8859-10 iso8859-11 iso8859-13 iso8859-14 iso8859-15 iso8859-16 iso8859-2 iso8859-3 iso8859-4 iso8859-5 iso8859-6 iso8859-7 iso8859-8 iso8859-9 iso8859_1 iso8859_10 iso8859_11 iso8859_13 iso8859_14 iso8859_15 iso8859_16 iso8859_2 iso8859_3 iso8859_4 iso8859_5 iso8859_6 iso8859_7 iso8859_8 iso8859_9&lt;br /&gt;
java javaText jis0201 jis0208 jis0212 jisx0201.1976-0 jisx0208 jisx0208.1983-0 jisx0208.1990-0 johab &lt;br /&gt;
koi7 koi8-r koi8-u ksc5601 &lt;br /&gt;
latin-1 latin-10 latin-2 latin-3 latin-4 latin-5 latin-6 latin-7 latin-8 latin-9 latin-celtic latin1 latin10 latin2 latin3 latin4 latin5 latin6 latin7 latin8 latin9 &lt;br /&gt;
mac-arabic mac-centraleurope mac-centraleuropean mac-croatian mac-cyrillic mac-dingbats mac-farsi mac-greek mac-hebrew mac-iceland mac-japanese mac-korean mac-roman mac-romanian mac-symbol mac-thai mac-turkish macarabic maccentraleurope maccentraleuropean maccroatian maccyrillic macdingbat macdingbats macfarsi macgreek machebrew maciceland macintosh macjapanese mackorean macroman macromanian macsymbol macthai macturkish microsoft-ansi microsoft-arabic microsoft-baltic microsoft-cp1250 microsoft-cp1251 microsoft-cp1252 microsoft-cp1253 microsoft-cp1254 microsoft-cp1255 microsoft-cp1256 microsoft-cp1257 microsoft-cp437 microsoft-cyrillic microsoft-easteuropean microsoft-greek microsoft-hebrew microsoft-turkish ms-ansi ms-arabic ms-baltic ms-cp1250 ms-cp1251 ms-cp1252 ms-cp1253 ms-cp1254 ms-cp1255 ms-cp1256 ms-cp1257 ms-cp367 ms-cp437 ms-cp819 ms-cyrillic ms-default ms-easteuropean ms-ee ms-greek ms-hebrew ms-oem ms-turkish next &lt;br /&gt;
nextstep &lt;br /&gt;
sgml &lt;br /&gt;
thai &lt;br /&gt;
us-ascii utf-16b utf-16be utf-16e utf-16le utf-8 utf-8-mac utf16b utf16be utf16l utf16le utf8 utf8-XML utf8-mac &lt;br /&gt;
windows-1250 windows-1251 windows-1252 windows-1253 windows-1254 windows-1255 windows-1256 windows-1257 windows-latin1&lt;br /&gt;
&lt;br /&gt;
For base64 encoding, refer to the &lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Base64Coder Base64Coder] &lt;br /&gt;
class, or use the string messages: &amp;lt;code&amp;gt;base64Encoded&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;base64Decoded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For utf8 encoding/decoding, use the string messages: &amp;lt;code&amp;gt;utf8Encoded&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;utf8Decoded&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Other useful Types ====&lt;br /&gt;
&lt;br /&gt;
===== Date =====&lt;br /&gt;
Represents a calendar date. Instances can be created with eg. &amp;quot;&amp;lt;code&amp;gt;Date today&amp;lt;/code&amp;gt;&amp;quot;, by giving day/month/year or a calendar day. Instances offer a large number of queries, such as weekday, dayInWeek, leapYear etc.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#DATE More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Date Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Time =====&lt;br /&gt;
Represents a time-of-day in second resolution. Instances are created with &amp;quot;&amp;lt;code&amp;gt;Time now&amp;lt;/CODE&amp;gt;&amp;quot; or by giving hour/minute/seconds.&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIME More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Time Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Timestamp (Date and Time) =====&lt;br /&gt;
Represents a timestamp. With the 18.1 release, the resolution has been improved to sub-nanosecond resolution, although internal timestamps as generated by the operating system will usually not generate such fine grained values (some systems will only generate, 1 millisecond resolution stamps).&lt;br /&gt;
&lt;br /&gt;
Update: now the resolution supported by Timestamps is 1 picosecond, and microsecond times are also supported on Windows systems.&lt;br /&gt;
&lt;br /&gt;
For backward compatibility, the default resolution is 1 millisecond for internally generated stamps, and whatever resolution is provided when stamps are read from an external source. When printed, the default print format includes 3 millisecond digits, but a separate print generator can produce higher resolution strings (in 18.1).&lt;br /&gt;
&lt;br /&gt;
The Timestamp class has been enhanced to support dates before 1.1.1970 and after 2036, which are typical restrictions of systems which represent times as &amp;quot;&#039;&#039;seconds since the epoch&#039;&#039;&amp;quot; in a 32bit integer. Expecco timestamps handle values before and after those dates, although no calendar adjustments are done for timestamps before the julian/gregorian switch (i.e. this affects weekdays, leap years, etc. before 1582, which are very unlikely to be encountered in technical environments ;-) ).&lt;br /&gt;
&amp;lt;br&amp;gt;Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIMESTAMP More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,Timestamp Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== TimeDuration =====&lt;br /&gt;
Represents an amount of time, to represent time intervals in picosecond resolution. &lt;br /&gt;
&lt;br /&gt;
When reading from a string or stream, a unit-specifier character is allowed to specify milliseconds (ms), seconds (s), minutes (m), hours (h) or days (d). For example, &amp;quot;&amp;lt;code&amp;gt;1h 20s&amp;lt;/code&amp;gt;&amp;quot; specifies 1 hour and 20 seconds.&lt;br /&gt;
&lt;br /&gt;
As a programmer, you can write (in Smalltalk): &amp;quot;&amp;lt;code&amp;gt;1 hours + 20 seconds&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Creation:&lt;br /&gt;
* TimeDuration fromString: &amp;amp;apos;&#039;&#039;aString&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromSeconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMinutes: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromHours: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMilliseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromMicroseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromNanoseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration fromPicoseconds: &amp;amp;apos;&#039;&#039;aNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
* TimeDuration days: &amp;amp;apos;&#039;&#039;dayNumber&#039;&#039;&amp;amp;apos; hours: &amp;amp;apos;&#039;&#039;hourNumber&#039;&#039;&amp;amp;apos;  minutes: &amp;amp;apos;&#039;&#039;minuteNumber&#039;&#039;&amp;amp;apos;  seconds: &amp;amp;apos;&#039;&#039;secondsNumber&#039;&#039;&amp;amp;apos;&lt;br /&gt;
&lt;br /&gt;
Overview: [http://live.exept.de/doc/online/english/overview/basicClasses/misc.html#TIMEDURATION More Info]&lt;br /&gt;
&amp;lt;br&amp;gt;Reference: [http://live.exept.de/ClassDoc/classDocOf:,TimeDuration Class Documentation]&lt;br /&gt;
&lt;br /&gt;
===== Delay =====&lt;br /&gt;
Delay is a utility providing timed delay functions. Most useful are (written in Smalltalk):&lt;br /&gt;
   Delay waitForSeconds: &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt;.   (arg is a number)&lt;br /&gt;
 and: &lt;br /&gt;
   Delay waitFor: &amp;lt;i&amp;gt;n&amp;lt;/i&amp;gt; seconds.  (arg is a time duration)&lt;br /&gt;
 and: &lt;br /&gt;
   Delay waitUntil: &amp;lt;i&amp;gt;timestamp&amp;lt;/i&amp;gt;. (arg is a timestamp)&lt;br /&gt;
&lt;br /&gt;
or (written in JavaScript):&lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitForSeconds(n)&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitFor(n.seconds())&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
 and &lt;br /&gt;
   &amp;quot;&amp;lt;code&amp;gt;Delay.waitUntil(timestamp)&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
Reference: [http://live.exept.de/ClassDoc/classDocOf:,Delay Class Documentation]&lt;br /&gt;
&lt;br /&gt;
==== CTypes ====&lt;br /&gt;
&lt;br /&gt;
These types describe C-data structures. They are needed when data is exchanged with DLL functions or is to be read/written in binary from/to a file or a communication channel.&lt;br /&gt;
&lt;br /&gt;
CTypes are usually parsed from a string using the C Parser, which is invoked by expecco when a type definition starts with a comment like &amp;quot;/* C: */&amp;quot;.&lt;br /&gt;
But of course, the C-Parser can also be invoked explicitly in a workspace or programmatically via an elementary block.&lt;br /&gt;
The following example would create a C-type from a structure definition string (in JavaScript code):&lt;br /&gt;
    t = CParser.parseDeclaration(&amp;quot;&lt;br /&gt;
        struct s {&lt;br /&gt;
            unsigned long DPR_Address;&lt;br /&gt;
            unsigned long DPR_Length;&lt;br /&gt;
            unsigned long PortAddress;&lt;br /&gt;
            struct p {&lt;br /&gt;
                unsigned char ProtocolID;&lt;br /&gt;
                union u {&lt;br /&gt;
                    uint16 dpInOutAreaSize;&lt;br /&gt;
                    uint16 dpInAreaSize;&lt;br /&gt;
                } Parameter;&lt;br /&gt;
            } Protocol[4];&lt;br /&gt;
        };&lt;br /&gt;
    &amp;quot;);&lt;br /&gt;
the type in variable &amp;quot;&amp;lt;code&amp;gt;t&amp;lt;/code&amp;gt;&amp;quot; can then be instantiated by sending it a &amp;quot;&amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt;&amp;quot; message:&lt;br /&gt;
    cDatum = t.new();&lt;br /&gt;
or with:&lt;br /&gt;
    cDatum = t.malloc();&lt;br /&gt;
The difference is that &amp;quot;&amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt;&amp;quot; allocates the bytes in the regular garbage collected expecco memory (which may move objects),&lt;br /&gt;
whereas &amp;quot;&amp;lt;code&amp;gt;malloc&amp;lt;/code&amp;gt;&amp;quot; allocates in pinned (not moving) memory on the C heap. Thus references to such malloc&#039;d memory can be passed to DLL code which wants to keep a reference to it, whereas C-data allocated with &amp;lt;code&amp;gt;new&amp;lt;/code&amp;gt; can only be used temporarily by C code and will vanish sooner or later after the call returns.&lt;br /&gt;
&lt;br /&gt;
You can inspect the created instance via the inspector (evaluate: &amp;quot;&amp;lt;code&amp;gt;cDatum.inspect()&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Individual fields of the c-datum are accessed via the following functions:&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.memberAt(fieldName)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;retrieves a field. If the field is a composite datum (array or structure), a new datum is extracted (i.e. a structure copy is made).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.at(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;retrieves an indexed array element as a copy.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.memberAtPut(fieldName, value)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;stores a field. If the field is a composite datum (array or structure), the whole value is copied.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.atPut(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;stores an indexed array element.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;CDatum.refMemberAt(fieldName)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;creates a pointer to a field. This allows for subfields to be modified.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cDatum.refAt(index0Based)&amp;lt;/code&amp;gt;&amp;lt;br&amp;gt;creates a pointer to an array element.&lt;br /&gt;
&lt;br /&gt;
notice that in JavaScript, indexed access can be written more convenient as &amp;quot;&amp;lt;code&amp;gt;cDatum[index0Based]&amp;lt;/code&amp;gt;&amp;quot; and that member field access can be written as &amp;quot;&amp;lt;code&amp;gt;cDatum.fieldName&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For the full protocol of CDatum, please refer to the class code in the&lt;br /&gt;
[http://live.exept.de/ClassDoc/classDocOf:,Ctype Class Documentation].&lt;br /&gt;
&amp;lt;br&amp;gt;Additional information is also found in the [[Datatype Element/en#CTypes]] documentation.&lt;br /&gt;
&lt;br /&gt;
=== Additional Standard Objects for JavaScript ===&lt;br /&gt;
&lt;br /&gt;
In order for a &amp;quot;&#039;&#039;well known&#039;&#039;&amp;quot; environment to be provided to those who know JavaScript, but do not know Smalltalk, mimicri classes (Math) and mimicri protocol has been added to the underlying Smalltalk system. These functions simply call corresponding Smalltalk functions and only exist to provide a JavaScript compatible API which is described below. &lt;br /&gt;
&lt;br /&gt;
Notice that this represents only a small fraction (less than 1/100th) of the real functionality of the base system. In order to find out more about all existing classes, you should open a class browser and navigate through the system yourself (eg. Number and subclasses).&amp;lt;br&amp;gt;There is also a more detailed introduction to the basic classes found in the &lt;br /&gt;
[http://live.exept.de/doc/online/english/overview/basicClasses/TOP.html Smalltalk/X Base Classes Documentation].&lt;br /&gt;
&lt;br /&gt;
==== Math ====&lt;br /&gt;
&lt;br /&gt;
===== Constants =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;E&#039;&#039;&#039;&amp;lt;br&amp;gt;Euler&#039;s constant, the base of the natural logarithm (approximately 2.718 as double precision IEEE number).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float e&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk (or &amp;quot;&amp;lt;code&amp;gt;Math E&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LN10&#039;&#039;&#039;&amp;lt;br&amp;gt;Natural logarithm of 10 (approximately 2.302 as double).&amp;lt;br&amp;gt;In Smalltalk, you can use &amp;quot;&amp;lt;code&amp;gt;Float ln10&amp;lt;/code&amp;gt;&amp;quot; (or &amp;quot;&amp;lt;code&amp;gt;Math LN10&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LN2&#039;&#039;&#039;&amp;lt;br&amp;gt;Natural logarithm of 2 (approximately 0.693 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float ln2&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LOG10E&#039;&#039;&#039;&amp;lt;br&amp;gt;Base 10 logarithm of E (approximately 0.434 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;LOG2E&#039;&#039;&#039;&amp;lt;br&amp;gt;Base 2 logarithm of E (approximately 1.442 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;PI&#039;&#039;&#039;&amp;lt;br&amp;gt;Pi (approximately 3.14159 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float pi&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;SQRT1_2&#039;&#039;&#039;&amp;lt;br&amp;gt;Square root of 1/2 (approximately 0.707 as double)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;SQRT2&#039;&#039;&#039;&amp;lt;br&amp;gt;Square root of 2 (approximately 1.414 as double).&amp;lt;br&amp;gt;Same as &amp;quot;&amp;lt;code&amp;gt;Float sqrt2&amp;lt;/code&amp;gt;&amp;quot; in Smalltalk.&lt;br /&gt;
&lt;br /&gt;
===== Min &amp;amp; Max =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;max&#039;&#039;&#039; (&#039;&#039;number1 , number2,...&#039;&#039;)&amp;lt;br&amp;gt;Returns the largest of up to 6 arguments&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;min&#039;&#039;&#039; (&#039;&#039;number1, number2,...&#039;&#039;)&amp;lt;br&amp;gt;Returns the smallest of up to 6 arguments&lt;br /&gt;
&lt;br /&gt;
===== Miscellaneous =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;abs&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the absolute value of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;binco&#039;&#039;&#039; (&#039;&#039;n, k&#039;&#039;) &amp;lt;br&amp;gt;Returns the binomial coefficient C(n,k) (&amp;lt;span title=&amp;quot;aka. = also known as&amp;quot;&amp;gt;aka&amp;lt;/span&amp;gt;. &amp;quot;n over k&amp;quot; or &amp;quot;choose k from n&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cbrt&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cubic root of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ceil&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the smallest integer greater than or equal to aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;exp&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns e&amp;lt;sup&amp;gt;aNumber&amp;lt;/sup&amp;gt;, where aNumber is the argument, and e is Euler&#039;s constant, the base of the natural logarithm&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fac&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the factorial of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;floor&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the greatest integer less than or equal to aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;gcd&#039;&#039;&#039; (&#039;&#039;a, b&#039;&#039;)&amp;lt;br&amp;gt;Returns the greatest common divisor of a and b&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;log10&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the log base 10 of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;log&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the log base E of aNumber&lt;br /&gt;
&amp;lt;!--ATTENTION:&lt;br /&gt;
    In JavaScript log is a base E log&lt;br /&gt;
    In Smalltalk log is a base 10 log (use ln for base E)&lt;br /&gt;
    In JavaScript, better use log10 to make things explicit.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pow&#039;&#039;&#039; (&#039;&#039;base, exp&#039;&#039;)&amp;lt;br&amp;gt;Returns base to the exponent power, that is, base&amp;lt;sup&amp;gt;exp&amp;lt;/sup&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;random&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a pseudo random number between 0 and 1&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;round&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of aNumber rounded to the nearest integer&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sqrt&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the square root of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;trunc&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of aNumber truncated towards zero&amp;lt;br&amp;gt;(that is: the smallest integer greater or equal if aNumber is negative, or the largest integer less or equal if positive)&lt;br /&gt;
&lt;br /&gt;
===== Trigonometric =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sin&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the sine of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cos&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cosine of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;tan&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the tangent of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cot&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cotangent of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;csc&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the cosecant of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sec&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the secant of aNumber (given in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcSin&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arcsine (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcCos&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arccosine (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcTan&#039;&#039;&#039; (&#039;&#039;aNumber&#039;&#039;)&amp;lt;br&amp;gt;Returns the arctangent (in radians) of aNumber&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;arcTan2&#039;&#039;&#039; (&#039;&#039;x, y&#039;&#039;)&amp;lt;br&amp;gt;Returns the arctangent of the quotient of its arguments (in radians)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;sinh&#039;&#039;&#039; / &#039;&#039;&#039;cosh&#039;&#039;&#039; / &#039;&#039;&#039;tanh&#039;&#039;&#039; / &#039;&#039;&#039;arSinh&#039;&#039;&#039; / &#039;&#039;&#039;arCosh&#039;&#039;&#039; etc.&amp;lt;br&amp;gt;Hyperbolic versions of above&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;degreesToRadians&#039;&#039;&#039;(&#039;&#039;d&#039;&#039;) / &#039;&#039;&#039;radiansToDegrees&#039;&#039;&#039;(&#039;&#039;r&#039;&#039;)&amp;lt;br&amp;gt;Conversions&lt;br /&gt;
&lt;br /&gt;
==== Number ====&lt;br /&gt;
===== Properties =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;MAX_VALUE&#039;&#039;&#039;&amp;lt;br&amp;gt;The largest representable number. The returned number is 0x7FFFFFFFFFFFFFFF, to mimicri a 64 bit limit on numbers for JS programs ported from other systems. In fact, expecco does not impose any such limit in integer values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;MIN_VALUE&#039;&#039;&#039;&amp;lt;br&amp;gt;The smallest representable number. The returned number is -0x8000000000000000, to mimicri a 64 bit limit on numbers for JS programs ported from other systems. In fact, expecco does not impose any such limit in integer values.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;NEGATIVE_INFINITY&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;negative infinity&#039; value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;NaN&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;not a number&#039; value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;POSITIVE_INFINITY&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the special &#039;positive infinity&#039; value&lt;br /&gt;
&lt;br /&gt;
===== Methods =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;asFloat&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns a floating-point version of the receiver object.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.asFloat()&amp;lt;/code&amp;gt;&amp;quot; yields the (double precision) floating point number: &amp;quot;1.0&amp;quot;.&amp;lt;br&amp;gt;You can also use one of &amp;quot;asFloat32&amp;quot;, &amp;quot;asFloat64&amp;quot;, &amp;quot;asFloat80&amp;quot;, &amp;quot;asFloat128&amp;quot; or &amp;quot;asLargeFloat&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;asInteger&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns an integer version of the receiver object (truncating).&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.0.asInteger()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;. Alternatives are ceiling(), floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;ceiling&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, ceiling returns the smallest integer which is larger than the receiver. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.ceiling()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;2&amp;quot;, whereas &amp;quot;&amp;lt;code&amp;gt;1.ceiling()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;floor&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, floor returns the largest integer which is smaller than the receiver. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.floor()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;, whereas &amp;quot;&amp;lt;code&amp;gt;1.floor()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: ceiling() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;rounded&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For non-integral values, rounded returns the nearest integer from rounding. For integers, the original value is returned.&amp;lt;br&amp;gt;For example: &amp;quot;&amp;lt;code&amp;gt;1.4.rounded()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;1&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;1.6.rounded()&amp;lt;/code&amp;gt;&amp;quot; yields the integer number: &amp;quot;2&amp;quot; and whereas &amp;quot;&amp;lt;code&amp;gt;1.rounded()&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1&amp;quot;. See also: ceiling() and floor().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;roundTo&#039;&#039;&#039; (&#039;&#039;r&#039;&#039;)&amp;lt;br&amp;gt;Rounds towards the nearest multiple of r.&amp;lt;br&amp;gt;For example, &amp;quot;&amp;lt;code&amp;gt;1.543.roundedTo(0.01)&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1.54&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;1.567.roundedTo(0.01)&amp;lt;/code&amp;gt;&amp;quot; returns &amp;quot;1.57&amp;quot;. See also: ceiling(), floor() and rounded().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toExponential&#039;&#039;&#039; (&#039;&#039;nDigits&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in exponential notation, where nDigits is the number of digits to appear after the decimal point&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toExponential&#039;&#039;&#039; (&#039;&#039;nDigits, nDigitsAfter&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in exponential notation&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aNumber&#039;&#039;.&#039;&#039;&#039;toFixed&#039;&#039;&#039; (&#039;&#039;nDigits&#039;&#039;)&amp;lt;br&amp;gt;Returns a string representing the number in fixed notation, where nDigits is the number of digits to appear after the decimal point&lt;br /&gt;
&lt;br /&gt;
==== Random ====&lt;br /&gt;
&lt;br /&gt;
A built in random generator, which generates linear congruential pseudo random numbers itself. On Unix/Linux operating systems, an additional class called &amp;quot;RandomGenerator&amp;quot; uses the operating system&#039;s random generator (&amp;lt;code&amp;gt;/dev/rand&amp;lt;/code&amp;gt;). In addition, alternative generators are available as &amp;quot;&amp;lt;code&amp;gt;RandomParkMiller&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;RandomTT800&amp;lt;/code&amp;gt;&amp;quot;. For most applications, the default generator named &amp;quot;&amp;lt;code&amp;gt;Random&amp;lt;/code&amp;gt;&amp;quot; should provide a reasonable random sequence (this will be the &amp;quot;/dev/rand&amp;quot;-based generator on Unix/Linux, and a Cryptographic Hash-based generator on other systems).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;next ()&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a random number between 0 and 1 (float)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;next (&#039;&#039;n&#039;&#039;)&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns n random numbers between 0 and 1 (float) as an array&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextBoolean ()&#039;&#039;&#039;&amp;lt;br&amp;gt;Randomly returns either true or false&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextBetween_and_&#039;&#039;&#039; (&#039;&#039;min, max&#039;&#039;)&amp;lt;br&amp;gt;Returns a random float between min and max&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Random&#039;&#039;.&#039;&#039;&#039;nextIntegerBetween_and_&#039;&#039;&#039; (&#039;&#039;min, max&#039;&#039;)&amp;lt;br&amp;gt;Returns a random integer between min and max (use 1 and 6, to simulate a dice)&lt;br /&gt;
&lt;br /&gt;
==== Time / Date ====&lt;br /&gt;
&lt;br /&gt;
Time and Date instances provide a rich protocol for all kinds of queries. The list below is only a short extract of the most used methods:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Time now&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the current time&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Date today&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the current date&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getDate&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the month (1..31)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getDay&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the week (0..6); Sunday is 0&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getMonth&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the day of the month (1..12)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aDate&#039;&#039;.&#039;&#039;&#039;getFullYear&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the year&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTime&#039;&#039;.&#039;&#039;&#039;getHours&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the hours (0..24)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTime&#039;&#039;.&#039;&#039;&#039;getMinutes&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the minutes (0..60)&lt;br /&gt;
&lt;br /&gt;
==== String ====&lt;br /&gt;
&lt;br /&gt;
Be reminded that the String class inherits from CharacterArray, ByteArray, SequentialCollection, Collection and Object. Thus all of those methods are also available (and useful) with strings. Use the browser or take a look at the online documentation for the full protocol (which is much larger than what is listed below).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charAt0&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the n&#039;th character as a Character instance object, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charAt1&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the n&#039;th character as a Character instance object, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charCodeAt0&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the code of the n&#039;th character, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;charCodeAt1&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)&amp;lt;br&amp;gt;Returns the code of the n&#039;th character, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;indexOf0&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the index of aCharacter, using a 0-based indexing scheme; -1 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;indexOf1&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the index of aCharacter, using a 1-based indexing scheme; 0 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;lastIndexOf0&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the last index of aCharacter, using a 0-based indexing scheme; -1 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;lastIndexOf1&#039;&#039;&#039; (&#039;&#039;aCharacter&#039;&#039;)&amp;lt;br&amp;gt;Returns the last index of aCharacter, using a 1-based indexing scheme; 0 if not found&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;quote()&#039;&#039;&#039;&amp;lt;br&amp;gt;Wraps the receiver into double quotes (&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;split&#039;&#039;&#039; (&#039;&#039;separator&#039;&#039;)&amp;lt;br&amp;gt;Splits the string into a collection of substrings using the separator. Warning: the JavaScript split(xxx) function and the Smalltalk split: method have different semantics (and argument order)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substr0&#039;&#039;&#039; (&#039;&#039;index, count&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index with the given length, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substr1&#039;&#039;&#039; (&#039;&#039;index, count&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index with the given length, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring0&#039;&#039;&#039; (&#039;&#039;index1&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring0&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring between the given indices, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring1&#039;&#039;&#039; (&#039;&#039;index1&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring starting at the index, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;substring1&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a substring between the given indices, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;toLowerCase&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all chars in lower case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;toUpperCase&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all chars in upper case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trim&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all leading and trailing white space removed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trimLeft&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all leading white space removed&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aString&#039;&#039;.&#039;&#039;&#039;trimRight&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns a copy of the receiver with all trailing white space removed&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Collection (Array) ====&lt;br /&gt;
&lt;br /&gt;
Notice that Array, OrderedCollection, ByteArray, String and others are also inheriting the Collection protocol. Thus the below listed messages can also be applied to instances of those.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;concat&#039;&#039;&#039; (&#039;&#039;aCollection&#039;&#039;)&amp;lt;br&amp;gt;Returns a new collection consisting of the concatenation of the receiver and the argument&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;every&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Returns true, if &amp;quot;filterFunction&amp;quot; returns true for all elements&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;filter&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Selects elements for which &amp;quot;filterFunction&amp;quot; returns true&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;forEach&#039;&#039;&#039; (&#039;&#039;function&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; for each element&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;join&#039;&#039;&#039; (&#039;&#039;seperator&#039;&#039;)&amp;lt;br&amp;gt;Joins the strings of the receiver into a new single string using the separator&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;map&#039;&#039;&#039; (&#039;&#039;function&#039;&#039;)&amp;lt;br&amp;gt;Returns a new collection collecting the results of applying &amp;quot;function&amp;quot; to each element in sequence&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;pop&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes and returns the last element of the collection. Modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;push&#039;&#039;&#039; (&#039;&#039;value&#039;&#039;)&amp;lt;br&amp;gt;Adds an element to the end of the collection. Modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce0&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 0-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce0&#039;&#039;&#039; (&#039;&#039;filterFunction, initialValue&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 0-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce1&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 1-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;reduce1&#039;&#039;&#039; (&#039;&#039;filterFunction, initialValue&#039;&#039;)&amp;lt;br&amp;gt;Applies &amp;quot;function&amp;quot; against two values, reducing from left to right. Function must be declared as: f(previousValue, currentValue, index, arr). Pass 1-based indices to the filter.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;shift&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes and returns the first element of the collection. Same as &#039;&#039;removeFirst&#039;&#039;. Notice that this modifies the receiver collection as a side effect.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;slice0&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a subcollection, using a 0-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;slice1&#039;&#039;&#039; (&#039;&#039;index1, index2&#039;&#039;)&amp;lt;br&amp;gt;Extracts a subcollection, using a 1-based indexing scheme&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;some&#039;&#039;&#039; (&#039;&#039;filterFunction&#039;&#039;)&amp;lt;br&amp;gt;Returns true, if &amp;quot;filterFunction&amp;quot; returns true for any element&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCollection&#039;&#039;.&#039;&#039;&#039;unshift&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds an element to the beginning of the collection. Same as &#039;&#039;addFirst&#039;&#039;. Notice that this modifies the receiver collection as a side effect.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript ====&lt;br /&gt;
&lt;br /&gt;
The global variable &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot; refers to either the Transcript information window (if it is open) or the standard error stream. As such, it implements most of the stream interface functions. Most noteworthy are:&lt;br /&gt;
&lt;br /&gt;
*Transcript.&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;,...)&amp;lt;br&amp;gt;Like show, but &amp;quot;%i&amp;quot; (i=1..8) sequences in the format argument are expanded by corresponding argument strings. Up to 8 arguments are allowed.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;,...)&amp;lt;br&amp;gt;Like showCR, but &amp;quot;%i&amp;quot; (i=1..8) sequences in the format argument are expanded by corresponding argument strings. Up to 8 arguments are allowed.&lt;br /&gt;
&lt;br /&gt;
and from the inherited write stream interface:&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPut&#039;&#039;&#039; (&#039;&#039;aChar&#039;&#039;)&amp;lt;br&amp;gt;Sends a single character&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPutAll&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;Sends a string&lt;br /&gt;
&lt;br /&gt;
* Transcript.&#039;&#039;&#039;nextPutLine&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;Sends a string followed by a linebreak&lt;br /&gt;
&lt;br /&gt;
Notice that if a prefix string is defined in a variable named &amp;quot;__Transcript_Prefix__&amp;quot;, that string is prepended to the output.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logger ====&lt;br /&gt;
&lt;br /&gt;
The global variable &amp;quot;&amp;lt;code&amp;gt;Logger&amp;lt;/code&amp;gt;&amp;quot; refers to an object which will handle system log messages. This is the underlying Smalltalk framework&#039;s logging mechanism, not to be confused with expecco&#039;s &#039;&#039;ActivityLog&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The Logger will filter messages according to their &#039;&#039;severity&#039;&#039;, which is one of {&amp;lt;code&amp;gt;debug, info, warn, error, fatal&amp;lt;/code&amp;gt;}. Severities are ordered as &amp;lt;code&amp;gt;debug &amp;lt; info &amp;lt; warn &amp;lt; error &amp;lt; fatal&amp;lt;/code&amp;gt;.&lt;br /&gt;
For filtering, a severityThreshold can be set, and only messages with a higher severity will be reported.&lt;br /&gt;
 &lt;br /&gt;
By default, the Logger sends its output to the &#039;&#039;stderr&#039;&#039; stream, which is usually redirected into a (log-)file when expecco runs unattended as a service or controlled by command line arguments.&lt;br /&gt;
This behavior can be changed by assigning a different logger to the global &amp;quot;Logger&amp;quot;. &lt;br /&gt;
Under Unix systems (OSX and Linux), the defaul logger can also be replaced by one which writes to the syslog facility.&lt;br /&gt;
&amp;lt;br&amp;gt;The Logger supports the following protocol:&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;debug&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs a debug message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;info&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an info message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an warning message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs an error message&lt;br /&gt;
&lt;br /&gt;
*Logger.&#039;&#039;&#039;fatal&#039;&#039;&#039; (&#039;&#039;message&#039;&#039;)&amp;lt;br&amp;gt;logs a fatal message&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Expecco Objects ===&lt;br /&gt;
Many objects internal to expecco&#039;s execution machinery are reachable via elementary code (i.e. from within an elementary-coded action&#039;s code).&lt;br /&gt;
A lot of useful and required information can be acquired by consulting these objects.&lt;br /&gt;
The anchor to all those objects is the &amp;quot;&#039;&#039;current activity&#039;&#039;&amp;quot; object.&lt;br /&gt;
&lt;br /&gt;
==== Current Activity ====&lt;br /&gt;
Within elementary code the activity instance which is executing this piece of code can be accessed via the variable &amp;quot;&amp;lt;code&amp;gt;this&amp;lt;/code&amp;gt;&amp;quot; (in Smalltalk: &amp;quot;&amp;lt;code&amp;gt;self&amp;lt;/code&amp;gt;&amp;quot;). For every executed action, a new activity object is created. It is usually alive during the execution only (i.e. it is destroyed and its memory reused automatically, after the block&#039;s action has finished).&lt;br /&gt;
&lt;br /&gt;
The current activity object supports the following functions:&lt;br /&gt;
&lt;br /&gt;
===== Reporting =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; () &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test) with infoString to be shown in the activity log. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) &amp;lt;br&amp;gt;Report a failure (in the SUT) with optional infoString to be shown in the activity log. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;success&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] ) OBSOLETE - see activitySuccess below&amp;lt;br&amp;gt;Finishes the current activity with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Finishes the current activity with success. Actually not needed, because simply returning from an action&#039;s execute method is semantically equivalent (however, this allows for early successful finish). Due to the more descriptive name, use this function instead of &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Finishes the current test case with success. Notice: this aborts the current activity and all of the callers up to the test case level. This behavior is different from activitySuccess&#039;s behavior.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; ( [&#039;&#039;infoString&#039;&#039;] )&amp;lt;br&amp;gt;Same as testPass (backward compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Logging =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logData&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Adds data to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logDataFile&#039;&#039;&#039; (&#039;&#039;fileName&#039;&#039;) &amp;lt;br&amp;gt;Adds a file attachment to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, detail) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logImageInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, image) &amp;lt;br&amp;gt;Adds an info message with an image (screendump) to the activity log. There is an option in the report generator to include those in the generated pdf-report.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;[[Settings_LoggingSettings/en|Execution-Log-Settings]]&amp;quot; dialog (by default, it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
Notice the similarity and difference between &amp;quot;error()&amp;quot; and &amp;quot;logError()&amp;quot;: both actually create a log-data entry, but &amp;quot;error()&amp;quot; stops the execution, whereas &amp;quot;logError()&amp;quot; proceeds (maybe, the naming is a bit confusing here...)&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Execution =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;) &amp;lt;br&amp;gt;Calls another action without any input values. The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter.&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;arg&#039;&#039;...) &amp;lt;br&amp;gt;Calls another action with &#039;&#039;argi&#039;&#039; input value(s). The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter. Up to 8 arguments are supported.&lt;br /&gt;
*&#039;&#039;&#039;call_with&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;inPinValues&#039;&#039;) &amp;lt;br&amp;gt;Calls another action passing input values as a collection of values. The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter.&lt;br /&gt;
*&#039;&#039;&#039;call_into&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;funcReceivingValues&#039;&#039;)&amp;lt;br&amp;gt;Not passing any input values (similar to call), for actions with multiple output values or which write multiple values. &lt;br /&gt;
*&#039;&#039;&#039;call_with_into&#039;&#039;&#039; (&#039;&#039;calledActionName&#039;&#039;, &#039;&#039;inPinValues&#039;&#039;, &#039;&#039;funcReceivingValues&#039;&#039;)&amp;lt;br&amp;gt;Similar to the above, for actions with multiple output values or which write multiple values. &lt;br /&gt;
The called action is specified by the &amp;quot;&#039;&#039;calledActionName&#039;&#039;&amp;quot; parameter which must be one of:&lt;br /&gt;
* a UUID (the called action-block&#039;s version- or function-ID), &lt;br /&gt;
* a UUID-string (the called action-block&#039;s version- or function-ID), &lt;br /&gt;
* a name-string (the called action-block&#039;s name), &lt;br /&gt;
* a direct reference to the action-block object.&lt;br /&gt;
 &lt;br /&gt;
Although giving a simple name-string is propably the easiest way to specify the action, it may lead to an error, if multiple actions are found with the same name (which never happens, if a UUID is used). If a UUID is used, this can be either the action&#039;s functional- or version-ID. If the version-ID is given, that particular action is called. If a functional-ID is given, the first action which is found to have a matching functional-ID is called. The version-ID is specific, but intolerant to reimports or changes in the called action. Therefore, you should propably use the functional-ID, if you do not want to use the action&#039;s name.&lt;br /&gt;
&amp;lt;br&amp;gt;In most &amp;quot;normal&amp;quot; situations, the action&#039;s name is unique and good enough.&lt;br /&gt;
&lt;br /&gt;
There is an automatic mechanism, to deal with renaming, in that constant action names are found and replaced. &lt;br /&gt;
Also, such action references are found via the &amp;quot;&#039;&#039;References&#039;&#039;&amp;quot; tree menu item and you&#039;ll get a warning if such an action is renamed or removed.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;&#039;&#039;inPinValues&#039;&#039;&amp;quot; argument can be either a vector (array) or a dictionary (mapping pin-name to value) of values to be passed to the input pins of the called action. An input value of &amp;quot;Void&amp;quot; (&amp;quot;void&amp;quot; in JavaScript) will be treated like an unconnected pin.&lt;br /&gt;
&lt;br /&gt;
The first variants (without the &amp;quot;into:&amp;quot; argument) return the value of the first output pin (or nil, if there are no output pins). If the output is written multiple times, an error is reported. &lt;br /&gt;
&lt;br /&gt;
The other variant expects a &amp;quot;&#039;&#039;funcReceivingValues&#039;&#039;&amp;quot; argument, which must be a JS-function or Smalltalk-Block. This function/block is called with the output pin values as arguments. For each pin, one collection containing all values written to the corresponding pin is passed to it as argument (a collection of values is passed, because the pins could be written multiple times by the action). &lt;br /&gt;
&lt;br /&gt;
For example from a Smalltalk coded action, the &amp;quot;&amp;lt;code&amp;gt;Arith [MinMax]&amp;lt;/code&amp;gt;&amp;quot; action (which has 2 outputs) can be called with:&lt;br /&gt;
 self&lt;br /&gt;
     call:&amp;quot;Arith [ MinMax ]&amp;quot; &lt;br /&gt;
     with:{ addend1 . addend2 } &lt;br /&gt;
     into:[:minOutValues :maxOutValues | &lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
        min := minOutValues first.&lt;br /&gt;
        max := maxOutputValues first.&lt;br /&gt;
     ]&lt;br /&gt;
with JavaScript code, the above would be written as:&lt;br /&gt;
 this.call_with_into(&amp;quot;Arith [ MinMax ]&amp;quot;,&lt;br /&gt;
                           [ addend1 , addend2 ], &lt;br /&gt;
                           function (minOutValues , maxOutValues) { &lt;br /&gt;
                              &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
                              min = minOutValues.first();&lt;br /&gt;
                              max = maxOutputValues.first();&lt;br /&gt;
                           })&lt;br /&gt;
or, using a lambda function, as:&lt;br /&gt;
 this.call_with_into(&amp;quot;Arith [ MinMax ]&amp;quot;,&lt;br /&gt;
                           [ addend1 , addend2 ], &lt;br /&gt;
                           (minOutValues , maxOutValues) =&amp;gt; { &lt;br /&gt;
                              &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// ... do something with the min/max values ...&amp;lt;/span&amp;gt;&lt;br /&gt;
                              min = minOutValues.first();&lt;br /&gt;
                              max = maxOutputValues.first();&lt;br /&gt;
                           })&lt;br /&gt;
In most cases, this callback function would simply store the output values into local variables, as in:&lt;br /&gt;
 execute&lt;br /&gt;
    |.. minResult maxResult ..|&lt;br /&gt;
    ...&lt;br /&gt;
    self &lt;br /&gt;
        call:&#039;Arith [ MinMax ]&#039; with:#(10 20)&lt;br /&gt;
        into:[:mins :maxes |&lt;br /&gt;
            minResult := mins first.&lt;br /&gt;
            maxResult := maxes first.&lt;br /&gt;
        ].&lt;br /&gt;
    ...&lt;br /&gt;
    do something with minResult and maxResult&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Exceptions in the called action can be handled in the calling action:&lt;br /&gt;
     ...&lt;br /&gt;
    [&lt;br /&gt;
        result := self call:&#039;Arith [ Quotient ]&#039; with:{ dividend . 0}.&lt;br /&gt;
    ] on:ZeroDivide do:[:ex |&lt;br /&gt;
        Transcript showCR:&#039;a division by zero occurred&#039;.&lt;br /&gt;
    ].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Notice, that a test-fail verdict is reported as TestFail, which is a subclass of Exception, &lt;br /&gt;
whereas a test-error verdict is reported as TestError, which is a subclass of Error.&lt;br /&gt;
Thus, to handle both failure and error in one handler, you may write:&lt;br /&gt;
    ...&lt;br /&gt;
    [&lt;br /&gt;
        result := self call: ...&lt;br /&gt;
    ] on:(Error, Exception) do:[:ex |&lt;br /&gt;
        Transcript showCR:&#039;either error or fail&#039;.&lt;br /&gt;
    ].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
or in JS:&lt;br /&gt;
    ...&lt;br /&gt;
    try {&lt;br /&gt;
        result = call( ... )&lt;br /&gt;
    } catch(Error + Exception) {&lt;br /&gt;
        Transcript.showCR(&amp;quot;either error or fail&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
===== Reflection, Information, Queries and Accessing =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activityCreator&#039;&#039;&#039; () &amp;lt;br&amp;gt;The triggering activity (i.e. the caller). Except for special tricks, this is only useful to generate nice print messages (such as &amp;quot;activity foo, called from bar&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activityProcess&#039;&#039;&#039; () &amp;lt;br&amp;gt;The thread executing the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;blockDescription&#039;&#039;&#039; () &amp;lt;br&amp;gt;The definition of the activity (i.e. the tree definition item of the action&#039;s step)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;executor&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the current executor. See [[#Executor Functions|&amp;quot;Executor Functions&amp;quot;]] below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueForPin&#039;&#039;&#039; (&#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueFor&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin by name. Reports an error, if there is no such pin, the pin is unconnected or has no value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inputValueFor_ifAbsent&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;)&amp;lt;br&amp;gt;The value of a certain pin by name. Returns &amp;quot;ifAbsentValue&amp;quot; if there is no such pin, the pin is unconnected or has no value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inventory&#039;&#039;&#039; () &amp;lt;br&amp;gt;The inventory of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resources&#039;&#039;&#039; () &amp;lt;br&amp;gt;All resources which have been acquired for the activity (as specified in the resource-definition of the action). Retrieves a collection of Resource objects, as described below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resourcesForId&#039;&#039;&#039; (&#039;&#039;skillId&#039;&#039;) &amp;lt;br&amp;gt;Resources which have been acquired for one particular skill-requirement. The argument &#039;&#039;skillId&#039;&#039; corresponds to the name as specified in the first column of the resource definition of the action). Notice, that a collection of Resource objects is returned - even if only one resource has been acquired.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;step&#039;&#039;&#039; () &amp;lt;br&amp;gt;The corresponding step of the activity&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;stepLocalStorageAt&#039;&#039;&#039; (&amp;quot;&amp;lt;varName&amp;gt;&amp;quot;) &amp;lt;br&amp;gt;Retrieves a step&#039;s local storage value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;stepLocalStorageAt_put&#039;&#039;&#039; (&amp;quot;&amp;lt;varName&amp;gt;&amp;quot;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Defines a step&#039;s local storage value.&lt;br /&gt;
:Step local storage can be seen as a kind of static variable, which is only visible inside the code of a single execute function, but with the live time of the step. This means that the value is still present, when the step is executed the next time. However, it will vanish, whenever the diagram which contains the step is edited. Also, its value is not copied, when the step is copied. It is also not made persistent. The value will be reset to nil with every edit operation on the diagram, or via a menu function in the project&#039;s &amp;quot;More&amp;quot; menu, or the step&#039;s menu.&lt;br /&gt;
:Step local storage can be used to count the number of invocations, or to implement static state which is to be preserved between step executions.&lt;br /&gt;
:This is an experimental feature, only to be used by advanced users.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Environment Access =====&lt;br /&gt;
&lt;br /&gt;
Starting at every compound activity, a nested stack of outer environments is present, ending in a top project environment. The following activity methods provide access to some of them. This can be used to automatically setup environment variables from a configuration or when autodetecting a system-under-test&#039;s configuration and leaving the values in a defined outer environment. Depending on the intended lifetime of those values, one of the following environments should be chosen as target of such operations:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environment&#039;&#039;&#039; () &amp;lt;br&amp;gt;The currently valid environment variables of the compound step which contains this action, or (if none) of the test plan in which this action executes (see &amp;quot;[[#Environment Access|Environment Access]]&amp;quot; below)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable (in the environment as described above)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable (in the environment as describe above)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;executorEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is only present during a single testplan execution&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;projectEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is attached to the current test suite (but not persistent when the suite is saved/loaded from an ets file)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;browserEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is attached to the expecco application window; i.e. present while the window is open (i.e. the current session). (it is not made persistent)&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;systemEnvironment&#039;&#039;&#039; () &amp;lt;br&amp;gt; an environment which is present while the expecco application is running (i.e. the current session). (it is not made persistent)&lt;br /&gt;
&lt;br /&gt;
Except for the project environment, none of them are made persistent directly (i.e. the values will not saved with the &amp;quot;.ets&amp;quot;file). However, every test suite, test plan and compound block provides a description of initial values and how to compute them in their environment description, which is edited using the [[ Environment Editor ]] or which can be modified with actions from the reflection library.&lt;br /&gt;
Also, such descriptions can be saved and loaded separately from the test suite via the &amp;quot;&#039;&#039;Load/Save Parameter Set&#039;&#039;&amp;quot; menu functions of the &amp;quot;&#039;&#039;File&#039;&#039;&amp;quot; menu or via the &amp;quot;--parameters&amp;quot; [[Starting_expecco_via_Command_Line/en#Test_Parameters | command line argument]].&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Event Sending =====&lt;br /&gt;
Events can be pushed onto an event queue from either actions found in the standard library or via&lt;br /&gt;
API calls to the current activity (also from bridged elementary actions).&lt;br /&gt;
The global event handler should be already running (and especially, a handler should be registered) before the first&lt;br /&gt;
event is sent. Otherwise, the event might be ignored or an error is raised. A sample suite is found in &amp;quot;demos/d62_Event_Queue_Demos&amp;quot;.&lt;br /&gt;
 &lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;eventOrPayloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The argument may be either an instance of Event, or the payload (which is packed into an Event instance with type #default). Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or #default) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Executor Functions ====&lt;br /&gt;
&lt;br /&gt;
The executor (as returned from the current activity via the &amp;quot;&#039;&#039;executor()&#039;&#039;&amp;quot; function described above) is responsible&lt;br /&gt;
to execute steps in a network and elementary code in a controlled fashion. In addition to sequencing and assigning activities to a particular execution thread, it also cares for the activityLog and error handling.&lt;br /&gt;
Usually, you do not need to interact with an executor directly.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;executorsWorkingDirectory&#039;&#039;&#039; () &amp;lt;br&amp;gt;Temporary working directory. This is removed after the execution (i.e. useful only for very temporary files, which are generated in an action and read in another)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testplan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The currently executed testplan (nil if a block test blocks are executed)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;project&#039;&#039;&#039; () &amp;lt;br&amp;gt;Project (testsuite or library) in which the test is executed&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Resource Functions ====&lt;br /&gt;
&lt;br /&gt;
Resources can be assigned to an action as a &amp;quot;&#039;&#039;required resource&#039;&#039;&amp;quot;, and the execution will be synchronized with the&lt;br /&gt;
allocation and reservation of a particular resource as acquired from an inventory.&lt;br /&gt;
Once allocated, the resources are available to the action via &#039;&#039;resources()&#039;&#039; or &#039;&#039;resourcesForId()&#039;&#039; functions:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resources&#039;&#039;&#039; () &amp;lt;br&amp;gt;retrieves the set of resources allocated for the action. The collection is keyed by the name as given in the &amp;quot;Resources&amp;quot; tab, the associated value is a resource instance providing the concrete values of the resource&#039;s skills.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;resourceForId&#039;&#039;&#039; (idString) &amp;lt;br&amp;gt;retrieves the resource allocated for the idString as given in the &amp;quot;Resources&amp;quot; tab, the returned value is a resource instance providing the concrete values of the resource&#039;s skills.&lt;br /&gt;
&lt;br /&gt;
Resource instances respond to the following protocol:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the resource&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;skillNamed&#039;&#039;&#039; (&#039;&#039;nameOrUUID&#039;&#039;) &amp;lt;br&amp;gt;Fetch a concrete skill-value of that resource. The argument can be either a skill&#039;&#039;s name, or the functional-UUID of the skill element (in the project tree).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;skillAttributeNamed&#039;&#039;&#039; (&#039;&#039;name&#039;&#039;) &amp;lt;br&amp;gt;Fetch a concrete skill-attribute-value of the resource&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Test Suite (Project) Functions ====&lt;br /&gt;
&lt;br /&gt;
Every activity, step or action has a reference to its containing project (or library, if imported).&lt;br /&gt;
The direct enclosing project/library is returned by the &amp;quot;project()&amp;quot; function, the top level project (i.e. the loaded suite) via the &amp;quot;topProject()&amp;quot; call.&lt;br /&gt;
Projects, Test Suites and Libraries are all the same kind of object (i.e. any project can be used as a test suite or imported into another as imported library). &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;documentation&#039;&#039;&#039; () &amp;lt;br&amp;gt;The documentation or nil&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testSuite independent of its name (remains constant after change)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;projectsWorkingDirectory&#039;&#039;&#039; () &amp;lt;br&amp;gt;Project directory - i.a. all attachments. This directory is created when a project file is loaded and is deleted when expecco is closed. Do not use it for permanently needed files.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;modelLanguageStringFor&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;)&amp;lt;br&amp;gt;translates a string according to the model-language translation table&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testSuite in exactly this version. (changed with any edit operation)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithName&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039;) &amp;lt;br&amp;gt;Retrieve an element by name&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithId&#039;&#039;&#039; (&#039;&#039;aUUID&#039;&#039;) &amp;lt;br&amp;gt;Retrieve an element by its version id&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;elementWithFunctionalId&#039;&#039;&#039; (&#039;&#039;aUUID&#039;&#039;)&amp;lt;br&amp;gt;Retrieve an element by its functional id&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aProject&#039;&#039;.&#039;&#039;&#039;typeNamed&#039;&#039;&#039; (&#039;&#039;aTypeName&#039;&#039;)&amp;lt;br&amp;gt;Retrieve a datatype. To instantiate a type, write&amp;lt;br&amp;gt;&amp;quot;&amp;lt;code&amp;gt;(self project typeNamed:&#039;Foo&#039;) new&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Testplan Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;documentation&#039;&#039;&#039; () &amp;lt;br&amp;gt;The documentation or nil&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Testplan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; () &amp;lt;br&amp;gt;A collection of tags of the testplan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testplan independent of its name (remains constant after change)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aTestPlan&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; () &amp;lt;br&amp;gt;A unique ID which defines this testplan in exactly this version. (changed with any edit operation)&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Step Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Step&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; () &amp;lt;br&amp;gt;A collection of tags of the Step&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPins&#039;&#039;&#039;() &amp;lt;br&amp;gt;A collection with all input pins&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPinForPinName&#039;&#039;&#039;(&#039;&#039;inputPinName&#039;&#039;) &amp;lt;br&amp;gt;The corresponding input pin. Raises an error, if no such input pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;inputPinForPinName_ifAbsent&#039;&#039;&#039;(&#039;&#039;inputPinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;) &amp;lt;br&amp;gt;The corresponding input pin. Returns &#039;&#039;ifAbsentValue&#039;&#039;, if no such input pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPins&#039;&#039;&#039;() &amp;lt;br&amp;gt;A collection with all output pins&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPinForPinName&#039;&#039;&#039;(&#039;&#039;outputPinName&#039;&#039;) &amp;lt;br&amp;gt;The corresponding output pin. Raises an error, if no such output pin exists.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aStep&#039;&#039;.&#039;&#039;&#039;outputPinForPinName_ifAbsent&#039;&#039;&#039;(&#039;&#039;outputPinName&#039;&#039;, &#039;&#039;ifAbsentValue&#039;&#039;) &amp;lt;br&amp;gt;The corresponding output pin. Returns &#039;&#039;ifAbsentValue&#039;&#039;, if no such output pin exists.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== &amp;lt;span id=&amp;quot;Smalltalk_PinFunctions&amp;gt;Pin Functions&amp;lt;/span&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
The input and output pins can be referenced in elementary code directly by their name.&lt;br /&gt;
The name refers to the pin - &#039;&#039;&#039;NOT&#039;&#039;&#039; the passed value (this allows for the code to check, if a value is present). For indexed pins (i.e. in steps with a variable number of pins), the collection of pins is referred to by the name, and pins are accessed via an index (1..). See more about variable pins in the section below.&lt;br /&gt;
&lt;br /&gt;
===== Common to all Pins: =====&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;datatype&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the data type of the pin (Reflection-API)&lt;br /&gt;
&lt;br /&gt;
===== Input Pins: =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value (useful to determine if there is a value if the trigger condition is &amp;quot;AndConnected&amp;quot; or &amp;quot;Or&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasEnvironmentFreezeValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has a freezeValue from an environment&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasFreezeValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has a freezeValue&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected (but not frozen)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of the pin. This is either the value received via a connection, or a constant freeze value, or an environment variable freeze value. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue, if the pin did not receive any value. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValue&#039;&#039;&#039; () - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;The pin has to be a mailbox pin. The execution of this action will be suspended until the pin receives a value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueWithTimeout&#039;&#039;&#039; (&#039;&#039;seconds&#039;&#039;) - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Like above, but the execution will only wait for the specified time limit, given in seconds. The parameter is typically an integer, but can also be a fraction (e.g. 1/3) or a floating-point number (e.g. 0.3).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;mbxPinName&#039;&#039;.&#039;&#039;&#039;consumeValue&#039;&#039;&#039; () - &#039;&#039;Mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Consumes the current value which is present at the mailbox input pin. If there is another pending input value, &amp;lt;code&amp;gt;hasValue()&amp;lt;/code&amp;gt; will continue to return true, and &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt; will return the next pending value.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins: =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered (only generates a value if the action completes successful)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected. This can be used to not perform expensive computations in an elementary action, iff no-one is interested in that value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;outPinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039; ) &amp;lt;br&amp;gt;Writes the value. If the output pin is unbuffered and connected to another step&#039;s input pin, the other step&#039;s action may be triggered (if the other step&#039;s trigger condition is fulfilled). If the output pin is buffered, the datum will be passed to the connected input, when the action has finished with success.&lt;br /&gt;
&lt;br /&gt;
===== Variable Input Pins =====&lt;br /&gt;
&lt;br /&gt;
Elementary steps can have a variable number of input pins, if the pin&#039;s schema has the &amp;quot;variable pin&amp;quot; attribute set. To change the number of pins of a step in the diagram editor, pull the pin-handle of a placed step, to add or remove pins. In elementary code, the following API call entries (to the variable pin) are provided to deal with this situation:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039; &amp;lt;br&amp;gt; now refers to a collection of pins, representing the set of pins actually present at the step. In contrast to regular pins, where pinName refers to a single pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;numberOfVariablePins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns the number of actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;size&#039;&#039;&#039; () &amp;lt;br&amp;gt; same as the above &amp;quot;numberOfVariablePins&amp;quot;&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;inputPinAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; returns the idx&#039;th actual pin of the schema pin named &amp;quot;pinName&amp;quot;. Notice this retrieves the pin for reflection queries, NOT the pin value. To get value or query if it has a value, call &#039;&#039;valueAt:&#039;&#039;() / &#039;&#039;hasValueAt&#039;&#039;(). Pin indexing starts with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;at&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; same as inputPinAt(&#039;&#039;idx&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;hasValueAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; true if the idx&#039;th variable pin is connected and has received a value. Same as &amp;lt;code&amp;gt;hasValue()&amp;lt;/code&amp;gt; for variable input pins. Indices start with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;values&#039;&#039;&#039; () &amp;lt;br&amp;gt;Retrieves the values passed to the pins as an array. The array contains nil entries for disconnected pins and those without a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valuesPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Retrieves the values as present; skips unconnected pins or those without a value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valueAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; to get the idx&#039;th pin&#039;s value; raises an error if no value was given or pin is not connected. Same as &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt; for variable input pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;valueIfPresentAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; to get the idx&#039;th pin&#039;s value, or nil if no value was given or pin is not connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueAt&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;)  -&#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;waitForValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;waitForValueAt_withTimeout&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;, &#039;&#039;seconds&#039;&#039;) - &#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;waitForValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varMbxPinName&#039;&#039;.&#039;&#039;&#039;consumeValueAt&#039;&#039;&#039; (&#039;&#039;index&#039;&#039;) - &#039;&#039;Variable mailbox pins only&#039;&#039;&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;consumeValue()&amp;lt;/code&amp;gt; for variable input mailbox pins.&lt;br /&gt;
&lt;br /&gt;
===== Variable Output Pins =====&lt;br /&gt;
&lt;br /&gt;
Starting with expecco v2.1, steps can also have a variable number of output pins, if the schema has the &amp;quot;variable output pin&amp;quot; attribute set. To change the number of pins, pull the pin-handle of a placed step, to add or remove pins. In elementary code, the following API call entries (to the variable pin) are provided to deal with this situation:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;numberOfVariablePins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns the number of actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPinAt_value&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt; write a value to the idx&#039;th output pin. Index starts with 1.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPinAt&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; returns the idx&#039;th actual pin of the schema pin named &amp;quot;pinName&amp;quot;. Notice that this retrieves the pin; to write an output value to it, call &#039;&#039;value&#039;&#039;(v) on the returned pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;at&#039;&#039;&#039; (&#039;&#039;idx&#039;&#039;) &amp;lt;br&amp;gt; same as outputPinAt(&#039;&#039;idx&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;varPinName&#039;&#039;.&#039;&#039;&#039;outputPins&#039;&#039;&#039; () &amp;lt;br&amp;gt; returns a collection of all actual pins present in the step for the (variable) schema pin named &amp;quot;pinName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Datatype Functions ====&lt;br /&gt;
&lt;br /&gt;
A datatype can be retrieved by asking a pin for its datatype using the &#039;&#039;&#039;datatype&#039;&#039;&#039; () function.&lt;br /&gt;
This is sometimes useful in elementary code, in order to instantiate a new value (given the pin) or to ask for details of the type.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;name&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the Datatype&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isAnyType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is the builtin &amp;quot;Any&amp;quot; type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isArrayType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is an &amp;quot;Array&amp;quot; type (with any element type)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isCompoundType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a compound (structure) type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isEnumType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is an enumeration type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isPrimaryType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is any builtin primary type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isRangeType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a subrange of another type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isTupleType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a tuple type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isUnionType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is a union type&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aType&#039;&#039;.&#039;&#039;&#039;isStringPrimaryType&#039;&#039;&#039; () &amp;lt;br&amp;gt;true if the datatype is the builtin &amp;quot;String&amp;quot; primary type&lt;br /&gt;
&lt;br /&gt;
==== Enum Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnumType&#039;&#039;.&#039;&#039;&#039;values&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns an array of enum-value names (symbolic)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;anEnumType&#039;&#039;.&#039;&#039;&#039;integerValueOf&#039;&#039;&#039; (&#039;&#039;elementName&#039;&#039;) &amp;lt;br&amp;gt;returns the associated integer value.&lt;br /&gt;
&lt;br /&gt;
==== Compound Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCompoundType&#039;&#039;.&#039;&#039;&#039;namedFieldDescriptions&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns an array of descriptions of the named fields (if any)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aCompoundType&#039;&#039;.&#039;&#039;&#039;indexedFieldDescriptins&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns a description of indexed fields (if any)&lt;br /&gt;
&lt;br /&gt;
Each field description can be asked for the &amp;quot;fieldName()&amp;quot;, &amp;quot;fieldType()&amp;quot; and &amp;quot;defaultValue()&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Primary Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aPrimaryType&#039;&#039;.&#039;&#039;&#039;typeClass&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the underlying Smalltalk class, of which values are instances of.&lt;br /&gt;
&lt;br /&gt;
==== Range Type Functions ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;baseType&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the underlying base type. Typically this will be the Integer primary type.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;minValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the minimum value of the range&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;aRangeType&#039;&#039;.&#039;&#039;&#039;maxValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;returns the maximum value of the range&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Functions for Any Tree- or Diagram Element ====&lt;br /&gt;
&lt;br /&gt;
These include: BlockDescriptions, Types, TestPlans, TestCases, Steps, Connections, Pins, Annotations etc.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;versionId&#039;&#039;&#039; &amp;lt;br&amp;gt;A globally unique identifier (GUID or UUID) which is changed with every modification of the item&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;functionalId&#039;&#039;&#039; &amp;lt;br&amp;gt;A globally unique identifier (GUID or UUID) which is assigned once-and-for-all to the item&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;id&#039;&#039;&#039; &amp;lt;br&amp;gt;alias for versionId().&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;tags&#039;&#039;&#039; &amp;lt;br&amp;gt;A collection of tags.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isAnnotation&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is an annotation (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isStep&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a step (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isConnection&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a connection (in a diagram)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isBlockDescription&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a block description (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isAttachment&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is any attachment (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;isFileAttachment&#039;&#039;&#039;&amp;lt;br&amp;gt;true, if it is a file attachment (in the tree)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;taggedValueAt&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;) &amp;lt;br&amp;gt;To retrieve a tagged value. These are usually preserved when objects are transported to/from other systems.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;taggedValueAt_put&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;, &#039;&#039;anObject&#039;&#039;) &amp;lt;br&amp;gt;to change a tagged value. Only a limited set of datatypes are supported: anObject must be a &#039;&#039;&#039;String&#039;&#039;&#039; or a &#039;&#039;&#039;Number&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;propertyAt&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;)&amp;lt;br&amp;gt;to retrieve an expecco property. These are expecco-internal properties. These are usually not recognized by other systems.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;object&#039;&#039;.&#039;&#039;&#039;propertyAt_put&#039;&#039;&#039; (&#039;&#039;aKey&#039;&#039;, &#039;&#039;anObject&#039;&#039;)&amp;lt;br&amp;gt;to set an expecco property. These are usually not recognized by other systems. Only a limited set of datatypes are supported: anObject must be a &#039;&#039;&#039;String&#039;&#039;&#039; or a &#039;&#039;&#039;Number&#039;&#039;&#039;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Groovy Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Groovy is an open source interpreter and compiler for a Java like scripting language which runs on top of the Java Virtual machine. For details, visit [http://groovy-lang.org/ &amp;quot;groovy-lang.org&amp;quot;] and especially the [http://groovy-lang.org/documentation.html Groovy Documentation Portal].&lt;br /&gt;
&lt;br /&gt;
Code written as a Groovy elementary block is not executed directly by expecco. Instead, the code is forwarded to a Groovy shell which runs inside a Java Virtual Machine (JVM). This may be a local JVM, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be the JVM which executes the tested application and is running physically on the SUT. &lt;br /&gt;
&lt;br /&gt;
By using Groovy blocks, expecco&#039;s basic black-box test functionality is extended to include powerful gray- and white-box tests. You can access the internals of objects inside the SUT, call its functions and even define new classes and functions and call them. Groovy is especially useful, if you have to install callback- or hooks inside the SUT, which interact back to expecco (e.g. to collect SUT-internal events and allow expecco to read those from the SUT). However, you should keep in mind that your tests may become affected by changes in the SUT and needs to be modified if interfaces change (which is a general property of white box tests, not a limitation of expecco).&lt;br /&gt;
&lt;br /&gt;
The machinery to interact with a JVM (and therefore to execute Groovy code blocks) requires the Java Bridge plugin, which is now (rel18.1) part of the basic expecco package. Groovy itself is available for free as a jar class library, which is loaded with or into the target application. The Java Bridge plugin already includes a prepackaged Groovy interpreter which can be loaded transparently into the SUT application whenever a Groovy block is executed. So except for the setting of the JVM path, no further setup or installation is required.&lt;br /&gt;
&lt;br /&gt;
=== Why use Groovy Elementary Blocks? ===&lt;br /&gt;
The Java Bridge and especially Groovy code is very useful when testing GUI frameworks, communication protocols or machine control soft- and hardware which is written in Java. Especially, if you have to call functions internal to the SUT in order to trigger actions or if you need to be informed about state changes via listeners or callbacks, Groovy is the perfect tool for the task. Note that calls into the JVM are relatively straight forward, using the method forwarding mechanism, even from Smalltalk code. However, callbacks and listeners, which usually have to be implemented as instances of special derived classes of a an abstract framework class, are hard to realize without Groovy.&lt;br /&gt;
&lt;br /&gt;
Without Groovy, you would have to add such classes to the software inside the SUT - e.g. by adding them to the tested software&#039;s jar packages, or by adding extra jar packages. In addition, you&#039;d have to provide a communication mechanism (socket, pipe or file interchange), by which your test action is able to retrieve this information.&lt;br /&gt;
&lt;br /&gt;
=== What is the Difference between a regular (expecco-) JavaScript Block and a Groovy Block? ===&lt;br /&gt;
&lt;br /&gt;
In one sentence: expecco JavaScript actions are executed inside expecco, Groovy actions inside the SUT (System Under Test) or any other external JVM (Java Virtual Machine).&lt;br /&gt;
&lt;br /&gt;
More detailed:&lt;br /&gt;
&lt;br /&gt;
Expecco&#039;s JavaScript actions are actually alternative syntactic forms of Smalltalk actions. When executed, they run inside the expecco executable and have access to any class or object inside expecco itself, or those which are passed in via input pins or environment variables.&lt;br /&gt;
&lt;br /&gt;
On the other hand, Groovy actions are &amp;quot;&#039;&#039;injected&#039;&#039;&amp;quot; (eg. downloaded) into a Java VM and execute in that object space. They cannot directly access expecco classes or objects, but instead can access all public classes and objects within the JVM in which they run, which can be the SUT (System Under Test). By means of proxy objects (which are forwarding operation-calls), expecco can deal with remote objects almost transparently: these can be returned from a Groovy action to expecco, and later be used again as arguments to other Groovy actions; i.e. they can be passed around via output- and input pins, stored in variables and inspected.&lt;br /&gt;
&lt;br /&gt;
=== What is the Difference between a Groovy Block and a Bridged Node Block? ===&lt;br /&gt;
&lt;br /&gt;
Groovy blocks execute inside a JVM (Java Virtual Machine) and can access any Java code (eg. classes inside a java application or inside a dynamically loaded jar-library).&lt;br /&gt;
&lt;br /&gt;
In contrast, Node actions are executed inside a Node (aka &amp;quot;Node.js&amp;quot;) interpreter (which is not a JVM). &lt;br /&gt;
&lt;br /&gt;
There are also slight differences in the syntax: Groovy is more Java-like, whereas Node blocks use pure JavaScript.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Compilation Mechanism and Performance Issues ===&lt;br /&gt;
When a Groovy action is executed for the very first time, the block&#039;s code is transmitted via the bridge to the Groovy shell on the target JVM as a string. There, the code is parsed and an anonymous jar is created, containing Java byte code. Thus, there is some initial overhead involved in both sending the code and more so in compiling the code in the JVM. However, for every followup call, the JVM will directly call the generated code and run at full Java speed (i.e. the execution speed is almost as if native Java code was executed), although there is still some overhead due to the interprocess communication (typically a few milliseconds for every call)&lt;br /&gt;
&lt;br /&gt;
=== Using a Single Local JVM Connection / Executing Groovy Actions on the Local Machine ===&lt;br /&gt;
By default, a Groovy action is executed on a JVM which runs on the local machine; i.e. the machine on which expecco itself is running.&lt;br /&gt;
With the execution of the very first Groovy action, a JVM is started as defined in the expecco settings dialog, then a bridge connection is established to that JVM, and the Groovy interpreter (called &amp;quot;&#039;&#039;GroovyShell&#039;&#039;&amp;quot;) is loaded and instantiated on the JVM. Then a reference to that GroovyShell object is remembered and used for all followup Groovy actions which are to execute on that local JVM.&lt;br /&gt;
This default behavior is convenient if you want to use Java support libraries for reporting, statistics or other computations, or if your SUT is running inside a local JVM, or if you want to call interface functions (protocols) which actually talk to your SUT.&lt;br /&gt;
&lt;br /&gt;
=== Using a Particular JVM Connection / Executing Groovy on a Possibly Remote Machine ===&lt;br /&gt;
If you either need to customize the JVM startup and/or your test scenario has to talk to one or multiple remote systems (or multiple java programs within one scenario), you have to setup multiple java connections, and pass the connection to use to your Groovy actions.&lt;br /&gt;
This can be done either via an input pin, or via an expecco environment variable.&lt;br /&gt;
The algorithm to provide this is as follows:&lt;br /&gt;
&lt;br /&gt;
* if the action has a pin named &amp;quot;&amp;lt;code&amp;gt;groovy&amp;lt;/code&amp;gt;&amp;quot;, and it is connected, that pin&#039;s value is used as GroovyShell handle&lt;br /&gt;
* otherwise, if the environment contains a variable named &amp;quot;&amp;lt;code&amp;gt;GROOVY&amp;lt;/code&amp;gt;&amp;quot;, that variable&#039;s value is used&lt;br /&gt;
* otherwise, a new GroovyShell is instantiated and used, on the JVM which is given by:&lt;br /&gt;
** if the action has a pin named &amp;quot;&amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt;&amp;quot;, and it is connected, that pin&#039;s value is used as Java Bridge handle&lt;br /&gt;
** otherwise, if the environment contains a variable named &amp;quot;&amp;lt;code&amp;gt;JAVA&amp;lt;/code&amp;gt;&amp;quot;, that variable&#039;s value is used&lt;br /&gt;
** finally, otherwise a local JVM connection is used (a shared singleton connection).&lt;br /&gt;
&lt;br /&gt;
This scheme makes the most common case easy, where only one single local JVM is required,&lt;br /&gt;
but still allows the flexibility to handle multiple JVMs and even multiple different GroovyShell instances within each JVM.&lt;br /&gt;
&lt;br /&gt;
To use input pins, you have to create corresponding pins manually, and the pin names MUST be &amp;quot;java&amp;quot; / &amp;quot;groovy&amp;quot;.&lt;br /&gt;
You cannot use these two reserved names as regular input pin names.&lt;br /&gt;
&lt;br /&gt;
=== Choosing another JVM Version ===&lt;br /&gt;
By default, the Groovy interpreter runs in the default Java virtual machine. That is the JWM which would be executed when&lt;br /&gt;
entering &amp;quot;&amp;lt;CODE&amp;gt;java&amp;lt;/CODE&amp;gt;&amp;quot; on the command line. To verify the version, open a command shell (or cmd.exe window) and enter&lt;br /&gt;
 java -version&lt;br /&gt;
&lt;br /&gt;
To specify another JVM, go to &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Java Bridge&#039;&#039;&amp;quot;,&lt;br /&gt;
and enter the path to a JRE (Java Runtime Environment) folder into the &amp;quot;&#039;&#039;Java Installation Path&#039;&#039;&amp;quot; field.&lt;br /&gt;
You can also enter a JDK (Java Development Kit) folder name into that field.&amp;lt;br&amp;gt;See also [[Settings_JavaBridgeSettings]].&lt;br /&gt;
&lt;br /&gt;
=== Additional JAR Class Libraries ===&lt;br /&gt;
By default, the Groovy code runs inside a JVM which has its classPath initialized from the preferences.&lt;br /&gt;
These class path preferences can be changed in the &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Project Management&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Groovy Class Path&#039;&#039;&amp;quot; settings dialog.&lt;br /&gt;
Additional jars can be added to the common classPath  (before a JVM is started) by the &amp;quot;[&#039;&#039;Add JAR to Groovy Class Path&#039;&#039;]&amp;quot; action,&lt;br /&gt;
or dynamically to a concrete already running JVM instance via the &amp;quot;[&#039;&#039;Add JAR to JVM&#039;&#039;]&amp;quot; action.&lt;br /&gt;
&lt;br /&gt;
Notice that you have to restart existing groovy connections to make such changes effective (via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Shut Down Bridge Connections&#039;&#039;&amp;quot; menu function).&lt;br /&gt;
&lt;br /&gt;
=== Groovy Code Snippets / Examples ===&lt;br /&gt;
==== Calling Existing Code in the System Under Test (SUT) via a Groovy Action====&lt;br /&gt;
&lt;br /&gt;
A Groovy block&#039;s code looks very similar to a regular JavaScript block&#039;s code (with some differences in the Groovy language). &lt;br /&gt;
However, it is executed inside a JVM, which may be inside the SUT.&lt;br /&gt;
It can therefore instantiate Java objects and call static and member functions inside the target system, if it is programmed in Java.&lt;br /&gt;
&lt;br /&gt;
For example, too call a static function named &amp;quot;&#039;&#039;foo&#039;&#039;&amp;quot; in a class named &amp;quot;&#039;&#039;MyTestClass&#039;&#039;&amp;quot;, use the following Groovy block:&lt;br /&gt;
&lt;br /&gt;
 def execute() {&lt;br /&gt;
    MyTestClass.foo(&amp;quot;hello world&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
if the class is located in another package (or especially: in one of your own), &lt;br /&gt;
use explicit package prefixes:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    javax.swing.JFrame frame = new javax.swing.JFrame();&lt;br /&gt;
    javax.swing.JButton button = new javax.swing.JButton( &amp;quot;Press Me&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
    frame.add(button);&lt;br /&gt;
    frame.setSize(300,100);&lt;br /&gt;
    frame.setVisible(true);&lt;br /&gt;
 }&lt;br /&gt;
or an import declaration:&lt;br /&gt;
&lt;br /&gt;
 import javax.swing.*;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of import definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    JFrame frame = new JFrame();&lt;br /&gt;
    JButton button = new JButton( &amp;quot;Press Me&amp;quot; );&lt;br /&gt;
 &lt;br /&gt;
    frame.add(button);&lt;br /&gt;
    frame.setSize(300,100);&lt;br /&gt;
    frame.setVisible(true);&lt;br /&gt;
 }&lt;br /&gt;
Notice that you may not remove the comment line starting with &amp;quot;// end of....&amp;quot;.&lt;br /&gt;
&amp;lt;br&amp;gt;This separator pattern has been hardcoded into the Groovy machinery to separate any class and import&lt;br /&gt;
definitions from the execution method.&lt;br /&gt;
&lt;br /&gt;
==== Defining a New Class in the System Under Test using Groovy ====&lt;br /&gt;
[[Bild:Groovy_Defining_Class1.png|thumb|300px|Drag this image into expecco]]&lt;br /&gt;
You can define your own classes in a Groovy block:&lt;br /&gt;
&lt;br /&gt;
For demonstration, let&#039;s start with a simple running example:&lt;br /&gt;
 class TestSleep {&lt;br /&gt;
   static void main(String[] args) {          &lt;br /&gt;
      println &#039;Step 1&#039;&lt;br /&gt;
      sleep(1000)&lt;br /&gt;
      println &#039;Step 2&#039;&lt;br /&gt;
      sleep(1000)&lt;br /&gt;
      println &#039;Step 3&#039;&lt;br /&gt;
   }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions -- do not remove this line unless imports above is empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    TestSleep.main(null);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Instances of new classes may be required especially to install listeners and callbacks when testing UI or server applications. A typical scenario is when you want expecco to be informed about mouse or keyboard events (MouseListener).&lt;br /&gt;
&lt;br /&gt;
Usually, instances of such classes are created in one Groovy action,&lt;br /&gt;
and passed to expecco via an output pin:&lt;br /&gt;
&lt;br /&gt;
 class MyClass extends Object {&lt;br /&gt;
    Object someState;&lt;br /&gt;
 &lt;br /&gt;
    def set_someState(Object newValue) {&lt;br /&gt;
        someState = newValue;&lt;br /&gt;
    }&lt;br /&gt;
    def get_someState() {&lt;br /&gt;
        return someState;&lt;br /&gt;
    }&lt;br /&gt;
    def String toString() {&lt;br /&gt;
        return &amp;quot;a very\nlong\nmultiline\na\nb\nstring\n&amp;quot;;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of local definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    outputPin.value( new MyClass() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Then, additional Groovy actions take that as an input value and call the classes methods:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Object myInst = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
    myInst.setSomeState(123);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
or:&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Object myInst = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
    output.value( myInst.getSomeState() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== Defining a Listener Class in the System Under Test using Groovy ====&lt;br /&gt;
A common pattern in Java communication frameworks is to define an abstract classes or interfaces which has to be subclassed by users of the framework. This pattern is common for callbacks or event listeners. The programmer has to define a listener class, create an instance of it, and register it towards the communication framework. To interact with such a framework in expecco, you will need a listener class, which responds to callbacks from the framework and either remembers them for later queries from a testcase&#039;s activity, or by directly calling back into expecco. The later is much harder to deal with, as those callbacks may come at any time, even when the test has already finished or the test is being debugged (remember that the JVM may run independent from expecco). So synchronization issues may be hard to solve. It is much easier and recommended to implement the first approach: the listener collects incoming events, until expecco is ready to process them.&lt;br /&gt;
&lt;br /&gt;
You will need an elementary Groovy block to instantiate and register the listener towards the framework similar to the conceptual code below:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a Groovy Elementary Block&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 import &amp;lt;interface or abstract class from which to inherit&amp;gt;;&lt;br /&gt;
 &lt;br /&gt;
 class MyListener extends AbstractListener {&lt;br /&gt;
    ArrayList eventQueue = new ArrayList();&lt;br /&gt;
    Object eventNotifier = new Object();&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;/**&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Called from a framework when an event occurs.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  */&amp;lt;/span&amp;gt;&lt;br /&gt;
    public void onExampleEvent(Object event) {&lt;br /&gt;
        synchronized (eventQueue) {&lt;br /&gt;
            eventQueue.add(event);&lt;br /&gt;
        }&lt;br /&gt;
        synchronized (eventNotifier) {&lt;br /&gt;
            eventNotifier.notifyAll();&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;/**&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Called from expecco to fetch next event.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  *&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * Of there is no event in the queue, blocks&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  * until an event arrives (by means of #onExampleEvent())&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;  */&amp;lt;/span&amp;gt;&lt;br /&gt;
    public Object getNextEvent() {&lt;br /&gt;
        while (true) {&lt;br /&gt;
            synchronized (eventQueue) {&lt;br /&gt;
                if (! eventQueue.isEmpty()) {&lt;br /&gt;
                    return eventQueue.remove(0);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            synchronized (eventNotifier) {&lt;br /&gt;
                try {&lt;br /&gt;
                    eventNotifier.wait();&lt;br /&gt;
                } catch (InterruptedException ie) {&lt;br /&gt;
                    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// Pass, try again&amp;lt;/span&amp;gt;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of local definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// called from expecco, to instantiate a listener&amp;lt;/span&amp;gt;&lt;br /&gt;
 def execute() {&lt;br /&gt;
    var theListener = new MyListener();&lt;br /&gt;
 &lt;br /&gt;
    framework.registerListener ( theListener );&lt;br /&gt;
    outputPin.value( theListener ); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// return it to expecco&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Make sure that the above elementary code is called from your activity diagram in the initialization/setup phase, and that the returned listener reference is either remembered in an environment variable of your suite, or passed down to the actual test case via input/output pins.&lt;br /&gt;
&lt;br /&gt;
Define an additional elementary block (here in JavaScript, but could also be Smalltalk or Groovy), which takes the listener as input pin and fetches the next event via &amp;lt;code&amp;gt;getNextEvent()&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a JavaScript Elementary Block&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 execute() {&lt;br /&gt;
    var theListener;&lt;br /&gt;
    var event;&lt;br /&gt;
  &lt;br /&gt;
    theListener = inPin.value();&lt;br /&gt;
    event = theListener.getNextEvent();&lt;br /&gt;
    outpin.value ( event );&lt;br /&gt;
 }&lt;br /&gt;
The above code blocks the test suite until an event arrives. It may be useful to add another method to query the number of received events, or to flush any previously received and already enqueued events.&lt;br /&gt;
&lt;br /&gt;
In your test case, perform any stimulation required to make the framework generate an event, so that the listener&#039;s framework entry is called.&lt;br /&gt;
Then, invoke the #getNextEvent() action to suspend execution until an incoming event arrives (you will probably set a [[DiagramElements-Pin#Timelimit Input Pin|time limit]] on that step&#039;s execution). Once this action finishes, the event is available in expecco as a reference to the real event object (remember: the event object is an object inside the remote Java machine, so what you have in expecco is a handle to that remote object).&lt;br /&gt;
&lt;br /&gt;
All getters, setters and other methods of the event&#039;s implementation can be invoked from elementary code (any of the programming languages can do that, due to the message forwarding of the bridge).&lt;br /&gt;
&lt;br /&gt;
For example, assuming that the event provides getEventID() and getMessageString() getters,&lt;br /&gt;
which can be called from a Smalltalk action with:&lt;br /&gt;
 id := theEvent getEventID. msg := theEvent getMessageString.&lt;br /&gt;
and from a JavaScript action or from another Groovy action witht:&lt;br /&gt;
 id = theEvent.getEventID(); msg = theEvent.getMessageString();.&lt;br /&gt;
&lt;br /&gt;
Also, the expecco object inspector has been enhanced to recognize those proxy bridge objects, and presents the internal state, inheritance and class protocol in a multitab fashion. This makes looking into those remote objects almost as comfortable as looking into local ones.&lt;br /&gt;
&lt;br /&gt;
==== Accessing JMX MBeans ====&lt;br /&gt;
&lt;br /&gt;
 import java.lang.management.*&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    def os = ManagementFactory.operatingSytemMXBean;&lt;br /&gt;
    def mem = ManagementFactory.memoryMXBean;&lt;br /&gt;
 &lt;br /&gt;
    Transcript.showCR(&amp;quot;OS architecture: &amp;quot; + os.arch.toString() );&lt;br /&gt;
    Transcript.showCR(&amp;quot;MEM heapUsage  : &amp;quot; + mem.heapMemoryUsage.toString() );&lt;br /&gt;
    Transcript.showCR(&amp;quot;POOLS:&amp;quot;);&lt;br /&gt;
    ManagementFactory.memoryPoolMXBeans.each { eachPool -&amp;gt;&lt;br /&gt;
        Transcript.showCR(&amp;quot;  pool name     : &amp;quot; + eachPool.name.toString() );&lt;br /&gt;
        Transcript.showCR(&amp;quot;  pool peakUsage: &amp;quot; + eachPool.peakUsage.toString() );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
Please refer to the corresponding Java documentation for details.&lt;br /&gt;
&lt;br /&gt;
==== Executing Jython, JRuby or other Script Code inside the JVM ====&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|16px]]  the following example is somewhat outdated due to the new builtin support for jython (in 19.2).&lt;br /&gt;
&lt;br /&gt;
The following example executes Jython (Python) code inside the JVM (please make sure that the jython jar is in your Groovy class path):&lt;br /&gt;
 import org.python.util.PythonInterpreter; &lt;br /&gt;
 import org.python.core.*; &lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// end of definitions -- do not remove this line unless imports above is empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 def main()&lt;br /&gt;
    throws PyException&lt;br /&gt;
 { &lt;br /&gt;
    Properties p = new Properties();&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// p.setProperty(&amp;quot;sys.path&amp;quot;, &amp;quot;/Users/cg/work/exept/bridgeFramework/javaBridge/javaBin/jython2.7.0&amp;quot;);&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    p.setProperty(&amp;quot;python.path&amp;quot;, &amp;quot;&amp;lt;path to jython2.7.0/Lib&amp;gt;&amp;quot;);&lt;br /&gt;
    p.setProperty(&amp;quot;python.home&amp;quot;, &amp;quot;&amp;lt;jython2.7.0&amp;gt;&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    Object props = System.getProperties();&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// String[] args = new String[0];&amp;lt;/span&amp;gt;&lt;br /&gt;
    String[] args = { &amp;quot;&amp;quot; };&lt;br /&gt;
    PythonInterpreter.initialize(props, p, args);&lt;br /&gt;
 &lt;br /&gt;
    PythonInterpreter interp =&lt;br /&gt;
        new PythonInterpreter();&lt;br /&gt;
 &lt;br /&gt;
    System.out.println(&amp;quot;Hello, brave new world&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;import sys&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;print sys&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    interp.set(&amp;quot;a&amp;quot;, new PyInteger(42));&lt;br /&gt;
    interp.exec(&amp;quot;print a&amp;quot;);&lt;br /&gt;
    interp.exec(&amp;quot;x = 2+2&amp;quot;);&lt;br /&gt;
    PyObject x = interp.get(&amp;quot;x&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    System.out.println(&amp;quot;x: &amp;quot;+x);&lt;br /&gt;
    System.out.println(&amp;quot;Goodbye, cruel world&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 def execute() {&lt;br /&gt;
    main();&lt;br /&gt;
 }&lt;br /&gt;
Of course, you can also write the &amp;quot;interp&amp;quot; instance to an output pin, and remember it somewhere or pass it to other actions. Then, other actions can directly invoke the &amp;quot;exec(...)&amp;quot; function, without instantiating a new interpreter.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Datatype Limitations ===&lt;br /&gt;
&lt;br /&gt;
==== Integer types ====&lt;br /&gt;
As Groovy dynamically compiles to plain Java bytecode and executes on top of a regular JVM, the integer range is limited to 32bit (64bit for &amp;quot;long int&amp;quot; types).&lt;br /&gt;
No automatic conversion between small and large integers is performed. If required, you will have to use a BigNum package and/or cast int to long int. There is currently no automatic conversion or transparent support to pass large numbers from expecco to Groovy and vice versa. Integers passed from Java to expecco will be represented as instances of the Integer type there.&lt;br /&gt;
&lt;br /&gt;
==== Limited Object Conversion to/from Groovy ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco&#039;s Smalltalk objects to Groovy, and back when returning values from Groovy. This conversion especially affects values passed to/from pins of a Groovy action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border &lt;br /&gt;
! from Smalltalk&lt;br /&gt;
! to Java and from Java&lt;br /&gt;
! to Smalltalk&lt;br /&gt;
! &lt;br /&gt;
|- &lt;br /&gt;
| String &lt;br /&gt;
| String &lt;br /&gt;
| String&lt;br /&gt;
|- &lt;br /&gt;
| Integer (up to 32/64 bit)&lt;br /&gt;
| int, long int, boxed Integer&lt;br /&gt;
| Integer&lt;br /&gt;
|- &lt;br /&gt;
| Float, Double&lt;br /&gt;
| float, double; boxed or unboxed&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Notice that Smalltalk Floats have double precision)&lt;br /&gt;
|- &lt;br /&gt;
| Fraction&lt;br /&gt;
| float, double; boxed or unboxed (danger alert: precision may be lost)&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Notice that Smalltalk Floats have double precision)&lt;br /&gt;
|- &lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|- &lt;br /&gt;
| Array of any above&lt;br /&gt;
| ArrayList of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|- &lt;br /&gt;
| other Smalltalk Object(!)&lt;br /&gt;
| -&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(!) does not work, yet: at the time of writing, Smalltalk objects other than the basic types listed above cannot be passed to Java.&lt;br /&gt;
However, the reverse direction is possible, and Smalltalk includes a mechanisms to handle (and even inspect) remote Java objects.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in Groovy ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in Groovy code.&lt;br /&gt;
And Smalltalk objects can only be passed as opaque handles to/from Groovy as described above.&lt;br /&gt;
However, all Java classes are at your hands now!&lt;br /&gt;
Some limited interaction with expecco and underlying Smalltalk objects is possible via the &amp;quot;&amp;lt;code&amp;gt;eval()&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;perform()&amp;lt;/code&amp;gt;&amp;quot; API described below.&lt;br /&gt;
&lt;br /&gt;
However, in general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), possibly an array of arrays, which is passed to a Groovy &amp;quot;interface function&amp;quot; first, which instantiates the required Java object(s). Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
=== Handling of Java (and Groovy) Objects in expecco/Smalltalk ===&lt;br /&gt;
&lt;br /&gt;
==== Java Object References (Handles) ====&lt;br /&gt;
&lt;br /&gt;
Groovy elementary function can return references to Java objects via output pins. Because the actual object is located inside a JVM (i.e. outside of expecco), these references are treated like opaque handles by the underlying Smalltalk runtime system. However, a mechanism is provided to allow for almost transparent access to the referenced object&#039;s private slots, its classes&#039; static slots, its class hierarchy and method information. The object inspector is able to present that information in a convenient way, similar to how Smalltalk objects are presented. Also methods of the Java object can be called and values returned to expecco.&lt;br /&gt;
&lt;br /&gt;
==== Message Forwarding ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk and JavaScript code can send regular messages to Java objects inside a remote JVM. This is possible via the Smalltalk &amp;quot;&amp;lt;code&amp;gt;doesNotUnderstand:&amp;lt;/code&amp;gt;&amp;quot; mechanism, which intercepts any call, sends a message to the real object (via the Java Bridge), awaits an answer and returns the result, which is usually a reference to another Java object. &lt;br /&gt;
&lt;br /&gt;
All of this is transparent to the programmer of the elementary code, except for the fact that Java method naming is different from Smalltalk. And of course a performance penalty, due to the interprocess communication, marshalling overhead and dynamic lookup via reflection on the Java side.&lt;br /&gt;
&lt;br /&gt;
==== Method Name Conversions ====&lt;br /&gt;
&lt;br /&gt;
When a message is sent from Smalltalk code to a Java object, a message translation mechanism similar to the Smalltalk &amp;lt;-&amp;gt; JavaScript mechanism is used:&lt;br /&gt;
 foo                  -&amp;gt; foo()&lt;br /&gt;
 foo:arg              -&amp;gt; foo(arg)&lt;br /&gt;
 foo:a1 _:a2 ... _:aN -&amp;gt; foo(a1, a2, ... aN) where the &amp;quot;_&amp;quot; are arbitrary strings.&lt;br /&gt;
&lt;br /&gt;
thus, to call a Java object&#039;s &amp;quot;installHandler(arg1, arg2, arg3)&amp;quot; function, you should write in Smalltalk:&lt;br /&gt;
 javaObject installHandler:arg1 _:arg2 _:arg3&lt;br /&gt;
and in JavaScript:&lt;br /&gt;
 javaObject.installhandler(arg1, arg2, arg3)&lt;br /&gt;
&lt;br /&gt;
It is obvious, that this kind of code is better written in JavaScript, being the same as a native Java call would look like.&lt;br /&gt;
&lt;br /&gt;
==== Conversion of Dynamic Smalltalk Objects to Static Java Types ====&lt;br /&gt;
&lt;br /&gt;
Inside expecco (which is running under a Smalltalk VM), all object references are dynamically typed.&lt;br /&gt;
This means, that in Smalltalk, every object holds a reference to its class and in principle, any object can be passed as argument to&lt;br /&gt;
a called function.&lt;br /&gt;
In contrast, Java requires the type of a function argument to be declared (either as a class or interface),&lt;br /&gt;
and the argument type(s) are part of a method&#039;s signature.&lt;br /&gt;
&lt;br /&gt;
Therefore, when calling a Java function from Smalltalk, the correct function must be found by reflection at execution time.&lt;br /&gt;
&lt;br /&gt;
For example, if the Java object provides two methods as in:&lt;br /&gt;
&lt;br /&gt;
 public void foo(Integer arg) { ... }&lt;br /&gt;
&lt;br /&gt;
 public void foo(Float arg) { ... }&lt;br /&gt;
&lt;br /&gt;
and it is called from Smalltalk with:&lt;br /&gt;
&lt;br /&gt;
 aJavaObjectHandle foo: 1&lt;br /&gt;
&lt;br /&gt;
then the &amp;quot;Integer&amp;quot;-argument version of foo must be called.&lt;br /&gt;
&lt;br /&gt;
Whereas if called as:&lt;br /&gt;
&lt;br /&gt;
 aJavaObjectHandle foo: 1.0&lt;br /&gt;
&lt;br /&gt;
then the &amp;quot;Float&amp;quot;-argument version is to be called.&lt;br /&gt;
&lt;br /&gt;
For this, the Java Bridge side uses reflection to scan the available methods for a best fit,&lt;br /&gt;
and transforms the passed Smalltalk argument to the best matching type before calling the actual function.&lt;br /&gt;
&lt;br /&gt;
There are some rare situations, where this automatic lookup fails or finds a wrong method.&lt;br /&gt;
For example, if same-named functions exist with&lt;br /&gt;
both a &amp;quot;&amp;lt;code&amp;gt;float&amp;lt;/code&amp;gt;&amp;quot; (unboxed) and a &amp;quot;&amp;lt;code&amp;gt;Float&amp;lt;/code&amp;gt;&amp;quot; (boxed) argument,&lt;br /&gt;
and you need to make sure which is called.&lt;br /&gt;
In such cases, you can either use a Groovy block as mediator, which calls the desired function with an explicitly casted argument, and call the Groovy block from Smalltalk (or JavaScript) or use an explicit cast operation (&amp;quot;&amp;lt;code&amp;gt;Bridge2::Cast object:o as:typeName&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==== Current IDE Limitations ====&lt;br /&gt;
&lt;br /&gt;
The Smalltalk IDE has currently only limited support to extract and present Java&#039;s static type information. Currently, there is no class- and function name completion in the editor, making elementary code development for Java/Groovy less pleasant. Therefore, for complicated setups, it is a good idea to open a specialized Java development environment (e.g. eclipse) in parallel, and test the setup code there before copy-pasting it into a Groovy block.&lt;br /&gt;
&lt;br /&gt;
Eclipse is also useful to find out class- and method names during development.&lt;br /&gt;
&lt;br /&gt;
=== Groovy Code API ===&lt;br /&gt;
&lt;br /&gt;
Groovy code supports a &#039;&#039;&#039;subset&#039;&#039;&#039; of the above activity functions, which is intended provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the elementary code executing in the remote Java VM has to make a remote procedure call back to expecco. On the JVM side, this is done very similar to the above described remote message mechanism, when messages are sent from Smalltalk to Java/Groovy. However, due to the static type system, it is not possible to call previously unknown interfaces. Therefore, only a fixed set of API entry points is supported.&lt;br /&gt;
&lt;br /&gt;
==== Attention / Warning (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
Unless explicitly prevented by the &amp;quot;&amp;lt;code&amp;gt;mayStillDoExpeccoCalls()&amp;lt;/code&amp;gt;&amp;quot; function ([[#Special_Functions (Groovy) |described below]]),&lt;br /&gt;
all called expecco functions listed below will ONLY work as expected WHILE the Groovy action is still ACTIVE (i.e. while inside the Groovy &amp;quot;&amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt;&amp;quot; function).&lt;br /&gt;
&lt;br /&gt;
The reason is that expecco ensures that handlers, which are responsible for transferring information from the Groovy code back to expecco,&lt;br /&gt;
will always be released, when the Groovy step has finished its execution.&lt;br /&gt;
This is mostly required to prevent memory leaks in the Java VM, because the observer instance object is registered inside the JVM and would remain there forever, if not unregistered. This observer object is a proxy for Java code, which implements all the functions below and forwards them (via an IPC mechanism) to expecco. One new such object is required for every Groovy action execution and if not released, they sooner or later consume huge amounts of JVM memory. Therefore by default, the observer is released after the Groovy action execution.&lt;br /&gt;
&lt;br /&gt;
In most Groovy blocks this is not a problem, except for those which install callback methods,&lt;br /&gt;
AND those callbacks get called AFTER the Groovy block has finished (for example by another Java thread),&lt;br /&gt;
AND the callback code calls one of those expecco interface functions. This includes the Transcript output functions, notifications and pin value writers.&lt;br /&gt;
&lt;br /&gt;
Unless the observer is still around, callbacks are ignored and behave like a no-operation, if called after the step has finished.&lt;br /&gt;
Of course, writing to a pin from within a callback AFTER the execute() function has finished does not work in any case (with or without a kept observer). The behavior in this case is undefined; currently, it is a no-operation, but it may be changed to raise an error in future versions.&lt;br /&gt;
&lt;br /&gt;
==== The Current Activity (Groovy) ====&lt;br /&gt;
The current activity instance is accessed as &amp;quot;&#039;&#039;this&#039;&#039;&amp;quot; inside the Groovy action code (like in an elementary JavaScript block). For every executed action, a new activity object is instantiated. It is usually alive during the execution only (i.e. it is destroyed and its memory reused automatically, after the block&#039;s action has finished). &lt;br /&gt;
&lt;br /&gt;
In Groovy (as in JavaScript or Java), if no receiver is given for a function call, &amp;quot;&#039;&#039;this&#039;&#039;&amp;quot; is the implicit receiver. Thus the statements &amp;quot;&amp;lt;CODE&amp;gt;this.logInfo(&amp;quot;hello&amp;quot;)&amp;lt;/CODE&amp;gt;&amp;quot; and &amp;quot;&amp;lt;CODE&amp;gt;logInfo(&amp;quot;hello&amp;quot;)&amp;lt;/CODE&amp;gt;&amp;quot; are equivalent.&lt;br /&gt;
&lt;br /&gt;
==== Objects are passed by Reference ====&lt;br /&gt;
Except for Strings and Numbers, objects are passed from Groovy to expecco by reference. These references can later be sent back to other Groovy actions transparently. Notice, that these references will keep the Groovy object (which is actually a Java object) alive until the reference object is garbage collected in expecco. Be aware that such references may have a very long life time, if kept in an activity log. Therefore, output pins which receive such references should either be marked as non-logging, or you should set the &amp;quot;&#039;&#039;Log Strings of Bridge Objects&#039;&#039;&amp;quot; flag in the [[Settings_LoggingSettings/en||&amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Logging&#039;&#039;&amp;quot; dialog]].&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; () &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. The infoString argument will be shown in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;]) &amp;lt;br&amp;gt;Report a failure (in the SUT) with optional infoString. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;]) &amp;lt;br&amp;gt;Report an inconclusive test (with optional infoString). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Finishes the current activity with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Finishes the current testCase with success. The optional infoString argument will be shown in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; ([&#039;&#039;infoString&#039;&#039;])&amp;lt;br&amp;gt;Same as pass(); for compatibility with bridged languages where &amp;quot;pass&amp;quot; is a reserved keyword (i.e. python).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, &#039;&#039;detail&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;, detail) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;[[Settings_LoggingSettings/en|Execution-Log-Settings]]&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco and Debugging (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inspect&#039;&#039;&#039; (&#039;&#039;javaObject&#039;&#039;) &amp;lt;br&amp;gt;Opens the expecco-inspector showing details of the argument object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;halt&#039;&#039;&#039;() or &#039;&#039;&#039;halt&#039;&#039;&#039;(&#039;&#039;message&#039;&#039;) &amp;lt;br&amp;gt;stops (breakpoint) and opens the expecco-debugger; however, this debugger cannot show the internals of the suspended Groovy code, but will only present the expecco calling chain up to the bridge call.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Ensures that the API-functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, it prevents releasing the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
:Even with mayStillDoExpeccoCalls(true), only functions which are not depending on the step&#039;s activity may be called after the activity has finished. This includes event, logging and transcript/stderr functions, but no pin access or verdict reporting functions. &lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (Groovy) ====&lt;br /&gt;
Currently, Groovy blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Groovy uses many more reserved keywords for syntax than JavaScript or Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error (&amp;quot;&amp;lt;foo&amp;gt; token not expected&amp;quot;) if you try. Be careful to not name your pins as any of: &amp;quot;in&amp;quot;, &amp;quot;return&amp;quot;, &amp;quot;class&amp;quot;, &amp;quot;private&amp;quot;, &amp;quot;public&amp;quot;, etc. As a proven best practice, add a &amp;quot;Pin&amp;quot; suffix to your pin names (i.e. name it &amp;quot;inPin&amp;quot;, instead of &amp;quot;in&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (Groovy) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (Groovy) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- *&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Groovy) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Groovy code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;writeLine&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;print&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;println&#039;&#039;&#039; (&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;println&#039;&#039;&#039; ()&amp;lt;br&amp;gt;For compatibility with Java&#039;s PrintStream protocol (expecco 2.8).&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Node.js (Bridged) Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Node.js is an open source interpreter for JavaScript. For details on the language and libraries, visit [https://www.w3schools.com/nodejs &amp;quot;NodeJS Tutorial&amp;quot;] .&lt;br /&gt;
&amp;lt;br&amp;gt;You have to download and install &amp;quot;node&amp;quot; separately - the interpreter is not part of the expecco installation procedure (see [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]]) and [https://nodejs.org/en/download/ https://nodejs.org/en/download] ).&lt;br /&gt;
&lt;br /&gt;
Node.js code execution in expecco is supported via 2 different mechanisms:&lt;br /&gt;
* Node.js Bridged Action Blocks - these look at the outside like regular action blocks with typed input and output pins, which are available inside the action&#039;s code via &amp;quot;&amp;lt;code&amp;gt;.value()&amp;lt;/code&amp;gt;&amp;quot; APIs. The bridge-partner in which the code is to be executed is started once and will remain an active process until terminated. Any state (data) created inside the bridge remains alive while the partner is running and the connection is alive.&lt;br /&gt;
* [[ElementaryBlock_Element/en#Node.js-Script_Blocks | Node.js-Script Action Blocks]] - these look like shell-script blocks, in that the standard input and output is used to interact with the script. For every individual script action, the script interpreter is started anew. No state is alive between and across actions (the script-interpreter is terminated after each action)&lt;br /&gt;
&lt;br /&gt;
The following describes the first kind of blocks (bridged). Node.js-Script blocks are described elsewhere, in the [[ElementaryBlock_Element/en#Node.js-Script_Blocks | Node.js-Script Blocks]] chapter.&lt;br /&gt;
&lt;br /&gt;
Code written as a Node.js elementary block is not executed directly by expecco. Instead, the code is forwarded to a node interpreter. This may be a local node process, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be on a remote system.&lt;br /&gt;
&lt;br /&gt;
=== NodeJS Datatype Limitations ===&lt;br /&gt;
Because expecco objects and Node objects live in different processes,&lt;br /&gt;
no direct object access is possible between the two partners. &lt;br /&gt;
When objects are passed via an input pin from expecco to Node, or via an output pin from Node to expecco, the object is either converted to JSON on the sender side and reconstructed on the receiver side, or it is passed by reference, in that the sender transmits a &amp;quot;handle&amp;quot; (which is some unique number) to the partner.&lt;br /&gt;
&lt;br /&gt;
Since the class system / object model is different, not all objects are exactly representable on the other side, and some information may be lost. If required, additional information must be explicitly passed (eg. by generating a string representation &#039;&#039;manually&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
==== Limited NodeJS Object Conversion ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco&#039;s Smalltalk objects to NodeJS, and back when returning values from NodeJS. This conversion especially affects values passed to/from pins of a NodeJS action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border&lt;br /&gt;
! from Smalltalk&lt;br /&gt;
! to NodeJS and from NodeJS&lt;br /&gt;
! to Smalltalk&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(node ONLY supports IEEE double numbers)&lt;br /&gt;
| Float&lt;br /&gt;
| Float&lt;br /&gt;
|-&lt;br /&gt;
| Float, Double&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Fraction&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|-&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|-&lt;br /&gt;
| -&lt;br /&gt;
| any&lt;br /&gt;
| any NodeJS object as Reference&amp;lt;br&amp;gt;via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;fetch in Node via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Filename&lt;br /&gt;
| String (i.e. pathname)&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| arbitrary Smalltalk Object (!)&lt;br /&gt;
| Object with slots&lt;br /&gt;
| Dictionary with slots&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(-) does not work. In general, only objects which can be represented by JSON can be transmitted between expecco and the node action.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in NodeJS ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in NodeJS code.&lt;br /&gt;
And only a subset of Smalltalk objects (those which can be represented as JSON string) can be passed to/from NodeJS as described above.&lt;br /&gt;
However, all node.js code (packages/modules) are at your hands now!&lt;br /&gt;
&lt;br /&gt;
In general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), possibly an array of arrays.&lt;br /&gt;
Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
It is also possible to pass Node-object-references from the Node interpreter to expecco, and pass it back to the Node interpreter later (usually in another action).&lt;br /&gt;
This is used to get connection, protocol or device handles from Node, and pass them to other (transmission or control) actions later.&lt;br /&gt;
&lt;br /&gt;
==== Limited Error Reporting ====&lt;br /&gt;
Notice, that arithmetic errors are usually not reported by Node. &lt;br /&gt;
Dividing by zero or taking the logarithm of a negative number will deliver a Nan (&amp;quot;Not a Number&amp;quot;) instead of raising an error. Thus you have to explicitly check the result from such computations in your code (this is different in expecco&#039;s builtin JavaScript actions, where an error is reported).&lt;br /&gt;
&lt;br /&gt;
=== Debugging NodeJS Actions ===&lt;br /&gt;
Some debugging facilities are provided to support development of Node code.&lt;br /&gt;
If your code contains an endless loop, you can interrupt the Node interpreter&lt;br /&gt;
(via the &amp;quot;&#039;&#039;Interrupt Execution&#039;&#039;&amp;quot; button at the top right)&lt;br /&gt;
and get a debugger window, showing the call stack and local variables.&lt;br /&gt;
&lt;br /&gt;
However, there are situations, when the Node interpreter gets completely locked up and ceases to react.&lt;br /&gt;
In this situation, you will have to shut down the Node interpreter via the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Node JS&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Close Connections&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Of course, this also implies, that any state inside the Node interpreter is lost, and you&#039;ll have to rerun your test setup from the start.&lt;br /&gt;
&lt;br /&gt;
===== Debugger Functions =====&lt;br /&gt;
Currently, you cannot look &amp;quot;into&amp;quot; objects, and you cannot modify the local variables.&lt;br /&gt;
The debugger looks very similar to the Smalltalk/JavaScript debugger&lt;br /&gt;
and supports &#039;&#039;continue&#039;&#039;, &#039;&#039;line stepping&#039;&#039;, &#039;&#039;stepping into called functions&#039;&#039;, &#039;&#039;stepping out of called functions&#039;&#039;,&lt;br /&gt;
&#039;&#039;aborting an activity&#039;&#039; and &#039;&#039;terminating&#039;&#039; the whole node-interpreter.&lt;br /&gt;
&lt;br /&gt;
===== Limitations of the Debugger =====&lt;br /&gt;
One problem which is encountered with the current node version is that the breakpoint line numbers&lt;br /&gt;
are sometimes off-by-one; this means, that the line reported by the node-debugger is wrong and&lt;br /&gt;
therefore also shown wrong in the debugger. This is a problem of the particular node version,&lt;br /&gt;
and may or may not appear in your concrete installation (i.e. node interpreter version).&lt;br /&gt;
&lt;br /&gt;
Sorry, but we cannot currently provide a workaround for this problem, as we have not yet figured out,&lt;br /&gt;
what constellation of source-code/statement/situation leads to this problem. &lt;br /&gt;
(this problem was also reported by other node users in the internet forums).&lt;br /&gt;
&lt;br /&gt;
=== NodeJS Code API ===&lt;br /&gt;
&lt;br /&gt;
NodeJS code supports a &#039;&#039;&#039;subset&#039;&#039;&#039; of the above activity functions, which is intended provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the code executing in the remote Node interpreter has to make a remote procedure call back to expecco. On the Node side, this is done very similar to the above described remote message mechanism, when messages are sent from expecco to a bridge.&lt;br /&gt;
Also notice, that due to the single threaded nature of Node programs, all functions which ask for a value from expecco (eg. &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot;) will take a callback argument, which is called when the return value arrives.&lt;br /&gt;
&lt;br /&gt;
Be remonded that the objects described below are proxy objects inside node, which will forward messages back to expecco when functions listed below are called on them. Due to the roundtrip times, these will be relatively slow (in the order of milliseconds).&lt;br /&gt;
&lt;br /&gt;
==== Variables seen by the Executed Node Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Logger &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;info()/warn()/error()/fatal()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Logger object (see Logger)&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
&lt;br /&gt;
==== Reporting (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. &amp;lt;br&amp;gt;If the infoString argument contains &amp;quot;%i&amp;quot; placeholders (&amp;quot;%1&amp;quot;,&amp;quot;%2&amp;quot;,...), these will be expanded by the remaining arguments.&amp;lt;br&amp;gt;(eg. &amp;lt;code&amp;gt;logFail(&amp;quot;foo:%1 bar:%2&amp;quot;, 123, 234.0)&amp;lt;/code&amp;gt; will generate the failure string &amp;quot;foo:123 bar:234.0&amp;quot;). &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;success&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;activitySuccess()&amp;quot;). Please use &amp;quot;activitySuccess&amp;quot; (&amp;quot;success&amp;quot; is not supported in all bridges due to name conflictswith other libraries. For readability, it is better to use the same name in all bridges: &amp;quot;activitySuccess&amp;quot;, which is supported on all bridges)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;,...)&amp;lt;br&amp;gt;Same as pass(); for compatibility with bridged languages where &amp;quot;pass&amp;quot; is a reserved keyword (i.e. python).&lt;br /&gt;
&lt;br /&gt;
==== Logging (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&amp;lt;br&amp;gt;Execution continues, but the test will be marked as failed.&amp;lt;br&amp;gt;If the messageString argument contains &amp;quot;%i&amp;quot; placeholders (&amp;quot;%1&amp;quot;,&amp;quot;%2&amp;quot;,...), these will be expanded by the remaining arguments.&amp;lt;br&amp;gt;(eg. &amp;lt;code&amp;gt;logFail(&amp;quot;foo:%1 bar:%2&amp;quot;, 123, 234.0)&amp;lt;/code&amp;gt; will generate the failure string &amp;quot;foo:123 bar:234.0&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a error message to the activity log.&amp;lt;br&amp;gt;Execution continues, but the test will be marked as erroneous.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds a warning to the activity log.&amp;lt;br&amp;gt;Execution continues.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...) &amp;lt;br&amp;gt;Adds an info message to the activity log.&amp;lt;br&amp;gt;Execution continues&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; (by default it is enabled).&amp;lt;br&amp;gt;Notice that the code in the bridge is suspended until the box is confirmed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;...)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (NodeJS) ====&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;nameOfAction&#039;&#039;&#039; ()&amp;lt;br&amp;gt;The name of the activity&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco (NodeJS) ====&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039;(&amp;amp;lt;actionName&amp;amp;gt;, &amp;amp;lt;arg1&amp;amp;gt;, &amp;amp;lt;arg2&amp;amp;gt;, ... &amp;amp;lt;argN&amp;amp;gt;, function(rslt...) {...});&amp;lt;br&amp;gt;Executes any other expecco action (inside expecco - not inside the node interpreter), and finally calls the callBack function, when the action has finished.&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;The callback may expect multiple rslt-arguments, to get the output values of more than one pin. However, it is currently not possible to get the values of pins which are written multiple times (i.e. an error will be reported, if that is the case)&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (NodeJS) ====&lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The payload is packed into an Event object with eventType &amp;quot;#default. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or #default) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&#039;&#039;varName&#039;&#039;, function(err, rslt) {...});&amp;lt;br&amp;gt;Fetches a value from the expecco environment which is in scope of the current activity, and finally calls the callBack function, when the value has been retrieved (passing the retrieved value as argument).&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from node actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&#039;&#039;varName&#039;&#039;, &#039;&#039;newValue&#039;&#039;, function(err) {...});&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity, and finally calls the callBack function, when the value has been stored.&amp;lt;br&amp;gt;Notice that this is an asynchronous callback; you should not perform any further actions after the call, but instead continue inside the callback (and signal final completion via &amp;quot;&amp;lt;code&amp;gt;activitySuccess() / error()&amp;lt;/code&amp;gt;&amp;quot; call from there).&amp;lt;br&amp;gt;The &#039;&#039;varName&#039;&#039; argument must be a string and &#039;&#039;newValue&#039;&#039; a simple object (number, boolean or string) from node actions.&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (NodeJS) ====&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039; (&amp;amp;lt;anyNodeObject&amp;amp;gt; [, &amp;lt;optionalName&amp;gt; ]) &amp;lt;br&amp;gt;Generates a reference to a NodeJS object, which can be passed to expecco as an output pin value. Such reference objects can be passed back to NodeJS later and are dereferenced there back to the original object. This is used to pass NodeJS handles (i.e. server/client handles) to expecco and later back to NodeJS. Read below about reference passing vs. value passing.&amp;lt;br&amp;gt;Notice that the nodeObject will be registered (i.e. remembered) inside the node interpreter, in order to be found later, when the reference is passed as input by another node action. When the reference is no longer needed, it should be deregistered by calling the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt; function described below.&amp;lt;br&amp;gt;Also notice, that expecco will do this automatically, when the reference object is finalized.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;releaseRef&#039;&#039;&#039; (&amp;amp;lt;nodeObjectReference&amp;amp;gt;) &amp;lt;br&amp;gt;removes the reference from the registery inside the node interpreter.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;wait&#039;&#039;&#039; () &amp;lt;br&amp;gt;Tells expecco to wait until one of the &amp;quot;&amp;lt;code&amp;gt;activitySuccess/error/fail/inconclusive&amp;lt;/code&amp;gt;&amp;quot; functions is called.&amp;lt;br&amp;gt;Use this if the action&#039;s execution is not finished when the execute() function returns, but instead will explicitly notify the finish from within a callback. This is also to be used if a pin value has to be written later by a callback function.&amp;lt;br&amp;gt;See example and description of callbacks/async functions below.&lt;br /&gt;
*&#039;&#039;&#039;waitForPin&#039;&#039;&#039; (&#039;&#039;pinName&#039;&#039;)&amp;lt;br&amp;gt;Tells expecco to wait until the given output pin receives a value. This is needed for async/await (promise resolved) pin values.&amp;lt;br&amp;gt;See example and description of callbacks/async functions below.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Make sure that the functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, do NOT release the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Javascript uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error (&amp;quot;&amp;lt;foo&amp;gt; token not expected&amp;quot;) if you try. Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;in&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;class&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;private&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;public&amp;lt;/code&amp;gt;&amp;quot;, etc.&amp;lt;br&amp;gt;As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (i.e. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (NodeJS) =====&lt;br /&gt;
&lt;br /&gt;
Currently, NodeJS blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value at the pin (the datum). Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;refValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the object referenced by the value at the pin. The pin must have received a reference. Raises an error if the pin did not receive any value. Use this to pass back the original reference object to expecco. The input pin must have received a reference to a Node object as generated previously by &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;. Read below about reference passing vs. value passing. &lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, null otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (NodeJS) =====&lt;br /&gt;
&lt;br /&gt;
Currently, NodeJS blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin is connected (this can be used to prevent writing output values and thus speed up the execution, especially if big arrays of data values are generated)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (NodeJS) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Node code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
In addition, stdout (console.log) and stderr (console.error) are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Reference passing vs. value passing of Node objects to expecco ===&lt;br /&gt;
&lt;br /&gt;
When values are passed via an output pin from Node to expecco, two mechanisms are possible:&lt;br /&gt;
* pass by value&amp;lt;br&amp;gt;The object&#039;s JSON string is generated and passed to expecco. There, the JSON encoding is decoded and a corresponding expecco object is constructed. Conceptional, the expecco object is a copy of the original object.&lt;br /&gt;
&lt;br /&gt;
* pass by reference&amp;lt;br&amp;gt;The object is remembered inside Node, and a reference is passed to expecco. Whenever this reference object is later sent to Node again (via an input pin), the original Node object is retrieved and passed to the JavaScript code. This mechanism preserves the object&#039;s identity on the Node side and must be used for object handles (such as protocol handles).&lt;br /&gt;
&lt;br /&gt;
The default mechanism is &amp;quot;&#039;&#039;pass by value&#039;&#039;&amp;quot;. To pass a reference, use &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass the generated reference to an output pin.&lt;br /&gt;
==== Example (NodeJS) ====&lt;br /&gt;
The following code snippet sends an object&#039;s reference to an output pin:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... generate a handle object ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    outputPin.value( makeRef (someHandle , &amp;quot;aNodeHandle&amp;quot; ) );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the returned handle can later be sent via an input pin to another Node action, and used transparently there:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var handle = inputPin.value();&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
occasionally, it is required that a reference which was received via an input pin must later be sent to an output pin again, preserving the original reference. This is to prevent additional memory allocations which would result from calling &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; again (you would get multiple references to the same object).&lt;br /&gt;
For this, use &amp;quot;&amp;lt;code&amp;gt;inputPin.refValue()&amp;lt;/code&amp;gt;&amp;quot; and send this to an output pin without a &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var handle = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// send the original reference to the output&amp;lt;/span&amp;gt;&lt;br /&gt;
     outputPin.value( inputPin.refValue() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Finally, you want to release the reference inside the node interpreter, to prevent memory leaks.&lt;br /&gt;
Usually, this should be called, when a handle becomes invalid (e.g. when a connection handle is closed).&lt;br /&gt;
&lt;br /&gt;
For this, call the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt;&amp;quot; function (on the node side), passing the reference instead of the referenced object.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a close-connection action block might look like:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     var reference = inputPin.refValue();&lt;br /&gt;
     var referredObject = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with referredObject ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     closeConnection( referredObject );&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// release to prevent memory leaks&amp;lt;/span&amp;gt;&lt;br /&gt;
     releaseRef(referredObject);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Asynchronous and Callback Functions  ===&lt;br /&gt;
A common pattern in node is &amp;quot;&#039;&#039;continuation passing style&#039;&#039;&amp;quot; control flow. That means, that many functions expect a function as callback argument, which is called later whenever the requested operation has finished. This is used especially with I/O and protocol related operations (such as socket connect, http requests, client connect setup etc.).&lt;br /&gt;
A similar situation arises with async functions, which somehow get a promise as value, and the promise is resolved via an await.&lt;br /&gt;
&lt;br /&gt;
If your &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; function calls any of those or is an async function which awaits on a promise, it has to tell expecco that the node-action is effectively still active when the execute function returns and that expecco should wait for an explicit finished-notification. This is done by either calling either &amp;quot;&amp;lt;code&amp;gt;wait()&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;waitForPin()&amp;lt;/code&amp;gt;&amp;quot; somewhere within the execute function. &lt;br /&gt;
&lt;br /&gt;
Then expecco will continue to wait for the action to be finished until the node code calls one of the &amp;quot;&amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;pass()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt;&amp;quot; functions (listed above) or - in case of a previous &amp;lt;code&amp;gt;waitForPin()&amp;lt;/code&amp;gt;, until that pin receives a value.&lt;br /&gt;
&lt;br /&gt;
Example 1:&amp;lt;br&amp;gt;the following code fragment represents a typical callback situation: the &amp;quot;myProtocolConnect()&amp;quot; call gets a callback, which will be called later (asynchronously), when a connection is established. However, &amp;quot;myProtocolConnect()&amp;quot; will return immediately. Without the &amp;quot;wait()&amp;quot; at the end, expecco would assume that the action has finished and would proceed with other actions (possibly without any output being written to the output pin (actually, it would later detect a value being written by an already finished action, and write a warning message to the console and the log).&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call a function which does a callback ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    myProtocolConnect( ... , function(err) {&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... callback possibly called much later ...&amp;lt;/span&amp;gt;&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco that we&#039;re done&amp;lt;/span&amp;gt;&lt;br /&gt;
        if (err) {&lt;br /&gt;
            error(&amp;quot;some error happened: &amp;quot;+err.toString());&lt;br /&gt;
        } else {&lt;br /&gt;
            outputPin.value(someConnectionHandle); &lt;br /&gt;
            success();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco to continue waiting&amp;lt;/span&amp;gt;&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Notice that callbacks can be either written as functions (with a statement body):&lt;br /&gt;
 function(err) { statement; ... statement; }&lt;br /&gt;
or as a lambda expression, where the body is an expression:&lt;br /&gt;
 (err) =&amp;gt; expression&lt;br /&gt;
&lt;br /&gt;
Example 2:&amp;lt;br&amp;gt;the following code fragment is typical for async/await functions. Similar to the above, but covered by syntactic sugar which makes this less obvious, the execute function will return early, but execute code asynchronously due to the awaited promise:&lt;br /&gt;
&lt;br /&gt;
 async function execute() {&lt;br /&gt;
    let appiumMacDriver = require(&amp;quot;appium-mac-driver&amp;quot;);  &lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// due to the async operations,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// this execute function will effectively finish when&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// the await receives the value,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// and it is written to the pin.&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// tell expecco that the function is finished when that pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// receives a value&amp;lt;/span&amp;gt;&lt;br /&gt;
    waitForPin(sessionOut);&lt;br /&gt;
 &lt;br /&gt;
    let driver = new appiumMacDriver.MacDriver();&lt;br /&gt;
    let session = driver.createSession(defaultCaps);&lt;br /&gt;
    let s = await session;&lt;br /&gt;
    sessionOut.value(s);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Example 3:&amp;lt;br&amp;gt;The following example demonstrates what happens if the &amp;quot;wait()&amp;quot; call is missing. The code below installs a callback which writes to an output pin 1 second AFTER the finished action:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     output.value(&amp;quot;Value1&amp;quot;);&lt;br /&gt;
     setTimeout(function(err) {&lt;br /&gt;
         output.value(&amp;quot;Value2&amp;quot;);&lt;br /&gt;
     }, 1000);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
the above code will lead to an error.&lt;br /&gt;
&lt;br /&gt;
The correct version is:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
     output.value(&amp;quot;Value1&amp;quot;);&lt;br /&gt;
     setTimeout(function(err) {&lt;br /&gt;
         output.value(&amp;quot;Value2&amp;quot;);&lt;br /&gt;
         success();&lt;br /&gt;
     }, 1000);&lt;br /&gt;
     wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Up to version 23.2, this situation was not always detected and could have lead to an output value being written to a same-named output pin of a followup action (iff another bridged action was triggered which was of the same type, that second action&#039;s output was sometimes written, depending on timing constraints).&amp;lt;br&amp;gt;With version 24.1, this is detected and an error message is sent to the Transcript (it cannot be reported as an error in the activity log, because the first action which is responsible has already finished, whereas the second action (which is innocent) cannot be blamed for that).&lt;br /&gt;
&lt;br /&gt;
=== Calling other Expecco Actions  ===&lt;br /&gt;
Any expecco action (i.e. elementary or compound) can be called from Node code.&lt;br /&gt;
However, as node uses a callback mechanism, the code looks a bit different from other languages, in that an additional callback argument is to be passed. You can pass either the name or the UUID of the activity which is to be called.&lt;br /&gt;
Arguments are passed to the called action&#039;s input pin (top to bottom).&lt;br /&gt;
&lt;br /&gt;
For now, there is a limitation, in that only a single value (per pin) can be passed to the callback (i.e. you cannot get the values of pins which are written multiple times).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  function execute() {&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call an expecco activity ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    call(&amp;quot;myAction&amp;quot;, 100, 200 , &lt;br /&gt;
        function(result) {&lt;br /&gt;
            &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... callback gets the first value from myAction&#039;s first output pin ...&amp;lt;/span&amp;gt;&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Notice, that in order to get a sequence of calls, the code needs nested functions, as in:&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &lt;br /&gt;
    call(&amp;quot;myAction1&amp;quot;, 1000, 2000, &lt;br /&gt;
        function(rslt1) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;after first call: &amp;quot;+rslt1);&lt;br /&gt;
            call(&amp;quot;myAction2&amp;quot;, 10000, 20000, &lt;br /&gt;
                function(err, rslt2) {&lt;br /&gt;
                    Transcript.showCR(&amp;quot;after second call: &amp;quot;+rslt2);&lt;br /&gt;
                    success();&lt;br /&gt;
                });&lt;br /&gt;
            &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
If the called action has multiple output pins, provide a callback function which expects more than one rslt argument,&lt;br /&gt;
as in:&lt;br /&gt;
 function execute() {&lt;br /&gt;
    &lt;br /&gt;
    call(&amp;quot;actionWithTwoOutputPins&amp;quot;, 1000, 2000, &lt;br /&gt;
        function(valueAtPin1, valueAtPin2) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;received two values: &amp;quot;+valueAtPin1+&amp;quot; and: &amp;quot;+valueAtPin2);&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Reading expecco Environment Variables  ===&lt;br /&gt;
Expecco variables can be fetched via the &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; function. Notice, that this takes a second callback function as argument, which is called when the value is (later) received. The execution of the action proceeds with this continuation, and &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; does not return. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 function execute() {&lt;br /&gt;
    environmentAt(&amp;quot;variable1&amp;quot;, function(err, varValue) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;the variable value is: &amp;quot;+varValue);&lt;br /&gt;
            success();&lt;br /&gt;
    });&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// not reached&amp;lt;/span&amp;gt;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
=== Executing Node Actions in Multiple Node Interpreters ===&lt;br /&gt;
In order to test the interaction between multiple node programs, &lt;br /&gt;
or to generate load for performance tests,&lt;br /&gt;
it may be required to start multiple node interpreters,&lt;br /&gt;
and run action code in them.&lt;br /&gt;
&lt;br /&gt;
This chapter describes how to start a node interpreter and how to interact with them.&lt;br /&gt;
&lt;br /&gt;
==== Starting another Node Interpreter on the Local Machine ====&lt;br /&gt;
&lt;br /&gt;
Every Node bridge uses the given port for bridge communication plus the next port for debugging.&lt;br /&gt;
Every bridge running on the same host must use different ports.&lt;br /&gt;
The default bridge uses port 8777 (and 8778 for debugging).&lt;br /&gt;
Thus, additional bridges should be given ports incremented in steps of 2,&lt;br /&gt;
and useful ports are 8779, 8781, 8783 etc. for additional node bridges.&lt;br /&gt;
&lt;br /&gt;
===== Programmatic Start =====&lt;br /&gt;
&lt;br /&gt;
 nodeBridge := Expecco &lt;br /&gt;
                    newNodeJSBridgeConnectionForHost:hostName port:portNr &lt;br /&gt;
                    in:aDirectoryOrNil.&lt;br /&gt;
&lt;br /&gt;
===== Using an Action from the Standard Library =====&lt;br /&gt;
use the &amp;quot;&#039;&#039;Start new Local Node Bridge&#039;&#039;&amp;quot; action from the library.&lt;br /&gt;
&lt;br /&gt;
===== Executing an Action inside another Node Interpreter =====&lt;br /&gt;
&lt;br /&gt;
Either add a &amp;quot;&#039;&#039;nodejs&#039;&#039;&amp;quot; input pin to the action (passing the other node-bridge&#039;s handle) or&lt;br /&gt;
set the &amp;quot;&amp;lt;code&amp;gt;NODEJS&amp;lt;/code&amp;gt;&amp;quot; environment variable before the action.&lt;br /&gt;
An example is found in the &amp;quot;&amp;lt;code&amp;gt;d62_Event_Queue_Demos.ets&amp;lt;/code&amp;gt;&amp;quot; suite:&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Event_Queue_Demo.png|600px|]]&lt;br /&gt;
&lt;br /&gt;
=== Node Packages ===&lt;br /&gt;
&lt;br /&gt;
===Example: Installing Additional Node Packages ===&lt;br /&gt;
Use the Node package manager &amp;quot;&amp;lt;code&amp;gt;npm&amp;lt;/code&amp;gt;&amp;quot; to install packages.&lt;br /&gt;
&amp;lt;br&amp;gt;The &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Node Bridge&#039;&#039;&amp;quot; menu also contains an entry to install npm packages.&lt;br /&gt;
&amp;lt;br&amp;gt;Find packages in [https://www.npmjs.com https://www.npmjs.com].&lt;br /&gt;
&lt;br /&gt;
For example, assume you need the current city weather in a suite, navigate to &amp;quot;https://www.npmjs.com&amp;quot;, search for &amp;quot;weather&amp;quot;, find the &amp;quot;&amp;lt;code&amp;gt;city-weather&amp;lt;/code&amp;gt;&amp;quot; package and click on it. You will arrive on a page giving installation instructions and sample code at the end.&lt;br /&gt;
Scroll down to the example code and keep that page open (we can use the code later).&lt;br /&gt;
&lt;br /&gt;
Open a cmd/shell window and execute on the command line:&lt;br /&gt;
 npm install city-weather&lt;br /&gt;
&lt;br /&gt;
=== Examples: Using a Node Package in Expecco ===&lt;br /&gt;
==== Example1: Access to the City Weather Service ====&lt;br /&gt;
For a first test, we will take the original code from the example.&lt;br /&gt;
Create a new node action, and enter the code:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(&#039;Rome&#039;, function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
(you can copy-paste the sample code from the webpage)&lt;br /&gt;
&lt;br /&gt;
Open the expecco console (aka &amp;quot;Transcript&amp;quot; via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Transcript&#039;&#039;&amp;quot; menu item) and run the test.&lt;br /&gt;
A temperature should be displayed on the Transcript.&lt;br /&gt;
&lt;br /&gt;
Now add an input pin named &amp;quot;&#039;&#039;city&#039;&#039;&amp;quot;, and change the code to:&lt;br /&gt;
 ...&lt;br /&gt;
 weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
 ...&lt;br /&gt;
and try the code in the &amp;quot;&#039;&#039;Test/Demo&#039;&#039;&amp;quot; page with a few different cities at the input pin.&lt;br /&gt;
&lt;br /&gt;
Then, add an output pin named &amp;quot;&#039;&#039;temperature&#039;&#039;&amp;quot;, and change the code again to:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
         temperature.value( temp );&lt;br /&gt;
     });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
if you now execute this action, you will notice, that the output pin does NOT get the value.&lt;br /&gt;
The reason is, that the pin is written by a node-callback function, which is called at a time after the action&#039;s &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; function has already finished.&lt;br /&gt;
Thus, we have to tell expecco, that it should wait until the callback is actually called.&lt;br /&gt;
For this, you should add a call to the &amp;quot;&amp;lt;code&amp;gt;wait()&amp;lt;/code&amp;gt;&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
This tells expecco, that the execute-function is not complete, and will wait for one of the &amp;quot;&amp;lt;code&amp;gt;success/fail/error&amp;lt;/code&amp;gt;&amp;quot; functions to be called.&lt;br /&gt;
So we also have to add a call to &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot; inside the callback (otherwise, expecco would wait forever).&lt;br /&gt;
&lt;br /&gt;
Thus, we change the code to:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
     weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
         console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&lt;br /&gt;
         temperature.value( temp );&lt;br /&gt;
         success();&lt;br /&gt;
     });&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
As a final step, you should remove or comment the call to &amp;quot;&amp;lt;code&amp;gt;console.log()&amp;lt;/code&amp;gt;&amp;quot; and add some error reporting, in case a city was not found:&lt;br /&gt;
 var weather = require(&amp;quot;city-weather&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
 function execute() {&lt;br /&gt;
    weather.getActualTemp(city.value(), function(temp){&lt;br /&gt;
        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// console.log(&amp;quot;Actual temperature: &amp;quot; + temp);&amp;lt;/span&amp;gt;        &lt;br /&gt;
        if (temp == &amp;quot;City was not found&amp;quot;) {&lt;br /&gt;
            error(temp+&amp;quot;: &amp;quot;+city.value());&lt;br /&gt;
        }&lt;br /&gt;
        temperature.value( temp );&lt;br /&gt;
        success();&lt;br /&gt;
    });&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==== Example2: Access OpenStreetMap Services ====&lt;br /&gt;
This is described in a [[Node_Examples/en | separate document]].&lt;br /&gt;
&lt;br /&gt;
== Bridged Python Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Code written as a Python elementary block is not executed directly by expecco. Instead, the code is forwarded to a python interpreter. This may be a local python process, whose sole purpose is to provide additional utility functions or which provides an interface to the actual system under test (SUT), or it may be on a remote system.&lt;br /&gt;
&lt;br /&gt;
==== Python Versions ====&lt;br /&gt;
Python is available in 2 major dialects (2.x vs. 3.x) and different implementations (cPython, Jython, IronPython):&lt;br /&gt;
* use &#039;&#039;&#039;jython&#039;&#039;&#039;, if you have to interface/embed java classes or jars; &lt;br /&gt;
* use &#039;&#039;&#039;ironPython&#039;&#039;&#039;, if you have to interface with .NET assemblies; &lt;br /&gt;
* use &#039;&#039;&#039;python3&#039;&#039;&#039; to interface to modern frameworks such as Tesseract (optical character recognition), computer vision, Tensorflow (machine learning) etc.&lt;br /&gt;
* use &#039;&#039;&#039;python2&#039;&#039;&#039; for some older frameworks, which have not yet been ported to the newer python3 (notice, that support for python2 is going to cease soon)&lt;br /&gt;
 &lt;br /&gt;
Of course, if you need to interface to a Python module which is specifically written for a version, that specific version is obligatory.&lt;br /&gt;
&lt;br /&gt;
You have to download and install Python, Python3, Jython and/or IronPython separately; these interpreters are not part of the expecco installation procedure.&lt;br /&gt;
&amp;lt;br&amp;gt;See ([[Installing_additional_Frameworks/en | &amp;quot;Installing Additional Frameworks&amp;quot;]]) and download Python from [https://www.python.org/downloads https://www.python.org/downloads], &lt;br /&gt;
[https://jython.org/downloads.html http://jython.org/downloads.html] for Jython, and [ https://ironpython.net/download/] for IronPython. &lt;br /&gt;
&lt;br /&gt;
Additional frameworks may be needed as prerequisite (i.e. Java for Jython, Mono for IronPython on non-Windows machines).&lt;br /&gt;
&lt;br /&gt;
==== Bridged vs. Scripted Actions====&lt;br /&gt;
Similar to Node, Python code execution is supported via 2 different mechanisms:&lt;br /&gt;
* &#039;&#039;&#039;Bridged Python&#039;&#039;&#039; action blocks - these look at the outside like regular action blocks with typed input and output pins, which are available inside the action&#039;s code via &amp;quot;&amp;lt;code&amp;gt;.value()&amp;lt;/code&amp;gt;&amp;quot; APIs. Objects can be interchanged between expecco and the python process either by value or by reference. The bridge-partner in which the code is to be executed is started once and will remain an active process until terminated. Any state (data) created inside the bridge remains alive while the partner is running and the connection is alive.&lt;br /&gt;
* &#039;&#039;&#039;Python-Script&#039;&#039;&#039; action blocks - these look like shell-script blocks, in that the standard input and output is used to interact with the script. For every individual script action, the interpreter  (i.e. Python) is started anew. No state is alive between and across actions (the python-interpreter is terminated after each action), and no objects can be exchanged (except for very simple objects by means of reading encoded objects via stdin/stdout/stderr).&lt;br /&gt;
&lt;br /&gt;
The following describes the first kind of blocks (bridged). Script blocks are described elsewhere, in the [[ElementaryBlock_Element/en#Python_Script_Blocks | Python-Script Blocks]] chapter.&lt;br /&gt;
&lt;br /&gt;
=== Debugging Bridged Python Actions ===&lt;br /&gt;
Debug support for bridged Python actions is still being developed and more features are added with newer versions. However, there are probably better IDEs available and it might be a good idea to develop and debug Python code in your preferred IDE, and only add interface code to already debugged modules as expecco actions (this is certainly a matter of your personal preferences; in the past, interfaces to many modules have been implemented using only expecco&#039;s debug facilities). &lt;br /&gt;
&lt;br /&gt;
In order to support debugging of Python actions, you have to install either the &amp;quot;&#039;&#039;debugpy&#039;&#039;&amp;quot; or the &amp;quot;&#039;&#039;ptvsd&#039;&#039;&amp;quot; package (*) with:&lt;br /&gt;
 pip install debugpy&lt;br /&gt;
or:&lt;br /&gt;
 pip3 install debugpy&lt;br /&gt;
or:&lt;br /&gt;
 python3 -m pip install debugpy&lt;br /&gt;
&lt;br /&gt;
*) ptvsd is no longer maintained and has been replaced by the debugpy package. Ptvsd might be obsolete by the time of reading this.&lt;br /&gt;
&lt;br /&gt;
For more information on the ptvsd package, see [https://pypi.org/project/ptvsd https://pypi.org/project/ptvsd] and [https://github.com/Microsoft/ptvsd https://github.com/Microsoft/ptvsd].&lt;br /&gt;
&amp;lt;br&amp;gt;For debugpy, refer to [https://pypi.org/project/debugpy https://pypi.org/project/debugpy].&lt;br /&gt;
 &lt;br /&gt;
Notice that the debug features are currently not supported by python2 or jython.&lt;br /&gt;
&lt;br /&gt;
=== Python Datatype Limitations ===&lt;br /&gt;
&lt;br /&gt;
==== Limited Python Object Conversion ====&lt;br /&gt;
Some limited form of object conversion is automatically performed when passing expecco objects to Python, and back when returning values from Python. This conversion especially affects values passed to/from pins of a Python action.&lt;br /&gt;
&lt;br /&gt;
The following table summarizes the conversion process:&lt;br /&gt;
{|  Border&lt;br /&gt;
! from Expecco (Smalltalk)&lt;br /&gt;
! to Python and from Python&lt;br /&gt;
! to Expecco&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| Float&amp;lt;br&amp;gt;&lt;br /&gt;
| Float&lt;br /&gt;
| Float&lt;br /&gt;
|-&lt;br /&gt;
| Float, Double&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Fraction&lt;br /&gt;
| Float&lt;br /&gt;
| Float&amp;lt;br&amp;gt;(Smalltalk Floats have double precision)&lt;br /&gt;
|-&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
| Boolean&lt;br /&gt;
|-&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
| Array of any above&lt;br /&gt;
|-&lt;br /&gt;
| ByteArray&lt;br /&gt;
| Array&lt;br /&gt;
| Array&lt;br /&gt;
|-&lt;br /&gt;
| -&lt;br /&gt;
| any&lt;br /&gt;
| any Python object as Reference&amp;lt;br&amp;gt;via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Python object reference&amp;lt;br&amp;gt;as previously generated&amp;lt;br&amp;gt;by &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;fetch the reference in Python via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;or the value via &amp;quot;&amp;lt;code&amp;gt;inpin.value()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
| fetch the reference in Python via &amp;quot;&amp;lt;code&amp;gt;inpin.refValue()&amp;lt;/code&amp;gt;&amp;quot;&amp;lt;br&amp;gt;or the value via &amp;quot;&amp;lt;code&amp;gt;inpin.value()&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
| send value or reference with &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Filename&lt;br /&gt;
| String (i.e. pathname)&lt;br /&gt;
| String&lt;br /&gt;
|-&lt;br /&gt;
| arbitrary Smalltalk Object (!)&lt;br /&gt;
| Object with slots&lt;br /&gt;
| Dictionary with slots&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(-) does not work. In general, only objects which can be represented by JSON can be transmitted between expecco and the python action.&lt;br /&gt;
&lt;br /&gt;
==== No Smalltalk Classes, No Smalltalk Objects in Python ====&lt;br /&gt;
Of course, no Smalltalk class can be used directly in Python code.&lt;br /&gt;
And only a subset of Smalltalk objects (those which can be represented as JSON string) can be passed to/from Python as described above &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In general: if more complex objects need to be interchanged, this must be either done by converting them to an array (of objects), an array of arrays or a dictionary.&lt;br /&gt;
Or, alternatively to some ASCII representation (XML or JSON, for a more lightweight approach) and convert this back and forth.&lt;br /&gt;
&lt;br /&gt;
It is also possible to pass an object-reference from the Python interpreter to expecco, and pass it back to the Python interpreter later (usually in another action).&lt;br /&gt;
This is used to get connection, protocol or device handles from Python, and pass them to other (transmission or control) actions later.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt; However, such objects can still be passed to expecco as an object reference as with:&amp;lt;code&amp;gt;output.value(makeRef(obj))&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Debugging Support ====&lt;br /&gt;
Some debugging facilities are provided to support development of Node code.&lt;br /&gt;
If your code contains an endless loop, you can interrupt the Node interpreter (via the &amp;quot;Interrupt Execution&amp;quot; button at the top right)&lt;br /&gt;
and get a debugger window, showing the call stack and local variables.&lt;br /&gt;
However, there are situations, when the Python interpreter gets completely locked up and ceases to react.&lt;br /&gt;
In this situation, you will have to shut down the Python interpreter via the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Node JS&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Close Connections&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Of course, thi also implies, that any state inside the Python interpreter is lost, and you&#039;ll have to rerun your test setup from the start.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Limited Syntax Highlighting, Code Completion and Limited Debugging Support ====&lt;br /&gt;
Currently, all of those are very limited: the syntax highlighter only detects keywords and some constants as such; code completion does not work and debug support is limited.&lt;br /&gt;
&lt;br /&gt;
The bridge is meant to interface to already debugger code, not as a replacement for a full python IDE.&lt;br /&gt;
For this, you should start the bridge under your favourite IDE and connect to this already running bridge.&lt;br /&gt;
&lt;br /&gt;
=== Bridged Python Code API ===&lt;br /&gt;
&lt;br /&gt;
WARNING: Bridged Python Elementary Actions are still being developed - their behavior might be subject to changes (aka the protocol will be extended).&lt;br /&gt;
 &lt;br /&gt;
Python code may consist of function- and/or class definitions. Among the functions, there should be one named &amp;quot;&amp;lt;CODE&amp;gt;execute()&amp;lt;/CODE&amp;gt;&amp;quot;; typically, that is the last defined function, which calls into other python code. If no &amp;quot;execute&amp;quot;-function is defined, expecco tries to call &amp;quot;&amp;lt;code&amp;gt;main()&amp;lt;/CODE&amp;gt;&amp;quot; as fallback. This special behavior was added to make it easier to reuse existing script code.&lt;br /&gt;
&lt;br /&gt;
Bridged Python code can use activity functions similar to the above Groovy or Node actions.&lt;br /&gt;
The API is intended to provide an interface similar to the JavaScript and Smalltalk elementary code API. Of course, technically for every API function below, the code executing in the remote Python interpreter has to make a remote procedure call back to expecco. On the Python side, this is done very similar to the above described remote message mechanism, when messages are sent from Smalltalk to a bridge.&lt;br /&gt;
&lt;br /&gt;
==== Variables seen by the Executed Python Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Logger &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;info(), warn(), error() and fatal()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Logger object (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Dialog &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports &amp;lt;code&amp;gt;confirm(), warn(), information()&amp;lt;/code&amp;gt;; these are forwarded to the Smalltalk Dialog object (see below)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Python) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a defect (in the test). Finishes the current activity with an &#039;&#039;error&#039;&#039; verdict.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report a failure (in the SUT). Finishes the current activity.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;) &amp;lt;br&amp;gt;Report an inconclusive test. Finishes the current activity.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;testPass&#039;&#039;&#039; (&#039;&#039;infoString&#039;&#039;)&amp;lt;br&amp;gt;Finishes the current testCase with success. This has the same effect as &amp;quot;pass()&amp;quot; in other actions - its name had to be changed because &amp;quot;pass&amp;quot; is a reserved keyword in Python.&lt;br /&gt;
&lt;br /&gt;
==== Logging (Python) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039; (&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert()&#039;&#039; (for Smalltalk protocol compatibility).&lt;br /&gt;
&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (Python) ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Interaction with Expecco (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;call&#039;&#039;&#039;(&amp;amp;lt;actionName&amp;amp;gt;, &amp;amp;lt;arg1&amp;amp;gt;, &amp;amp;lt;arg2&amp;amp;gt;, ... &amp;amp;lt;argN&amp;amp;gt;);&amp;lt;br&amp;gt;Executes any other expecco action (inside expecco - not inside the Python interpreter), and returns the generated output pin values as a tuple&amp;lt;br&amp;gt;It is currently not possible to get the values of pins which are written multiple times (i.e. an error will be reported, if that is the case)&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
:Errata:&amp;lt;br&amp;gt;&lt;br /&gt;
::The call function only returns the first value of the first pin.&amp;lt;br&amp;gt;&lt;br /&gt;
::See callN below (release &amp;gt;= 26.2)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;callN&#039;&#039;&#039;(&amp;amp;lt;actionName&amp;amp;gt;, &amp;amp;lt;arg1&amp;amp;gt;, &amp;amp;lt;arg2&amp;amp;gt;, ... &amp;amp;lt;argN&amp;amp;gt;);&amp;lt;br&amp;gt;Same as &amp;lt;code&amp;gt;call&amp;lt;/code&amp;gt; above, but returns a tuple (Array) containing the first value of each output pin of the called action.&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from python actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from python actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (Python) ====&lt;br /&gt;
* &#039;&#039;&#039;pushEvent&#039;&#039;&#039; (&#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event onto the global event handler&#039;s event queue. The payload is packed into an Event object with eventType &amp;quot;&amp;lt;code&amp;gt;#default&amp;lt;/code&amp;gt;. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039; (&#039;&#039;eventTypeSymbolOrNil&#039;&#039;, &#039;&#039;payloadData&#039;&#039;) &amp;lt;br&amp;gt; pushes an event of type (or &amp;lt;code&amp;gt;#default&amp;lt;/code&amp;gt;) onto the global event handler&#039;s event queue. Raises an error, if no global event handler process is running.&lt;br /&gt;
&lt;br /&gt;
==== Special Functions (Python) ====&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039; (&amp;amp;lt;anyPythonObject&amp;amp;gt;) &amp;lt;br&amp;gt;Generates a reference to a Python object, which can be passed to expecco as an output pin value. Such reference objects can be passed back to Python later and are dereferenced there back to the original object. This is used to pass Python handles (i.e. server/client handles) to expecco and later back to Python. Read below about reference passing vs. value passing.&amp;lt;br&amp;gt;Notice that the pythonObject will be registered (i.e. remembered) inside the python interpreter, in order to be found later, when the reference is passed as input by another node action. When the reference is no longer needed, it should be deregistered by calling the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt; function described below.&amp;lt;br&amp;gt;Also notice, that expecco will do this automatically, when the reference object is finalised.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;releaseRef&#039;&#039;&#039; (&amp;amp;lt;nodeObjectReference&amp;amp;gt;) &amp;lt;br&amp;gt;removes the reference from the registery inside the Python interpreter.&amp;lt;br&amp;gt;See example below.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;wait&#039;&#039;&#039; () &amp;lt;br&amp;gt;Tells expecco to wait until one of the &amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt; functions is called.&amp;lt;br&amp;gt;Use this if a pin value has to be written later by a callback function.&amp;lt;br&amp;gt;See explanation of [[#Asynchronous_and_Callback_Functions|async callbacks]] and the example in the NodeJS API description.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;mayStillDoExpeccoCalls&#039;&#039;&#039; (&#039;&#039;boolean&#039;&#039;) &amp;lt;br&amp;gt;Make sure that the functions described here will still be callable (by Java callback functions from other threads) even after the step has finished execution. In other words, do NOT release the observer object which is responsible for the transfer of information between the two systems. Be aware that this object remains and will never be released, until the bridge connection is closed. I.e. there is a potential for a memory leak inside the Java VM here.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;bridge_inMainThread&#039;&#039;&#039; (task)&amp;lt;br&amp;gt;OS X only:&amp;lt;br&amp;gt;Task must be a lambda expression which is executed by the main thread (as opposed to the bridge connection thread).&amp;lt;br&amp;gt;This is required on eg. OS X to run code which interacts with OS X windowing framework.&amp;lt;br&amp;gt;On non-OSX systems, this executes the task directly (and also in the main thread).&amp;lt;br&amp;gt;Typical use: &amp;lt;code&amp;gt;bridge_inMainThread(lambda: someWindow.show() )&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (Python) ====&lt;br /&gt;
Currently, python blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;Python uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error if you try. Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;def&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt;&amp;quot; etc. As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (i.e. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (Python) =====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns true if the pin is connected&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the value at the pin (the datum). Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;refValue&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the object referenced by the value at the pin. The pin must have received a reference. Raises an error if the pin did not receive any value. Use this to pass back the original reference object to expecco. The input pin must have received a reference to a Python object as generated previously by &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;. Read below about reference passing vs. value passing. &lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; () &amp;lt;br&amp;gt;Returns the pin-datum if it has one, None otherwise. Similar to &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;, but avoids the exception.&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;lt;code&amp;gt;value()&amp;lt;/code&amp;gt;, but avoids the exception. Use this, if &amp;quot;None&amp;quot; is a possible value at the pin, and the code needs to distinguish between getting a &amp;quot;None&amp;quot; at the pin and not having a value at all at the pin.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039; (&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the alternativeValue if the pin did not receive any value.&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (Python) =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isBuffered&#039;&#039;&#039; () &amp;lt;br&amp;gt;True if the pin is buffered&lt;br /&gt;
 --&amp;gt;&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() (vsn 26.2)&amp;lt;br&amp;gt;Returns true if the pin is connected, false otherwise. This may be used to avoid generating output values to unconnected pins (useful if the value is expensive to compute or leads to a big data transfer).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pinName&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039; (&#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes the value.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Python) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Python code. However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;fmt&#039;&#039;, &#039;&#039;arg&#039;&#039;...)&amp;lt;br&amp;gt;Like &amp;quot;&amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt;, but &amp;quot;%i&amp;quot; sequences in the format argument are expanded by the corresponding arg strings.&lt;br /&gt;
&lt;br /&gt;
*Transcript &#039;&#039;&#039;clear&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Clears the contents of the Transcript window (new in 24.2)&lt;br /&gt;
&lt;br /&gt;
*Transcript &#039;&#039;&#039;raiseWindow&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Makes the Transcript window visible (new in 24.2)&lt;br /&gt;
&lt;br /&gt;
In addition, stdout (console.log) and stderr (console.error) are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Dialog (Python) ====&lt;br /&gt;
Some of expecco&#039;s Dialog messages are forwarded from Python:&lt;br /&gt;
*&#039;&#039;&#039;information&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;) (new in 23.2)&amp;lt;br&amp;gt;Opens an information dialog. I.e. &amp;quot;&amp;lt;code&amp;gt;Dialog.information(&amp;quot;Hello&amp;quot;)&amp;lt;/code&amp;gt; will show &amp;quot;Hello&amp;quot; in a popup dialog window.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;confirm&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a Yes/No confirmation dialog (and returns True/False)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;request&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a dialog asking for a string (and returns the entered string or None on cancel)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestPassword&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a dialog asking for a password string (and returns the entered string or None on cancel)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestFilename&#039;&#039;&#039; (&#039;&#039;msg&#039;&#039;) (new in 23.2)&amp;lt;br&amp;gt;Opens a dialog asking for a file name string (and returns the entered file name or None on cancel)&lt;br /&gt;
&lt;br /&gt;
=== Global and Static Variables ===&lt;br /&gt;
Python actions are defined within the scope of another function, to prevent accidentically overwriting/redefining any global.&lt;br /&gt;
Thus, you have to access globals via &amp;quot;globals().get(&amp;quot;name&amp;quot;)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Static Variables ====&lt;br /&gt;
Starting with v24.1, static variables (which are visible within one activity and which are preserved across calls) can be defined by&lt;br /&gt;
prepending the execute function&#039;s code with:&lt;br /&gt;
 # start of static definitions&lt;br /&gt;
 ... any variables which should be static ...&lt;br /&gt;
 # end of static definitions&lt;br /&gt;
&lt;br /&gt;
Notice that these comment lines must be written exactly as above.&lt;br /&gt;
&amp;lt;br&amp;gt;As an example, the following uses a static variable to increment a counter whenever the action is Ivoked:&lt;br /&gt;
 # start of static definitions&lt;br /&gt;
 count=0&lt;br /&gt;
 # end of static definitions&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     nonlocal count&lt;br /&gt;
 &lt;br /&gt;
     count = count + 1&lt;br /&gt;
     print(f&amp;quot;count={count}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Notice that the above example does not work in pre 24.1 versions.&lt;br /&gt;
&amp;lt;br&amp;gt;Also notice, that the static definitions are re-executed whenever the action code is changed or recompiled (i.e. that the count variable is reset to 0).&lt;br /&gt;
&lt;br /&gt;
==== Global Variables ====&lt;br /&gt;
&lt;br /&gt;
Example of a global variable that can also be used in other modules.&lt;br /&gt;
&lt;br /&gt;
Caution: Please make sure that the name of the global variable is unique in your test suite!&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     global count&lt;br /&gt;
     try:&lt;br /&gt;
         count&lt;br /&gt;
     except NameError:&lt;br /&gt;
         # Throws a NameError if not yet initialised&lt;br /&gt;
         count = 0&lt;br /&gt;
     count = count + 1&lt;br /&gt;
     print(f&amp;quot;count={count}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Printing Debug Messages in Python ===&lt;br /&gt;
Be aware, that the stdout stream is buffered in Python. Thus, debugprints generated by print might not appear immeditely.&lt;br /&gt;
&amp;lt;br&amp;gt;Eg, the following code:&lt;br /&gt;
 print(&amp;quot;start&amp;quot;)&lt;br /&gt;
 time.sleep(10)&lt;br /&gt;
 print(&amp;quot;end&amp;quot;)&lt;br /&gt;
will show both lines after the sleep.&lt;br /&gt;
&lt;br /&gt;
Use&lt;br /&gt;
 sys.stdout.flush()&lt;br /&gt;
to force messages to be passed immediately to expecco; eg:&lt;br /&gt;
 print(&amp;quot;start&amp;quot;)&lt;br /&gt;
 sys.stdout.flush()&lt;br /&gt;
 time.sleep(10)&lt;br /&gt;
 print(&amp;quot;end&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
=== Python Asynchronous and Callback Functions  ===&lt;br /&gt;
If output pins are to be written by a callback which is invoked AFTER the python function returned, the expecco activity will already be finished, and the pin will NOT be written.&lt;br /&gt;
Instead, a warning is generated in the log.&lt;br /&gt;
&lt;br /&gt;
You MUST tell expecco that the execute function has not yet finished, by calling &amp;quot;wait()&amp;quot; and signal the real activity end in the callback via one of &amp;quot;success()&amp;quot;, &amp;quot;error()&amp;quot;or &amp;quot;fail()&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For a detailed description of this mechanism, read the &lt;br /&gt;
[[#Asynchronous and Callback Functions|corresponding section]] in the Node API.&lt;br /&gt;
&lt;br /&gt;
=== Reference passing vs. value passing of Python objects to expecco ===&lt;br /&gt;
&lt;br /&gt;
When values are passed via an output pin from Python to expecco, two mechanisms are possible:&lt;br /&gt;
* pass by value&amp;lt;br&amp;gt;The object&#039;s JSON string is generated and passed to expecco. There, the JSON encoding is decoded and a corresponding expecco object is constructed. Conceptional, the expecco object is a copy of the original object.&lt;br /&gt;
&lt;br /&gt;
* pass by reference&amp;lt;br&amp;gt;The object is remembered inside Python, and a reference is passed to expecco. Whenever this reference object is later sent to Python again (via an input pin), the original Python object is retrieved and passed to the Python code. This mechanism preserves the object&#039;s identity on the Python side and must be used for object handles (such as protocol handles).&lt;br /&gt;
&lt;br /&gt;
The default mechanism is &amp;quot;&#039;&#039;pass by value&#039;&#039;&amp;quot;. &lt;br /&gt;
&amp;lt;br&amp;gt;To pass a reference, use &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass the generated reference to an output pin.&lt;br /&gt;
&lt;br /&gt;
When objects are passed from expecco to python, this is transparent. Python will automatically resolve passed in references. Thus you can send a &amp;quot;pointer&amp;quot; to an object to an output pin via &amp;quot;&amp;lt;code&amp;gt;makeRef(obj)&amp;lt;/code&amp;gt;&amp;quot; and pass it to another Python action, where the value will refer to the original object.&lt;br /&gt;
 &lt;br /&gt;
==== Example (Python) ====&lt;br /&gt;
The following code snippet sends an object&#039;s reference to an output pin:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... generate a handle object ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    outputPin.value( makeRef (someHandle ) )&lt;br /&gt;
&lt;br /&gt;
the returned handle can later be sent via an input pin to another Python action inside the same bridge, and use transparently there:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     handle = inputPin.value()&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
occasionally, it is required that a reference which was received via an input pin must later be sent to an output pin again, preserving the original reference. This is to prevent additional memory allocations which would result from calling &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; again (you would get multiple references to the same object).&lt;br /&gt;
For this, use &amp;quot;&amp;lt;code&amp;gt;inputPin.refValue()&amp;lt;/code&amp;gt;&amp;quot; and send this to an output pin without a &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     handle = inputPin.value();&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with handle ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# send the original reference to the output&amp;lt;/span&amp;gt;&lt;br /&gt;
     outputPin.value( inputPin.refValue() )&lt;br /&gt;
&lt;br /&gt;
Finally, you want to release the reference inside the Python interpreter, to prevent memory leaks.&lt;br /&gt;
Usually, this should be called, when a handle becomes invalid (e.g. when a connection handle is closed).&lt;br /&gt;
&lt;br /&gt;
For this, call the &amp;quot;&amp;lt;code&amp;gt;releaseRef&amp;lt;/code&amp;gt;&amp;quot; function (on the node side), passing the reference instead of the referenced object.&lt;br /&gt;
&amp;lt;br&amp;gt;For example, a close-connection action block might look like:&lt;br /&gt;
&lt;br /&gt;
 def execute():&lt;br /&gt;
     reference = inputPin.refValue()&lt;br /&gt;
     referredObject = inputPin.value()&lt;br /&gt;
 &lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;... do something with referredObject ...&amp;lt;/span&amp;gt;&lt;br /&gt;
     closeConnection( referredObject )&lt;br /&gt;
     &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# release to prevent memory leaks&amp;lt;/span&amp;gt;&lt;br /&gt;
     releaseRef(referredObject)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Commented: text was copy-pasted from Node; may need adoption to Python&lt;br /&gt;
=== Asynchronous and Callback Functions  ===&lt;br /&gt;
A common pattern in node is &amp;quot;&#039;&#039;continuation passing style&#039;&#039;&amp;quot; control flow. That means, that many functions expect function as callback argument, which is called later whenever the requested operation has finished. This is used especially with I/O and protocol related operations (such as socket connect, http requests, client connect setup etc.).&lt;br /&gt;
If your &amp;quot;&amp;lt;code&amp;gt;execute&amp;lt;/code&amp;gt;&amp;quot; functions calls any of those, and wants the expecco action to wait until the callback occurred, you should call the &amp;quot;wait()&amp;quot; function at the end of the execute function. &lt;br /&gt;
&lt;br /&gt;
Then expecco will continue to wait for the action to be finished until the node code calls one of the &amp;quot;&amp;lt;code&amp;gt;fail()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;error()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;success()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;pass()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;inconclusive()&amp;lt;/code&amp;gt;&amp;quot; functions (listed above).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  function execute() {&lt;br /&gt;
     ... call a function which does a callback ...&lt;br /&gt;
    myProtocolConnect( ... , function(err) {&lt;br /&gt;
        ... callback possibly called much later ...&lt;br /&gt;
        // tell expecco that we&#039;re done&lt;br /&gt;
        if (err) {&lt;br /&gt;
            error(&amp;quot;some error happened: &amp;quot;+err.toString());&lt;br /&gt;
        } else { &lt;br /&gt;
            success();&lt;br /&gt;
        }&lt;br /&gt;
    });&lt;br /&gt;
    // tell expecco to continue waiting&lt;br /&gt;
    wait();&lt;br /&gt;
 }&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Calling other Expecco Actions (Python) ===&lt;br /&gt;
Not yet implemented &lt;br /&gt;
&lt;br /&gt;
Any expecco action (i.e. elementary or compound) can be called from Python code.&lt;br /&gt;
You can pass either the name or the UUID of the activity which is to be called.&lt;br /&gt;
Arguments are passed to the called action&#039;s input pin (top to bottom).&lt;br /&gt;
&lt;br /&gt;
For now, there is a limitation, in that only a single value (per pin) can be returned (i.e. you cannot get the values of pins which are written multiple times).&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
  def execute():&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt; ... call an expecco activity ...&amp;lt;/span&amp;gt;&lt;br /&gt;
    result = call(&amp;quot;myAction&amp;quot;, 100, 200)&lt;br /&gt;
&lt;br /&gt;
=== Python2 vs. Python3 ===&lt;br /&gt;
Although python2 is going to be obsoleted soon, there are still many packages and frameworks around, which require that version. &lt;br /&gt;
&lt;br /&gt;
If all of your actions use the same python version, specify it in the &amp;quot;Python&amp;quot; field of the interpreter settings dialog.&lt;br /&gt;
Otherwise, change individual action&#039;s python version via the &amp;quot;Language&amp;quot; comboList, above the code editor (change to &amp;quot;BridgedPython2&amp;quot; or &amp;quot;BridgedPython3&amp;quot; to make it explicit).  &lt;br /&gt;
&lt;br /&gt;
Paths to the explicit versions and to the unspecific version are all defined in the pathon settings.&lt;br /&gt;
&lt;br /&gt;
=== Reading expecco Environment Variables (Python) ===&lt;br /&gt;
Expecco variables can be fetched via the &amp;quot;&amp;lt;code&amp;gt;environmentAt&amp;lt;/code&amp;gt;&amp;quot; function.&lt;br /&gt;
&amp;lt;br&amp;gt;For example:&lt;br /&gt;
 def execute():&lt;br /&gt;
    varValue = environmentAt(&amp;quot;variable1&amp;quot;)&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
=== Python Packages ===&lt;br /&gt;
You should install python packages using &amp;quot;pip&amp;quot; or &amp;quot;pip3&amp;quot;, depending on the python version, for which a package is to be installed.&lt;br /&gt;
For more information, please consult the [http://pip.pypa.io pip documentation].&lt;br /&gt;
&lt;br /&gt;
On Windows, &amp;quot;pipwin&amp;quot; seems to perform best, if additional C/C++ libraries need to be installed or compiled (eg. &amp;quot;pipwin install pyaudio&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
When installing, make sure that the packages are installed in the correct target directory, as per Python environment; i.e. if you have multiple versions of the interpreter or virtual environments, make sure that the Python as started by expecco (and defined in the settings) uses and sees the correct module path.&lt;br /&gt;
&lt;br /&gt;
===Installing Additional Python Packages ===&lt;br /&gt;
Use the Python package installer &amp;quot;&amp;lt;code&amp;gt;pip&amp;lt;/code&amp;gt;&amp;quot; (or &amp;quot;&amp;lt;code&amp;gt;pip3&amp;lt;/code&amp;gt;&amp;quot;) to install packages.&lt;br /&gt;
The &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Python Bridge&#039;&#039;&amp;quot; menu also contains an entry to install pip packages.&lt;br /&gt;
If you use virtual environments, make sure that your packages are installed in the correct location.&lt;br /&gt;
&lt;br /&gt;
Find packages in [https://pypi.org/ https://pypi.org/] or [https://docs.python.org/3/py-modindex.html https://docs.python.org/3/py-modindex.html].&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
For example, assume you need the current city weather in a suite, navigate to &amp;quot;https://www.npmjs.com&amp;quot;, search for &amp;quot;weather&amp;quot;, find the &amp;quot;&amp;lt;code&amp;gt;city-weather&amp;lt;/code&amp;gt;&amp;quot; package and click on it. You will arrive on a page giving installation instructions and sample code at the end.&lt;br /&gt;
Scroll down to the example code and keep that page open (we can use the code later).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Open a cmd/shell window and execute on the command line:&lt;br /&gt;
 npm install city-weather&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Accessing Assemblies in IronPython ===&lt;br /&gt;
Because IronPython executes inside a CLR environment, it has access to any assembly (written in any language).&lt;br /&gt;
For this, IronPython provides a special language extension, which is described in detail in [[https://ironpython.net/documentation/dotnet/dotnet.html the IronPython documentation]].&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 *** to be added **&lt;br /&gt;
&lt;br /&gt;
=== Example 1: Using the &amp;quot;overpy&amp;quot; Python Package (open street map access) in Expecco ===&lt;br /&gt;
In this example, we will access the OpenStreetMap API to fetch information about a particular street&lt;br /&gt;
(&amp;quot;Straße der Nationen&amp;quot;) in a given city (&amp;quot;Chemnitz&amp;quot;).&lt;br /&gt;
 &lt;br /&gt;
The example was taken from [https://pypi.org/project/overpy https://pypi.org/project/overpy] which is documented in [https://python-overpy.readthedocs.io/en/latest/index.html https://python-overpy.readthedocs.io/en/latest/index.html].&amp;lt;br&amp;gt;It requires python3 (you will get a UnicodeEncodeError if you try it in python2).&lt;br /&gt;
&lt;br /&gt;
First, install the package with:&lt;br /&gt;
 pip3 install overpy&lt;br /&gt;
&lt;br /&gt;
For a first test, we will take the original code from the example.&lt;br /&gt;
Create a new Python action, and enter the code:&lt;br /&gt;
 import overpy&lt;br /&gt;
 &lt;br /&gt;
 api = overpy.Overpass()&lt;br /&gt;
 &lt;br /&gt;
 def execute(): &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;# fetch all ways and nodes&amp;lt;/span&amp;gt;&lt;br /&gt;
    result = api.query(&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        way(50.746,7.154, 50.748,7.157) [&amp;quot;highway&amp;quot;];&lt;br /&gt;
        (._;&amp;gt;;);&lt;br /&gt;
        out body;&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;)&lt;br /&gt;
 &lt;br /&gt;
    for way in result.ways:&lt;br /&gt;
        print(&amp;quot;Name:%s&amp;quot; % way.tags.get(&amp;quot;name&amp;quot;, &amp;quot;n/a&amp;quot;))&lt;br /&gt;
        print(&amp;quot;  Highway:%s&amp;quot; % way.tags.get(&amp;quot;highway&amp;quot;, &amp;quot;n/a&amp;quot;))&lt;br /&gt;
        print(&amp;quot;  Nodes:&amp;quot;)&lt;br /&gt;
        for node in way.nodes:&lt;br /&gt;
            print(&amp;quot;    Lat:%f, Lon:%f&amp;quot; % (node.lat, node.lon))&lt;br /&gt;
&lt;br /&gt;
(you can copy-paste the sample code from the webpage)&lt;br /&gt;
&lt;br /&gt;
Open the expecco console (aka &amp;quot;Transcript&amp;quot; via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Transcript&#039;&#039;&amp;quot; menu item) and run the test.&lt;br /&gt;
A list of street nodes should be displayed on the Transcript.&lt;br /&gt;
&amp;lt;br&amp;gt;Of course, the above can be changed to send the latitude and longitude values to output pins for further processing in your test suite.&lt;br /&gt;
&lt;br /&gt;
=== Example 2: Accessing other Python Packages or Individual Script Files ===&lt;br /&gt;
The following works in 19.2 and later.&amp;lt;br&amp;gt;&lt;br /&gt;
In the following example, functions contained in a regular Python script file are called.&lt;br /&gt;
We assume, that the file is named &amp;quot;MyLib.py&amp;quot;, and located in some directory &#039;&#039;DIR&#039;&#039;:&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
DIR/MyLib.py:&lt;br /&gt;
 def fun1(a,b):&lt;br /&gt;
    return a+b;&lt;br /&gt;
 &lt;br /&gt;
 def fun2(a,b):&lt;br /&gt;
    return a-b;&lt;br /&gt;
&lt;br /&gt;
We also assume, that you have created a new python action block, containing the code:&lt;br /&gt;
&lt;br /&gt;
 import MyLib&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
    Transcript.showCR(&amp;quot;fun1:&amp;quot; + str(MyLib.fun1(10,20))&lt;br /&gt;
                    + &amp;quot; fun2:&amp;quot; + str(MyLib.fun2(10,20)))&lt;br /&gt;
&lt;br /&gt;
If you execute this action, you will probably get a &amp;quot;Module Not Found&amp;quot; error from python,&lt;br /&gt;
(unless DIR is already in your PYTHONPATH environment variable).&lt;br /&gt;
&lt;br /&gt;
To fix the problem, open the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; dialog,&lt;br /&gt;
and add DIR to the &amp;quot;Module Path&amp;quot; value. Notice that on Unix/Linux, you have to separate directories with colons &amp;quot;:&amp;quot;, whereas under Windows, you&#039;ll have to separate them with semicolons &amp;quot;;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You will have to shut down the already running Python interpreter and restart it, for the new PYTHONPATH setting to become valid.&amp;lt;br&amp;gt;For this, use the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python Bridge&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Shutdown Interpreters&#039;&#039;&amp;quot; menu item (or shut down all external interpreters via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Debug&#039;&#039;&amp;quot; menu).&lt;br /&gt;
&lt;br /&gt;
=== Example 3: Accessing Python Script Files in Attachments ===&lt;br /&gt;
The following works in 19.2 and later.&amp;lt;br&amp;gt;&lt;br /&gt;
You can add Python script files (i.e. like the &amp;quot;MyLib.py&amp;quot; file in the above example) as attachment to to the suite.&amp;lt;br&amp;gt;For this you have to add &amp;quot;$(Attachments)&amp;quot; to the Python module path setting in &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot;, and import it in the Python code as in the previous example.&lt;br /&gt;
&lt;br /&gt;
=== Example 4: Using the Python Appium Bindings ===&lt;br /&gt;
In the following, we&#039;ll use a Python Appium interface for automation of a mobile application&lt;br /&gt;
(in this case, not using the mobile plugin, and not using the GUI Browser).&lt;br /&gt;
This may be a useful scenario, if you already have python test actions, which you want to integrate into&lt;br /&gt;
expecco.&lt;br /&gt;
&lt;br /&gt;
First install the required python package(s) via the command line or via expecco&#039;s &amp;quot;&#039;&#039;Plugin&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; menu:&lt;br /&gt;
 pip3 install Appium-Python-Client&lt;br /&gt;
or:&lt;br /&gt;
 python -m pip install Appium-Python-Client&lt;br /&gt;
then make a dummy BridgePython block to check if the package is found:&lt;br /&gt;
 import appium&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     Transcript.showCR (&amp;quot;Hello world; Appium was found&amp;quot;);&lt;br /&gt;
Now take either existing code, or copy-paste samples from the [https://pypi.org/project/Appium-Python-Client Appium-Python-Client website]; here is a typical code fragment (of course, you have to adjust the values as required). Obviously, it is also a good idea to add input pins to the python action, so the capabilities and connection parameters can be passed as arguments.&lt;br /&gt;
 from appium import webdriver&lt;br /&gt;
 &lt;br /&gt;
 desired_caps = dict(&lt;br /&gt;
     platformName=&#039;Android&#039;,&lt;br /&gt;
     platformVersion=&#039;10&#039;,&lt;br /&gt;
     automationName=&#039;uiautomator2&#039;,&lt;br /&gt;
     deviceName=&#039;Android Emulator&#039;,&lt;br /&gt;
 )&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     driver = webdriver.Remote(&#039;http://localhost:4723/wd/hub&#039;, desired_caps)&lt;br /&gt;
     el = driver.find_element_by_accessibility_id(&#039;item&#039;)&lt;br /&gt;
     el.click()&lt;br /&gt;
&lt;br /&gt;
=== Example 5: Interfacing to Tensorflow ===&lt;br /&gt;
&lt;br /&gt;
* Create a bridged Python action containing the following code:&lt;br /&gt;
 import numpy as np &lt;br /&gt;
 import tensorflow as tf&lt;br /&gt;
 import tensorflow_hub as hub&lt;br /&gt;
 import tensorflow_datasets as tfds&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     print(&amp;quot;Version: &amp;quot;, tf.__version__)&lt;br /&gt;
     print(&amp;quot;Eager mode: &amp;quot;, tf.executing_eagerly())&lt;br /&gt;
     print(&amp;quot;Hub Version: &amp;quot;, hub.__version__)&lt;br /&gt;
     print(&amp;quot;GPU is&amp;quot;, &amp;quot;available&amp;quot; if tf.config.experimental.list_physical_devices(&amp;quot;GPU&amp;quot;) else &amp;quot;NOT AVAILABLE&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
* run it&lt;br /&gt;
* if you get a &amp;quot;module not found&amp;quot; error message, either click on the link (named &amp;quot;here&amp;quot;), embedded in the error message, or alternatively select the &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Install pip Package&#039;&#039;&amp;quot; menu item. Of course, you can also install packaged from the command line in a shell/cmd window.&lt;br /&gt;
* install missing packages (care for the correct virtual environment if you use them)&lt;br /&gt;
* repeat running it, until you get an output on the Transcript (or stderr) similar to:&lt;br /&gt;
 1: Version:  2.4.1&lt;br /&gt;
 1: Eager mode:  True&lt;br /&gt;
 1: Hub Version:  0.11.0&lt;br /&gt;
 1: GPU is NOT AVAILABLE&lt;br /&gt;
&lt;br /&gt;
* You may have to shutdown the bridge after installation of new packages (although it usually works without, unless existing and already loaded packages are upgraded during the installation).&lt;br /&gt;
&lt;br /&gt;
=== Example 6: Interfacing to the &amp;quot;astropy&amp;quot; Package ===&lt;br /&gt;
The &amp;quot;astropy&amp;quot; package contains a number of very useful functions for astronomy applications. Among others, you&#039;ll find time functions, geo-location mapping, physical constants, image processing and much more inside.&amp;lt;br&amp;gt;(see https://docs.astropy.org/en/stable/index.html)&lt;br /&gt;
&lt;br /&gt;
===== Installation =====&lt;br /&gt;
&lt;br /&gt;
First install the required python package(s) via the command line or via expecco&#039;s &amp;quot;&#039;&#039;Plugin&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Bridges&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Python&#039;&#039;&amp;quot; menu:&lt;br /&gt;
 pip3 install numpy&lt;br /&gt;
 pip3 install astropy (astropy-Python-Client)&lt;br /&gt;
or:&lt;br /&gt;
 python -m pip install numpy&lt;br /&gt;
 python -m pip install astropy (astropy-Python-Client)&lt;br /&gt;
&lt;br /&gt;
===== Smoke Test if Package is Installed =====&lt;br /&gt;
&lt;br /&gt;
then make a dummy BridgePython block to check if the package is found:&lt;br /&gt;
 import astropy&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
     Transcript.showCR (&amp;quot;Hello world; astropy was found&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
Notice: because bumpy and astropy are relatively big packages, the first initial execution may take a few seconds because the Python interpreter has to load these packages (but this only happens when the very first Python action is executed).&lt;br /&gt;
&lt;br /&gt;
===== Interface to an astropy Function =====&lt;br /&gt;
&lt;br /&gt;
The following example demonstrates how to call functions within astropy;&lt;br /&gt;
this will convert an expecco timestamp (a DateTime object) to a julianDate (as Float).&lt;br /&gt;
(Hint: JulianDates are commonly used in Astronomy and Space Sciences).&lt;br /&gt;
&lt;br /&gt;
Please read https://docs.astropy.org/en/stable/time/index.html for details on time functions.&lt;br /&gt;
&lt;br /&gt;
The code includes a few debug prints (to the Transcript). In a production suite, these should probably be commented (or replaced by calls to a logger, which can be switched on/off dynamically).&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample1.png|500px]]&lt;br /&gt;
&lt;br /&gt;
The action can then be used in a diagram as:&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample2.png|500px]]&lt;br /&gt;
&lt;br /&gt;
After a run, we get the Julian date as a float:&lt;br /&gt;
&lt;br /&gt;
[[Datei:AstroPyExample3.png|500px]]&lt;br /&gt;
&lt;br /&gt;
Be aware that expecco requires objects to be JSON serializable to be passed from/to the Python interpreter. Sadly, this is not true for all atrophy objects. If required either pass objects by reference or encode/decode them as strings (or extract subfields into an array and pass the array or pass subfields via individual input/output pins).&lt;br /&gt;
&lt;br /&gt;
It may also be possible to define additional JSON encoders/decoders for individual types.&lt;br /&gt;
&lt;br /&gt;
=== Example 7: Background Thread Inside Python ===&lt;br /&gt;
&lt;br /&gt;
It may be useful to execute python code in a Python background thread;&lt;br /&gt;
for example to poll for data or to check for external equipment status&lt;br /&gt;
in a loop.&lt;br /&gt;
&lt;br /&gt;
===== Extra Process with a Secondary Python Bridge =====&lt;br /&gt;
&lt;br /&gt;
In many cases, you can start a secondary Python bridge and execute actions&lt;br /&gt;
in it via an expecco background action. &lt;br /&gt;
&amp;lt;br&amp;gt;For this: &lt;br /&gt;
* start a new Python bridge (using the &amp;quot;[Python] Start bridge&amp;quot; action from the standard library) in the background action&lt;br /&gt;
* add a python bridge input pin to actions which are to be executed there and pass that bridge reference to the background action&#039;s python step inputs.&lt;br /&gt;
:As an alternative, define an environment variable named &amp;quot;PYTHON&amp;quot; in the background action and set its value to the second bridge instance. Then all python actions inside and under the bg-action will be executed there.&lt;br /&gt;
Notice that no object references can be exchanged between the two bridges;&lt;br /&gt;
you are limited to data types which are JSON representable.&lt;br /&gt;
&lt;br /&gt;
===== Thread inside the Same Python Bridge =====&lt;br /&gt;
If the above is not feasable (for example because the background actions needs access to values or handles of the other actions), you can start a thread inside the same bridge.&lt;br /&gt;
&lt;br /&gt;
However, a number of have to be considered:&lt;br /&gt;
* ensure that the extra thread can be terminated eventually.&amp;lt;br&amp;gt;Because Python does not provide a kill-thread mechanism, the thread must check for a stop variable, and terminate itself.&lt;br /&gt;
* the stop variable should not be a Python global, to avoid name conflicts if more than one background thread is started (or another imported library uses a similar mechanism)&lt;br /&gt;
* communication with the background thread must be performed via event queues, because it cannot write to any output pin.&lt;br /&gt;
&lt;br /&gt;
Here is an example which follows the above scheme:&lt;br /&gt;
====== Background Thread Starter ======&lt;br /&gt;
[[Datei:Python_background_action_schema.png|mini]]&lt;br /&gt;
A Python action which gets a bridge and additional parameters as input. Here, a deltaTime, which defines the poll-loop cycle and a token which is passed with the checkStatus to the event queue.&lt;br /&gt;
&lt;br /&gt;
The action defines 3 functions, the threaded function itself, for which a new thread is started by &amp;quot;execute&amp;quot;, and a thread-stop function (which simply sets the &amp;quot;running&amp;quot; variable to False.&lt;br /&gt;
&lt;br /&gt;
A reference to the stop-function is sent to the output pin.&lt;br /&gt;
&lt;br /&gt;
 import sys&lt;br /&gt;
 import time&lt;br /&gt;
 import threading&lt;br /&gt;
 &lt;br /&gt;
 running = True &lt;br /&gt;
 &lt;br /&gt;
 def thread_function(dt, tok):&lt;br /&gt;
    nonlocal running&lt;br /&gt;
 &lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;Thread %s: starting&amp;quot;, tok)&lt;br /&gt;
    while running:&lt;br /&gt;
        time.sleep(dt)&lt;br /&gt;
        if running:&lt;br /&gt;
            checkOutcome = True # perform check...&lt;br /&gt;
            pushEventType_data(&amp;quot;bg-check&amp;quot;, (tok,checkOutcome))&lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;Thread %s: finishing&amp;quot;, tok)&lt;br /&gt;
 &lt;br /&gt;
 def stopThread():&lt;br /&gt;
    nonlocal running&lt;br /&gt;
    ExpeccoLogger.info(&amp;quot;stopThread&amp;quot;)&lt;br /&gt;
    running = False&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
    ExpeccoLogger.info (&amp;quot;start&amp;quot;)&lt;br /&gt;
    x = threading.Thread(target=thread_function, &lt;br /&gt;
                         args=(waitTime.value(), token.value(),))&lt;br /&gt;
    x.start()&lt;br /&gt;
    stopper = stopThread &lt;br /&gt;
    stopThreadOut.value(makeRef(stopThread))&lt;br /&gt;
    ExpeccoLogger.info (&amp;quot;end&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
====== Thread Stopper ======&lt;br /&gt;
[[Datei:Call_Python_Function.png|mini]]&lt;br /&gt;
the stop-function provided by the thread-starter can later be called to clear the &amp;quot;running&amp;quot; flag. An action to call it would look like:&lt;br /&gt;
&lt;br /&gt;
 import threading&lt;br /&gt;
 &lt;br /&gt;
 def execute():&lt;br /&gt;
   f = func.value()&lt;br /&gt;
   f()&lt;br /&gt;
&lt;br /&gt;
====== EventQueue Setup ======&lt;br /&gt;
The background thread will write to an event queue, with its events marked as &#039;bg-check&#039;. Thus, we must define a handler for those events.&lt;br /&gt;
In expecco, a handler can be either an action block, or a Smalltalk block or a JavaScript function.&lt;br /&gt;
&amp;lt;br&amp;gt;This example uses a Smalltalk block which send a message to the Transcript:&lt;br /&gt;
[[Datei:Python_BG-Thread-Setup.png]]&lt;br /&gt;
When executed, the Transcript shows:&lt;br /&gt;
 [info]: start {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: Thread action1: starting {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: end {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:49.907)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:50.909)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:51.914)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:52.919)&lt;br /&gt;
 Event(type=bg-check data=#(action1 true) ts=2024-04-29 16:11:53.937)&lt;br /&gt;
 [info]: stopThread {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
 [info]: Thread action1: finishing {SimpleBridge &amp;gt;&amp;gt; event_LOGGER: [78]}&lt;br /&gt;
&lt;br /&gt;
=== Example 8: Interfacing to a .NET Assembly via IronPython ===&lt;br /&gt;
&lt;br /&gt;
IronPython is a python interpreter running within the .NET CLR framework. The ability of IronPython to import .NET assemblies, makes it easy to also interface those to expecco.&lt;br /&gt;
 &lt;br /&gt;
Please refer to the IronPython documentation on how to import .NET assemblies.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;--- example to be added ---&lt;br /&gt;
&lt;br /&gt;
== Bridged C Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The following works in 19.2 and above.&amp;lt;br&amp;gt;&lt;br /&gt;
You have to make sure that a C-compiler toolchain is available and can be called directly or indirectly (see [[Installing_additional_Frameworks/en | &amp;quot;Installing additional Frameworks&amp;quot;]]).&lt;br /&gt;
&lt;br /&gt;
Bridged C-code is highly dependent on the C-compiler toolchain of the target machine and may require preparations for machine dependencies with #ifdefs (word length, OS-APIs etc.). It is typically used by experts and for special situations, when simpler alternatives are not available. &lt;br /&gt;
&lt;br /&gt;
Bridged C-code can be used to implement time critical functions or to interface to C/C++ libraries, when the simple DLL-call interface is too complicated to use (for example, if complicated data structures have to be exchanged, if C-callbacks are needed, or if C++ interfaces are to be implemented).&lt;br /&gt;
&lt;br /&gt;
In addition, bridged C-Code actions run in a separate process, isolated from expecco. Thus expecco is not affected by errors in the C-code and cannot be disturbed (eg. by invalid memory references), which is not guaranteed for DLL called functions (which are executed within the expecco process).&amp;lt;br&amp;gt;On the downside, there is some overhead involved in calling a bridged action, since input/output parameters and the call itself are transmitted via an interprocess communication mechanism (i.e. socket/network message). Thus the call roundtrip times are in the millisecond range, as opposed to microseconds for DLL calls.&lt;br /&gt;
&lt;br /&gt;
Other applications are high-speed data acquisition and protocol implementations, in which a C-part is responsible for the time critical task, and expecco can query/control that task remotely (i.e. fetch captured data or state information).&lt;br /&gt;
&lt;br /&gt;
=== The C Bridge ===&lt;br /&gt;
Be reminded that bridged C-Code actions are executed inside a separate OS-process, which runs the C-bridge code.&lt;br /&gt;
Whenever a bridged C-action is to be executed, the pin-data is transferred via an interprocess communication mechanism (IPC), and the action&#039;s code is executed inside the bridge process. Pin data and event requests are transmitted back to expecco via the same IPC mechanism.&lt;br /&gt;
&lt;br /&gt;
The C-bridge itself is available as executable or as shared or linkable library in two configurations, with or without the dynamic C code injection facility.&lt;br /&gt;
&lt;br /&gt;
Setups without code injection are useful to augment (statically compiled) embedded systems with a debug interface, through which expecco can later access specific (and explicitly published) interfaces. In such a setup, no dynamic C-code can be injected into the running application. Instead, the set of callable interfaces must be declared and implemented in advance (in the embedded system).&lt;br /&gt;
&lt;br /&gt;
The following chapter describes the dynamic C-code injection facility as seen by elementary activity code in expecco.&amp;lt;br&amp;gt;For static embedded systems, please refer to the [[Embedded Systems C Bridge API | &amp;quot;Embedded Systems C Bridge API&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== Bridged C Code API ===&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. Bridged C elementary actions are still being developed and the API may be extended or improved in the future (However, it is very very likely to be backward compatible).&lt;br /&gt;
 &lt;br /&gt;
The API is intended to look similar to the other languages&#039; elementary code API.&lt;br /&gt;
However, due to the nature and syntax of the C-language, certain differences are apparent.&amp;lt;br&amp;gt;&lt;br /&gt;
The biggest differences are due to C being a statically typed language: the simple &amp;quot;&amp;lt;code&amp;gt;pin.value()&amp;lt;/code&amp;gt;&amp;quot; interface for pins (as used in other languages) cannot be offered here; instead, a datatype-specific API is provided in C. &lt;br /&gt;
&lt;br /&gt;
==== Variables Seen by the Executed C Function ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed function:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages in the expecco Transcript window (used as argument; see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stdout stream (used as argument; see below). This is NOT the same as the stdout FILE*.&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;supports a few functions to display messages on expecco&#039;s stderr stream (used as argument; see below). This is NOT the same as the stderr FILE*.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;__bridge__&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco. The instance slot named &amp;quot;&amp;lt;code&amp;gt;asynchronous&amp;lt;/code&amp;gt;&amp;quot; is of special interest if the called function uses asynchronous callbacks (see below)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (C) ====&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;error&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Report a defect (in the test). Stops execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;fail&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039;, ...) &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution. The arguments are printf-style. &lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;inconclusive&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;activitySuccess&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;). The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
==== Logging (C) ====&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logFail&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a fail message to the activity log, but continues execution. The arguments are printf-style.&amp;lt;br&amp;gt;Notice: although the action continues to be executed, it will be marked as failed at the end.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logError&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a error message to the activity log, but continues execution. The arguments are printf-style.&amp;lt;br&amp;gt;Notice: although the action continues to be executed, it will be marked as erronous at the end.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logWarning&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds a warning to the activity log, but continues execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;logInfo&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...) &amp;lt;br&amp;gt;Adds an info message to the activity log, and continues execution. The arguments are printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;alert&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log -Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;warn&#039;&#039;&#039; (char* &#039;&#039;fmt&#039;&#039; , ...)&amp;lt;br&amp;gt;Same as alert(). (For Smalltalk protocol compatibility)&lt;br /&gt;
&lt;br /&gt;
==== Event Sending (C) ====&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_data&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, char* &#039;&#039;dataOrNULL&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; must be a 0-terminated string.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_dataBytes&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, unsigned char* &#039;&#039;dataOrNULL&#039;&#039;, int &#039;&#039;numBytes&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; points to a byte-buffer of given length.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;pushEventType_dataJSON&#039;&#039;&#039;(char* &#039;&#039;event&#039;&#039;, jsonObject &#039;&#039;dataOrNULL&#039;&#039;)&amp;lt;br&amp;gt;adds an event to expecco&#039;s event queue. The payload in &#039;&#039;dataOrNULL&#039;&#039; is a [[Embedded_Systems_C_Bridge_API#JSON_Library|json object]].&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
==== Reflection, Information, Queries and Accessing (C) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;) &amp;lt;br&amp;gt;The value of an environment variable&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAt_put&#039;&#039;&#039; (&#039;&#039;anEnvironmentVarName&#039;&#039;, &#039;&#039;value&#039;&#039;) &amp;lt;br&amp;gt;Changing the value of an environment variable.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlan&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text plan&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfActiveTestPlanItem&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the currently executing text case&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nameOfStep&#039;&#039;&#039; () &amp;lt;br&amp;gt;The name of the corresponding step of the activity&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Pin Functions (C) ====&lt;br /&gt;
Currently, C blocks do not support a variable number of input or output pins.&lt;br /&gt;
&lt;br /&gt;
Attention:&lt;br /&gt;
&amp;lt;br&amp;gt;C uses many more reserved keywords for syntax than Smalltalk. These keywords cannot be used as pin names, and you will get a syntax error if you try.&amp;lt;br&amp;gt;Be careful to not name your pins as any of: &amp;quot;&amp;lt;code&amp;gt;return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;char&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;&amp;quot;, etc. &lt;br /&gt;
&lt;br /&gt;
As a proven best practice, add a &amp;quot;&#039;&#039;Pin&#039;&#039;&amp;quot; suffix to your pin names (e.g. name it &amp;quot;&#039;&#039;inPin&#039;&#039;&amp;quot;, instead of &amp;quot;&#039;&#039;in&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===== Input Pins (C) =====&lt;br /&gt;
&lt;br /&gt;
====== Queries ======&lt;br /&gt;
*bool_t &#039;&#039;&#039;hasValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin has received a value, where &#039;&#039;true&#039;&#039; is represented as 1, false as 0.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;isConnected&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin is connected. This is useful for output pins to avoid computing or sending back values which are not used by expecco.&lt;br /&gt;
&lt;br /&gt;
====== Pin Value ======&lt;br /&gt;
&#039;&#039;&#039;Scalar Values&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*char* &#039;&#039;&#039;stringValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the string value at the pin as a c-char*. Raises an error if the pin did not receive a value, or if the value was not a string.&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: The returned pointer becomes invalid after the action&#039;s execution; it should therefore be strcpy&#039;d if it is needed later (i.e. do not keep a reference to it).&amp;lt;br&amp;gt;See keepRef() below to get a pointer which is NOT freed. &lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the integer value at the pin as a c-long. Raises an error if the pin did not receive a value, or if the value was not an integer.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the integer value at the pin as a c-longLong. Raises an error if the pin did not receive a value, or if the value was not an integer.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the double value at the pin as a c-double Raises an error if the pin did not receive a value, or if the value was not a number.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the boolean value at the pin as a c-int. Raises an error if the pin did not receive a value, or if the value was not a boolean.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vectors&#039;&#039;&#039; (aka Arrays / bulk data)&amp;lt;br&amp;gt;&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the byteArray value at the pin as a c-unsigned char*. Raises an error if the pin did not receive a value, or if the value was not a byteArray or C-struct. This can also be used to receive other bulk data, such as an int32 or float array. For example, by converting a collection of numbers first to a byteArray, and then casting the bytesValue to another pointer type in the bridge code.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;bytesLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of bytes in the byte[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request. If you need to keep it (for whatever reason), it must be copied to a static or another malloc&#039;d memory area or fetched with keepRef() which is described below.&lt;br /&gt;
&lt;br /&gt;
*ushort* &#039;&#039;&#039;shortsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the shortArray value at the pin as a c-unsigned short*. Raises an error if the pin did not receive a value, or if the value was not an array.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt;  or &amp;lt;code&amp;gt;shortsLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of shorts in the short[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request See also keepRef() below.&lt;br /&gt;
&lt;br /&gt;
*uint* &#039;&#039;&#039;intsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the intArray value at the pin as a c-unsigned int*. Raises an error if the pin did not receive a value, or if the value was not an array.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt;  or &amp;lt;code&amp;gt;intsLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of ints in the int[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request (see keepRef() below).&lt;br /&gt;
&lt;br /&gt;
*long* &#039;&#039;&#039;longsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the intArray value at the pin as a c-unsigned long*. Raises an error if the pin did not receive a value, or if the value was not an array.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt;  or &amp;lt;code&amp;gt;longsLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of longss in the long[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request (see keepRef() below).&lt;br /&gt;
&lt;br /&gt;
*float* &#039;&#039;&#039;floatsValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the floatArray value at the pin as a c-float*. Raises an error if the pin did not receive a value, or if the value was not an array.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt;  or &amp;lt;code&amp;gt;floatsLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of floats in the float[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request (see keepRef() below).&lt;br /&gt;
&lt;br /&gt;
*double* &#039;&#039;&#039;doublesValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the doubleArray value at the pin as a c-double*. Raises an error if the pin did not receive a value, or if the value was not an array.&amp;lt;br&amp;gt;Use &amp;lt;code&amp;gt;arraySize(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt;  or &amp;lt;code&amp;gt;doublesLength(&#039;&#039;inPin&#039;&#039;)&amp;lt;/code&amp;gt; to get the number of doubles in the double[].&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]Attention: the returned array has been allocated with malloc() on the heap, and will be freed after the request (see keepRef() below).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*void* &#039;&#039;&#039;pointerValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pointer value at the pin as a &amp;lt;code&amp;gt;void*&amp;lt;/code&amp;gt;. This must be a pointer which has been previously sent to expecco via putPointer(). Raises an error if the pin did not receive a value, or if the value was not a pointer. This means, that it must be a pointer as previously sent to expecco with putPointer. Please read the description of &amp;quot;&amp;lt;code&amp;gt;putPointer()&amp;lt;/code&amp;gt;&amp;quot; below.&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValue&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the value at the pin as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]]. Raises an error if the pin did not receive a value.&amp;lt;br&amp;gt;[[bild:bulb.png|20px]]The returned pointer becomes invalid after the action&#039;s execution; field values should therefore be extracted and copied if needed later (i.e. do not keep a reference to it or its components).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queries&#039;&#039;&#039;&amp;lt;br&amp;gt;&lt;br /&gt;
*int &#039;&#039;&#039;arraySize&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the number of array elements, if there is a byte-, short-, int-, float- or double-Array at the pin.&amp;lt;br&amp;gt;Notice that the number of elements is returned, NOT the number of bytes.&amp;lt;br&amp;gt;Raises an error if the pin did not receive a value, or if the value was not an array or C-struct.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Values with Default&#039;&#039;&#039;&lt;br /&gt;
*char* &#039;&#039;&#039;stringValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, char* &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;stringValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, long &#039;&#039;repl&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, longlong &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longLongValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, double &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;doubleValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, bool_t &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;booleanValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, uchar* &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, &#039;&#039;repl&#039;&#039; otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;bytesValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. Be aware of automatic freeing unless the pointer is fetched with keepRef().&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValueIfAbsent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;, jsonObject &#039;&#039;repl&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin-datum as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] if it has one, &#039;&#039;repl&#039;&#039;  otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;jsonValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;stringValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, an empty string otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;stringValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution unless fetched with keepRef().&lt;br /&gt;
&lt;br /&gt;
*long &#039;&#039;&#039;longValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*longlong &#039;&#039;&#039;longLongValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) (vsn24.1, 64bit)&amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;longLongValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&amp;lt;br&amp;gt;This API is only avalable in 64bit versions of the C-bridge (i.e. not in the cBridge32.exe for Windows) and only with expecco vsn 24.1 and later.&lt;br /&gt;
&lt;br /&gt;
*double &#039;&#039;&#039;doubleValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0.0 (zero) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;doubleValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;booleanValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, 0 (false) otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;booleanValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*uchar* &#039;&#039;&#039;bytesValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin&#039;s datum if it has one, NULL otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;bytesValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception.&lt;br /&gt;
&lt;br /&gt;
*jsonObject &#039;&#039;&#039;jsonValueIfPresent&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt;Returns the pin-datum as a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] if it has one, NULL otherwise. Similar to &amp;quot;&amp;lt;code&amp;gt;jsonValue()&amp;lt;/code&amp;gt;&amp;quot;, but avoids the exception. The returned pointer becomes invalid after the action&#039;s execution.&lt;br /&gt;
&lt;br /&gt;
*void* &#039;&#039;&#039;keepRef&#039;&#039;&#039; (&#039;&#039;inPin&#039;&#039;) &amp;lt;br&amp;gt; (rel. 26.1) Returns a pointer to the malloc&#039;s bulk data and tells the bridge that the underlying memory shall NOT be freed when execute() returns.&amp;lt;br&amp;gt;This avoids the need to memcpy big data blocks from the incoming memory buffer; however it is now in your responsibility to free that memory eventually.&amp;lt;br&amp;gt;This is only to be used for strings, bytearrays and other bulk vectors.&lt;br /&gt;
&lt;br /&gt;
Variable number of input/output pins are not supported. You should pass an array or structure if required.&lt;br /&gt;
&lt;br /&gt;
===== Output Pins (C) =====&lt;br /&gt;
&lt;br /&gt;
*bool_t &#039;&#039;&#039;isConnected&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;) (rel. 26.2)&amp;lt;br&amp;gt;Returns true (1) if the pin is connected, false (0) otherwise. This may be used to avoid generating output values to unconnected pins (useful if the value is expensive to compute or leads to a big data transfer).&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putString&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, char* &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a string to the output pin. The string must be zero-terminated.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putStringN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, char* &#039;&#039;data&#039;&#039;, int &#039;&#039;len&#039;&#039;) &amp;lt;br&amp;gt;Writes len bytes of a string to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a long to the output pin.&amp;lt;br&amp;gt;Be aware that the size of a long depends on the cbridge host&#039;s CPU architecture, the OS and the C-compiler: on Unix machines, it is typically an int64, whereas on Windows it is usually an int32.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes an unsigned long to the output pin.&amp;lt;br&amp;gt;Be aware that the size of an unsigned long depends on the cbridge host&#039;s CPU architecture, the OS and the C-compiler: on Unix machines, it is typically an uint64, whereas on Windows it is usually an uint32.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLongLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a long long to the output pin. Typically, a long long is an int64 on all architectures.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULongLong&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long long &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes an unsigned long long to the output pin. Typically, an unsigned long long is an uint64 on all architectures (depends on cbridge host&#039;s CPU, OS and compiler). This API is not available in the 32 bit cBridge version.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putDouble&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, double &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a double (float64) to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putBoolean&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, bool_t &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a boolean to the output pin. Anything but 0 (zero) is interpreted as true.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putJsonObject&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, jsonObject &#039;&#039;data&#039;&#039;) &amp;lt;br&amp;gt;Writes a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]] to the output pin. Refer to [[Embedded_Systems_C_Bridge_API#JSON_Library | the JSON library documentation]] on how to create a [[Embedded_Systems_C_Bridge_API#JSON_Library|jsonObject]].&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putBytesN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned char* &#039;&#039;bytes&#039;&#039;, int &#039;&#039;nBytes&#039;&#039;) &amp;lt;br&amp;gt;Writes nBytes from a byte array to the output pin.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putPointer&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, void* &#039;&#039;dataPtr&#039;&#039;) &amp;lt;br&amp;gt;Writes a reference for dataPtr to the output pin. This value can be passed to another cBridge action (executed on the same bridge), where it can be read from the input with &amp;lt;code&amp;gt;pointerValue()&amp;lt;/code&amp;gt; (this is similar to the makeRef mechanism of other bridged languages).&lt;br /&gt;
&lt;br /&gt;
The following API is available since the 21.2 release:&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putDoublesN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, double*  &#039;&#039;doubles&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count double values as a vector to the output pin. expecco will receive these values as a collection of double precision floating point values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putFloatsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, float*  &#039;&#039;floats&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count float values as a vector to the output pin. expecco will receive these values as a collection of single precision floating point values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putIntsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, int*  &#039;&#039;ints&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count int values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putLongsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, long*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count long values as a vector to the output pin. expecco will receive these values as a collection of integer values.&amp;lt;br&amp;gt;Be reminded that the sizeof longs may be different between Windows and non-Windows machines.&lt;br /&gt;
&lt;br /&gt;
These vectors will appear at the output pin as a collection; the type of collection is given by the pin&#039;s datatype. For most space efficient representation, we recommend the use of the bulk data types (FloatArray, DoubleArray, etc.)&lt;br /&gt;
&lt;br /&gt;
The following API is available since the 21.2.1 update release:&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putShortsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, short*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count (signed) short values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putUIntsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned int*  &#039;&#039;ints&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned int values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putULongsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned long*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned long values as a vector to the output pin. expecco will receive these values as a collection of integer values.&amp;lt;br&amp;gt;Be reminded that the sizeof longs may be different between Windows and non-Windows machines.&lt;br /&gt;
&lt;br /&gt;
* void &#039;&#039;&#039;putUShortsN&#039;&#039;&#039; (&#039;&#039;outPin&#039;&#039;, unsigned short*  &#039;&#039;longs&#039;&#039;, int &#039;&#039;count&#039;&#039;) &amp;lt;br&amp;gt;Writes count unsigned short values as a vector to the output pin. expecco will receive these values as a collection of integer values.&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (C) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from C code (as pseudo variables).&lt;br /&gt;
However, only a very limited subset of operations is supported (in the following, &#039;&#039;stream&#039;&#039; stands for one of the above wellknown expecco streams and is given as argument to the function):&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;cr&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;)&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;show&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;, char* &#039;&#039;fmt&#039;&#039;, ...)&amp;lt;br&amp;gt;Adds a textual representation of the argument. The argument is printf-style.&lt;br /&gt;
&lt;br /&gt;
*void &#039;&#039;&#039;showCR&#039;&#039;&#039; (&#039;&#039;stream&#039;&#039;, char* &#039;&#039;fmt&#039;&#039;, ...)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
If the bridge was started by expecco (as opposed to being executed on a remote host), stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Thus, you can use &amp;quot;&amp;lt;code&amp;gt;fprintf(stdout, ...)&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;fprintf(stderr, ...)&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;showCR(Transcript, ...)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Additional Utility Functions (C) ====&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;getTmpDirectory&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Returns a pointer to the pathname of the temp directory.&lt;br /&gt;
&lt;br /&gt;
*char* &#039;&#039;&#039;getenv&#039;&#039;&#039; (char* &#039;&#039;varName&#039;&#039;)&amp;lt;br&amp;gt;Returns a pointer to the shell variable&#039;s value.&lt;br /&gt;
&lt;br /&gt;
*int &#039;&#039;&#039;setenv&#039;&#039;&#039; (char* &#039;&#039;varName&#039;&#039;, char* &#039;&#039;value&#039;&#039;)&amp;lt;br&amp;gt;Set the shell variable&#039;s value.&lt;br /&gt;
&lt;br /&gt;
=== Referring to Functions in Shared Libraries ===&lt;br /&gt;
&lt;br /&gt;
If the cBridge code refers to any functions which are located in additional shared libraries (DLLs), the bridge needs to know where to find those.&lt;br /&gt;
&lt;br /&gt;
The location of any shared library must be specified in the C-bridge settings dialog, unless the library is found in the CBridge executable&#039;s folder or at a standard place (eg. &amp;quot;/usr/lib&amp;quot;, &amp;quot;/usr/local/lib&amp;quot;, etc. on Unix and &amp;quot;C:\Windows&amp;quot; and others on Windows).&lt;br /&gt;
The details depend on the OperatingSystem; Windows searches along the PATH setting, linux along LD_LIBRARY_PATH. If in doubt, consult your OS documentation.&lt;br /&gt;
&lt;br /&gt;
Navigate to &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;External Script Interpreters&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;CBridge&#039;&#039;&amp;quot; and add the path to the &amp;quot;DLL Path&amp;quot; field.&lt;br /&gt;
&lt;br /&gt;
As an alternative, edit the CC-Script and add appropriate command line arguments to the linker command near the end (it is recommended to keep the original, and make an edited copy).&lt;br /&gt;
&lt;br /&gt;
You&#039;ll also have to edit the script, if additional compiler or linkage arguments are required, or if you have to determine the location of additional frameworks dynamically.&lt;br /&gt;
&lt;br /&gt;
=== Referring to Types Defined in expecco ===&lt;br /&gt;
&lt;br /&gt;
User defined struct, union and enum &amp;quot;CType (C-Defined)&amp;quot; dataypes (which are declared in expecco and present in the suite&#039;s element tree) are visible inside the activity code, and can be included as:&lt;br /&gt;
 #include &amp;quot;expecco/Types/XXX.h&amp;quot;&lt;br /&gt;
where &amp;quot;XXX&amp;quot; is the name of the expecco type (in the tree).&lt;br /&gt;
If the type declares an unnamed struct, the type will be known as a typedef in the C-code. &lt;br /&gt;
==== Typedef Name vs. struct/union Name ====&lt;br /&gt;
If the type is named &amp;quot;myStruct&amp;quot; and defined as:&lt;br /&gt;
 struct {&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
it should be referred to in the C-code as:&lt;br /&gt;
 myStruct s, *sP;&lt;br /&gt;
In this case, the name of the typedef is the name of the type.&lt;br /&gt;
&lt;br /&gt;
In contrast, if it was defined as:&lt;br /&gt;
 struct foo {&lt;br /&gt;
    ...&lt;br /&gt;
 }&lt;br /&gt;
you can also write:&lt;br /&gt;
 struct foo s;&lt;br /&gt;
 struct foo *sP; &lt;br /&gt;
In other words, there will be a typedef for &amp;quot;myStruct&amp;quot; (the name of the type) and a struct by the name as in the type&#039;s definition.&lt;br /&gt;
&lt;br /&gt;
Notice, that these files do actually not exist; instead, the activity&#039;s C-code is scanned and dynamically expanded to include those definitions. See example below.&lt;br /&gt;
You should shutdown any already running bridge, when a type is changed, to enforce a recompilation of the C code.&lt;br /&gt;
&lt;br /&gt;
=== Including Attachments as Header Files ===&lt;br /&gt;
&lt;br /&gt;
Attached files can be included as:&lt;br /&gt;
 #include &amp;quot;expecco/Attachments/XXX.h&amp;quot;&lt;br /&gt;
where &amp;quot;XXX.h&amp;quot; is the name of the expecco attachment file.&lt;br /&gt;
&amp;lt;br&amp;gt;Be reminded that the name of the attachment itself (the tree-item name) is not required to be the same as the name of the file, although usually, they are.&lt;br /&gt;
&lt;br /&gt;
=== C++ Interfaces ===&lt;br /&gt;
C++ functions should be called indirectly via a C function wrapper (i.e. &amp;lt;code&amp;gt;extern &amp;quot;C&amp;quot;&amp;lt;/code&amp;gt;). &lt;br /&gt;
&amp;lt;br&amp;gt;Object references can be passed from the bridge to expecco and back via the &amp;quot;&amp;lt;code&amp;gt;putPointer&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;pointerValue&amp;lt;/code&amp;gt;&amp;quot; functions.&lt;br /&gt;
&lt;br /&gt;
=== Running Bridged C-Code on a Remote Computer ===&lt;br /&gt;
&lt;br /&gt;
The remote computer must have the cBridge executable running.&lt;br /&gt;
The executable is found in the &amp;quot;&amp;lt;code&amp;gt;packages/bridgeFramework/cBridge/cLibrary&amp;lt;/code&amp;gt;&amp;quot; folder under your expecco installation folder and should be copied to the remote machine. Windows users will find both a 64bit version (&amp;quot;cBridge.exe&amp;quot;) and a 32bit one (&amp;quot;cBrige32.exe&amp;quot;). If your C-code needs or refers to any existing dll, make sure that the correct bridge is configured in the settings (a 32bit bridge will not be able to load a 64bit dll and vice versa).  &lt;br /&gt;
&lt;br /&gt;
On the expecco side, you have two options:&lt;br /&gt;
# specify that the bridge is already running in the settings; then all cBridge actions which have not been explicitly given a bridge to execute in will be executed there&lt;br /&gt;
# explicitly connect to a running bridge via the &amp;quot;&#039;&#039;Connect to Running Bridge&#039;&#039;&amp;quot; action block, and passing the resulting bridge handle to the C-action.&lt;br /&gt;
The handle can be passed either explicitly via the step&#039;s cBridge input pin, or implicitly by declaring a variable named &amp;quot;&amp;lt;code&amp;gt;CBRIDGE&amp;lt;/code&amp;gt;&amp;quot; and storing the handle there. &amp;lt;br&amp;gt;The cBridge input pin is generated via the step&#039;s &#039;&#039;Special Pins&#039;&#039; menu.&lt;br /&gt;
&amp;lt;br&amp;gt;If the CBRIDGE variable is declared in a compound action, it will be valid by all actions executed from that and below that action. This makes it possible to run actions on multiple bridges without explicitly passing the bridge handles around via input pins.&lt;br /&gt;
&lt;br /&gt;
Bridges can be started either by one of the bridge start actions in the standard library or by a batch-, shell- or powershell script. Type &amp;quot;&amp;lt;code&amp;gt;cBridge --help&amp;lt;/code&amp;gt;&amp;quot; for command line options.&lt;br /&gt;
&lt;br /&gt;
You can have multiple bridges running, even in heterogenous networks (i.e. call for a remote C-action on a Windows machine, while running expecco on a Linux machine). &lt;br /&gt;
We provide bridge executables for additional architectures (eg. Raspberry-PI) upon request and for a small additional fee.&lt;br /&gt;
&lt;br /&gt;
=== Running Multiple Bridges in Parallel ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can start multiple bridges via the &amp;quot;[Start new local CBridge]&amp;quot; action from the standard library and remember the bridge connection handles in variables.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Setup.png|300px]]&amp;lt;br&amp;gt;Make sure, that the bridges are using different ports.&lt;br /&gt;
&lt;br /&gt;
In addition, add a bridge input pin to the action(s) which you want to execute on one of those bridges (via the &amp;quot;Special Pins&amp;quot; popup menu in the action&#039;s schema).&amp;lt;br&amp;gt;[[Datei:ShowTempDir.png|300px]]&amp;lt;br&amp;gt;&lt;br /&gt;
For example, the following simply sends a message to the standard error:&lt;br /&gt;
 static void&lt;br /&gt;
 execute() {&lt;br /&gt;
    char buffer[128];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s&amp;quot;, getTmpDirectory());&lt;br /&gt;
    putString(output, buffer);&lt;br /&gt;
 }&lt;br /&gt;
and finally, here is an example which executes this action in parallel on&lt;br /&gt;
4 bridges:&amp;lt;br&amp;gt;[[Datei:FourActions.png|300px]].&lt;br /&gt;
&lt;br /&gt;
=== Bulk Data ===&lt;br /&gt;
&lt;br /&gt;
If a huge number of data elements (known as &amp;quot;&#039;&#039;Bulk Data&#039;&#039;&amp;quot;) are to be transferred, transmission times may get much longer than the actual execution time of the action (keep in mind that the communication times take most of the time if the executed computation is simple).&lt;br /&gt;
&lt;br /&gt;
If the cBridge runs on the same machine as expecco, shared memory will be used to exchange bulk data. This may reduce the transmission times drastically, depending on the amount of data (there are still other messages exchanged via the socket communication).&lt;br /&gt;
&lt;br /&gt;
===== Data from C to Expecco =====&lt;br /&gt;
* Passing a Pointer to expecco&lt;br /&gt;
:if you can leave the data inside the bridge (eg. as malloc&#039;d data vector), &#039;&#039;&#039;and&#039;&#039;&#039; expecco does not need to access the elements of the vector, you can leave the data inside the cBridge and only pass a handle to expecco. This handle may later be sent to another C-action (on the same bridge) to process the data at non-critical times (eg. at the end of the test).&lt;br /&gt;
:This mechanism is the fastest because only a small handle (typically 32/64 bits) has to be transmitted to expecco. However, it degrades to become very very slow if you access individual elements of the vector from expecco, as this will result in one IPC roundtrip per accessed element.&lt;br /&gt;
* Passing Bulk Data as a Vector&lt;br /&gt;
:If each vector element is sent individually to an output pin (eg. in a loop with &amp;lt;code&amp;gt;putFloat&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;putDouble&amp;lt;/code&amp;gt;), one IPC roundtrip will be performed per element. &lt;br /&gt;
:It is much faster to send the whole vector data sent as one array via putDoublesN(), putFloatsN() or putIntsN(). This still does introduce some additional cost due to JSON-encoding (on the cBridge side) and JSON-decoding on the expecco side, but the effective transmission time is dramatically reduced.&lt;br /&gt;
* Passing Bulk Data as a ByteArray&lt;br /&gt;
:Further speedup is possible by not sending the data as a number vector, but instead as a byte vector, actually sending the raw ended bytes from the bridge to expecco. For this, use a putBytesN() call and case your bulk data to a &amp;quot;char *&amp;quot; &amp;lt;small&amp;gt;&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&amp;lt;/small&amp;gt;.&lt;br /&gt;
:However (big warning): expecco will receive a byte-vector and you will have to add code to extract the relevant elements from this. If the cBridge CPU and the expecco-CPU use a different byte order or a different floating-point-number representations, you will have to deal with that in that extraction code. Be aware, that it may even depend on the compiler: Microsoft VisualC compilers for x86_64 interpret &amp;quot;long&amp;quot; as a 32bit integer, whereas most other compilers/systems treat them as 64bit integers.&amp;lt;br&amp;gt;&lt;br /&gt;
:This is probably the fastest method to transmit bytes, but comes with those possible pitfalls. We therefore recommend to try the &amp;quot;Bulk Data as Vector&amp;quot; method first. In most situations that is either within the acceptable timing constraints, or too far off, such that the ByteArray transmission will also not be fast enough, and you should use the pointer passing method anyway.&lt;br /&gt;
&lt;br /&gt;
===== Passing Data from Expecco to C =====&lt;br /&gt;
Be aware that the bulk data pointer you receive at an input pin has been allocated&lt;br /&gt;
in malloc&#039;d memory which is freed when the execute() function returns. If the data is to be retained inside the C bridge (or passed to a function which keeps a reference), you have two choices:&lt;br /&gt;
* memcpy the data into an internal buffer&lt;br /&gt;
* tell the caller that the buld data should not be freed on return from execute&lt;br /&gt;
The second variant is available with expecco 26.1, and preferred.&amp;lt;br&amp;gt;In either case, it is in your responsibility to free the memory when no longer needed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&amp;lt;/small&amp;gt;Starting with expecco 26.1, this is no longer required - there are now additional fast bulk transfer entries named: &amp;lt;code&amp;gt;putFloatsN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;putDoublesN&amp;lt;/code&amp;gt; etc.&lt;br /&gt;
&lt;br /&gt;
=== Example1: Writing and Calling C Code in Expecco ===&lt;br /&gt;
&lt;br /&gt;
In this example, numbers and a string will be passed to a C action block.&amp;lt;br&amp;gt;The action has been defined with 3 input pins:&lt;br /&gt;
* &amp;lt;code&amp;gt;in1&amp;lt;/code&amp;gt; (type Float)&lt;br /&gt;
* &amp;lt;code&amp;gt;in2&amp;lt;/code&amp;gt; (type Integer)&lt;br /&gt;
* &amp;lt;code&amp;gt;in3&amp;lt;/code&amp;gt; (type String)&lt;br /&gt;
and the single output &amp;quot;&amp;lt;code&amp;gt;out1&amp;lt;/code&amp;gt;&amp;quot;, with type String.&lt;br /&gt;
&lt;br /&gt;
The code will generate a string by concatenating the printf strings of its arguments at the output&lt;br /&gt;
and also print a number of messages via different output channels.&lt;br /&gt;
&lt;br /&gt;
Create a new bridged C action,&amp;lt;br&amp;gt; &lt;br /&gt;
[[Datei:CBridge Demo Action1.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;and enter the code:&lt;br /&gt;
 &lt;br /&gt;
 static void&lt;br /&gt;
 execute() {&lt;br /&gt;
    double dVal = &#039;&#039;&#039;doubleValue&#039;&#039;&#039;(in1); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s double value&amp;lt;/span&amp;gt;&lt;br /&gt;
    long lVal   = &#039;&#039;&#039;longValue&#039;&#039;&#039;(in2);   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s integer value&amp;lt;/span&amp;gt;&lt;br /&gt;
    char* sVal  = &#039;&#039;&#039;stringValue&#039;&#039;&#039;(in3); &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// fetch input pin&#039;s string value&amp;lt;/span&amp;gt;&lt;br /&gt;
    char buffer[512];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s / %ld / %g&amp;quot;, sVal, lVal, dVal);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// write to output pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;putString&#039;&#039;&#039;(out1, buffer);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// a regular print&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// (will be shown inside expecco&#039;s Transcript, if io-trace is enabled)&amp;lt;/span&amp;gt;&lt;br /&gt;
    fprintf(stderr, &amp;quot;hello on stderr from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// another regular print&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// (will be shown inside expecco&#039;s Transcript, if io-trace is enabled)&amp;lt;/span&amp;gt;&lt;br /&gt;
    fprintf(stdout, &amp;quot;hello on stdout from C-Code!\n&amp;quot;);&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s Transcript&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s stdout&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Stdout, &amp;quot;hello on expecco&#039;s stdout from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s stderr&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Stderr, &amp;quot;hello on expecco&#039;s stderr from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// explicit output to expecco&#039;s Transcript&amp;lt;/span&amp;gt;&lt;br /&gt;
    &#039;&#039;&#039;show&#039;&#039;&#039;(Transcript, &amp;quot;another hello from C-Code!\n&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// possibly report failure to expecco&amp;lt;/span&amp;gt;&lt;br /&gt;
    if (strlen(sVal) &amp;lt; 20) {&lt;br /&gt;
        &#039;&#039;&#039;fail&#039;&#039;&#039;(&amp;quot;short string \&amp;quot;%s\&amp;quot; (length=%d)&amp;quot;, sVal, strlen(sVal))&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Example2: Passing Complex Objects to and from C-Code (by value) ===&lt;br /&gt;
&lt;br /&gt;
Complex struct objects can be passed by value to the C-code by defining a CStruct type&lt;br /&gt;
i.e. create a new type named eg. &amp;quot;myStruct&amp;quot; in the tree, define it as C-Type and enter a definition similar to:&lt;br /&gt;
&lt;br /&gt;
 /* C: */&lt;br /&gt;
 struct {&lt;br /&gt;
    int i1;&lt;br /&gt;
    float f1;&lt;br /&gt;
    double d1;&lt;br /&gt;
    char c[20];&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
then, add an input pin with that datatype to the C-action,&lt;br /&gt;
and add the following line to the action&#039;s C-code, to include the type&#039;s definition:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;expecco/Types/myStruct.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(the name of the include must match the type&#039;s typename in the tree)&lt;br /&gt;
&lt;br /&gt;
From within your C-code, access the fields with:&lt;br /&gt;
&lt;br /&gt;
 struct myStruct* p;&lt;br /&gt;
 &lt;br /&gt;
 p = (struct myStruct*)&#039;&#039;&#039;bytesValue&#039;&#039;&#039;(inPin);&lt;br /&gt;
 &lt;br /&gt;
 fprintf(stderr, &amp;quot;got i1:%d\n&amp;quot;, p-&amp;gt;i1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got f1:%f\n&amp;quot;, p-&amp;gt;f1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got d1:%F\n&amp;quot;, p-&amp;gt;d1);&lt;br /&gt;
 fprintf(stderr, &amp;quot;got c:%s\n&amp;quot;, p-&amp;gt;c);&lt;br /&gt;
&lt;br /&gt;
and write such a struct to an output pin with:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;putBytesN&#039;&#039;&#039;(outPin, p, sizeof(struct myStruct));&lt;br /&gt;
&lt;br /&gt;
To create such a struct argument, use an instance creation action block (and possibly additional field setter actions).&lt;br /&gt;
Those can be automatically generated by selecting the type in the tree,&lt;br /&gt;
and invoking the popup menu function &amp;quot;&#039;&#039;Refactoring&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Generate&#039;&#039;&amp;quot; &amp;amp;rarr; &amp;quot;&#039;&#039;Creators and Accessors&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Example3: Passing Handles/Pointers to expecco and Back to Another C Action ===&lt;br /&gt;
&lt;br /&gt;
A common situation is when two C actions are given, where one generates a handle (i.e. pointer),&lt;br /&gt;
which must be passed to the other action (in the same bridge). &lt;br /&gt;
&amp;lt;br&amp;gt;For example, the first may be a &amp;quot;&amp;lt;code&amp;gt;createConnection()&amp;lt;/code&amp;gt;&amp;quot; function,&lt;br /&gt;
and the second needs that connection handle as argument (that would typically be a kind of &amp;quot;&amp;lt;code&amp;gt;send()&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;receive()&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;close()&amp;lt;/code&amp;gt;&amp;quot; function, and the handle something like a FILE pointer or Windows handle).&lt;br /&gt;
&lt;br /&gt;
For this scenario, the cBridge provides a mechanism similar to the &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; facility of other bridges.&lt;br /&gt;
The first action function will send the handle to an output pin via &amp;quot;&amp;lt;code&amp;gt;putPointer()&amp;lt;/code&amp;gt;&amp;quot;;&lt;br /&gt;
the pin&#039;s datatype should be &amp;quot;&amp;lt;code&amp;gt;Any&amp;lt;/code&amp;gt;&amp;quot;,  &amp;quot;&amp;lt;code&amp;gt;Handle&amp;lt;/code&amp;gt;&amp;quot; or a struct type as described above:&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     ...&lt;br /&gt;
     &#039;&#039;&#039;putPointer&#039;&#039;&#039;( outPin, (void*) handle );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
and the other action functions can get this handle from an input pin:&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     handle = &#039;&#039;&#039;pointerValue&#039;&#039;&#039;( inPin );&lt;br /&gt;
     ...&lt;br /&gt;
&lt;br /&gt;
=== Example4: Passing Bulk Data to expecco and to another C Action ===&lt;br /&gt;
&lt;br /&gt;
In this example, one generates some data (eg. a vector of float values),&lt;br /&gt;
and passes this to another C action (possibly in another bridge). &lt;br /&gt;
&amp;lt;br&amp;gt;For example, the first may be a measurement value collector,&lt;br /&gt;
and the second computes some statistical analysis.&lt;br /&gt;
Be aware, that this example was created for demnstration; in practice, you would probably pass a pointer within the same bridge. But the example is also useful if one of those actions is a non-C action, for example a Python numpy action.&lt;br /&gt;
&lt;br /&gt;
The first action function generates some data and sends them to an output pin.&lt;br /&gt;
The pin&#039;s datatype should be &amp;quot;&amp;lt;code&amp;gt;float*&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;FloatArray&amp;lt;/code&amp;gt;&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 #define NUM_FLOATS 1024 // or whatever&lt;br /&gt;
 void execute() {&lt;br /&gt;
     float data[NUM_FLOATS];&lt;br /&gt;
     ...&lt;br /&gt;
     // compute or generate the data&lt;br /&gt;
     for (i=0; i&amp;lt;NUM_FLOATS; i++) {&lt;br /&gt;
         data[i] = ...&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
     // send it to the output pin  &lt;br /&gt;
     &#039;&#039;&#039;putFloatsN&#039;&#039;&#039;( outPin, data, NUM_FLOATS );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
the receiving action can get this data from an input pin (also with type &amp;quot;&amp;lt;code&amp;gt;float*&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;FloatArray&amp;lt;/code&amp;gt;&amp;quot;):&lt;br /&gt;
&lt;br /&gt;
 void execute() {&lt;br /&gt;
     float* data;&lt;br /&gt;
     int numElements;&lt;br /&gt;
&lt;br /&gt;
     // receive from an input pin &lt;br /&gt;
     // always verify the size! &lt;br /&gt;
     // The data could have been created by any action with any size!&lt;br /&gt;
     data = &#039;&#039;&#039;floatsValue&#039;&#039;&#039;( inPin );&lt;br /&gt;
     numElements = &#039;&#039;&#039;arraySize&#039;&#039;&#039;( inPin );&lt;br /&gt;
     ...&lt;br /&gt;
     // processing&lt;br /&gt;
     for (i=0; i&amp;lt;numElements; i++) {&lt;br /&gt;
         ... do something with data[i] ....&lt;br /&gt;
     }&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== Bridged Smalltalk Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
The following works in 20.1 and above.&amp;lt;br&amp;gt;&lt;br /&gt;
Similar to the above described bridged Node and bridged Python actions, these actions are coded in the Smalltalk language and executed by a separate Smalltalk engine (separate process). Both local and remote execution are possible.&lt;br /&gt;
&lt;br /&gt;
By the time of writing, bridged Smalltalk actions can be executed in an ST/X Smalltalk engine, support for VA-Smalltalk and VW-Smalltalk is being developed and will be available in one of the next expecco releases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Bridged Smalltalk Code API ===&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. &lt;br /&gt;
Bridged Smalltalk elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Smalltalk actions will execute in another Smalltalk system; by the time of writing, this may be another Smalltalk/X or a VisualWorks Smalltalk system. With enough customer interest, other dialects (VisualAge and Squeak) may be supported in the future.&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular Smalltalk actions, which execute inside expecco itself.&lt;br /&gt;
However, for some objects, only a subset of the protocol is available.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed code:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&amp;lt;code&amp;gt;bridge&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;the bridge object which handles the communication with expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Report a defect (in the test). Up to 4 optional with:-args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ]  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ]  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039;:&#039;&#039;infoString&#039;&#039; [ &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg1&#039;&#039; ... &#039;&#039;&#039;with&#039;&#039;&#039;:&#039;&#039;arg4&#039;&#039; ] &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039; &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039;&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039;:&#039;&#039;messageString&#039;&#039;&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for JavaScript compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Bridged Smalltalk) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from remote smalltalk actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from remote smalltalk actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;hasValue&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039;:&#039;&#039;alternativeValue&#039;&#039; &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;valueIfPresent&#039;&#039;&#039; &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;isConnected&#039;&#039;&#039; &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;:&#039;&#039;someValue&#039;&#039;&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see makeRef below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Bridged Smalltalk) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from remote Smalltalk images. &lt;br /&gt;
However, only a limited subset of messages is supported:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039;:&#039;&#039;arg&#039;&#039;&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039;:&#039;&#039;arg&#039;&#039;&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutAll&#039;&#039;&#039;:&#039;&#039;string&#039;&#039;&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutLine&#039;&#039;&#039;:&#039;&#039;string&#039;&#039;&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Smalltalk) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;&#039;&#039;&#039;value:&#039;&#039;&#039;&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote smalltalk in another action.&lt;br /&gt;
This would make it impossible to get handles from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;makeRef&amp;quot; method solves this.&lt;br /&gt;
 &lt;br /&gt;
*&#039;&#039;self&#039;&#039; &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;object&#039;&#039;&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;self&#039;&#039; &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;object&#039;&#039; &#039;&#039;&#039;name&#039;&#039;&#039;:&#039;&#039;aString&#039;&#039;&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
&lt;br /&gt;
I.e. to write a reference to a pin, use:&lt;br /&gt;
 &#039;&#039;somePin&#039;&#039; &#039;&#039;&#039;value&#039;&#039;&#039;:(self &#039;&#039;&#039;makeRef&#039;&#039;&#039;:&#039;&#039;someObject&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== Additional Information on Bridged VisualWorks Smalltalk Actions ===&lt;br /&gt;
&lt;br /&gt;
Inside bridged VisualWorks actions, the above described &amp;quot;Transcript&amp;quot; refers to the expecco Transcript; not the VisualWorks Transcript (the remote code is compiled inside an environment, where the Transcript variable has been redefined).&lt;br /&gt;
&lt;br /&gt;
To send output to the VisualWorks Transcript, use &amp;quot;Smalltalk.Core.Transcript&amp;quot;, as in:&lt;br /&gt;
 ...&lt;br /&gt;
 Smalltalk.Core.Transcript show:&#039;Hello on VW Transcript&#039;; cr&lt;br /&gt;
 ...&lt;br /&gt;
 Transcript show:&#039;Hello on expecco Transcript&#039;; cr&lt;br /&gt;
 ...&lt;br /&gt;
 Be aware, that the VW Transcript does not understand the &amp;quot;showCR:&amp;quot; message; you need &amp;quot;show:&amp;quot; followed by &amp;quot;cr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Bridged Ruby Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Note: This is a preliminary API documentation. &lt;br /&gt;
Bridged Ruby elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Ruby actions will execute in a Ruby interpreter.&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular actions, which execute inside expecco itself or another language interpreter.&lt;br /&gt;
However, due to Ruby language specifics, some differences are noticable.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the scope of the executed code&amp;lt;br&amp;gt;(notice the &amp;quot;$&amp;quot; prefix; Ruby requires global variables to be prefixed by a &amp;quot;$&amp;quot; character):&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;$Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages in the expecco Transcript window (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; $Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages on expecco&#039;s stdout stream (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; $Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display messages on expecco&#039;s stderr stream (see below)&lt;br /&gt;
&amp;lt;!-- *&amp;lt;code&amp;gt; $Logger&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to generate log messages using expecco&#039;s Logger stream (see below) --&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt; $Dialog&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to display confirmation dialogs (see below)&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;error&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Report a defect (in the test). Up to 4 optional args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;fail&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ])  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;inconclusive&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ])  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;activitySuccess&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pass&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039; [ ,&#039;&#039;arg1&#039;&#039; ... ,&#039;&#039;arg4&#039;&#039; ]) &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== $Transcript, $Stderr and $Stdout (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are also accessible from Ruby actions (with a $-prefix). &lt;br /&gt;
Notice, that $Stderr refers to expecco&#039;s stderr and $Stdout refers to expecco&#039;s stdout. Both may be (and usually are) different from the Ruby interpreter&#039;s STDERR/STDOUT.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039; ()&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line)&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039;(&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;Adds a textual representation of the argument, which can be a string, number or any other object.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039;(&#039;&#039;arg&#039;&#039;)&amp;lt;br&amp;gt;A combination of show(), followed by a linebreak.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutAll&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutLine&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;puts&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== $Dialog (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;confirm&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple yes/no dialog; returns a boolean.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;request&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple string-input dialog; returns a string or nil if cancel was pressed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestPassword&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;same, but the entered string is not shown on the screen&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestFilename&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;asks for a filename&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for JavaScript compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
==== Environment Access (Bridged Ruby) ====&lt;br /&gt;
*&#039;&#039;&#039;environmentAt&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;);&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from ruby actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environmentAtPut&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;, &amp;amp;lt;newValue&amp;amp;gt;);&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from ruby actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;hasValue&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;()&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;valueIfAbsent&#039;&#039;&#039;(&#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;valueIfPresent&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;isConnected&#039;&#039;&#039;() &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Ruby) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;pin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;(&#039;&#039;someValue&#039;&#039;)&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see &amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt; below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Ruby) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;&#039;&#039;&#039;value:&#039;&#039;&#039;&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote ruby in another action.&lt;br /&gt;
This would make it impossible to get a handle from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; method solves this, by creating a &amp;quot;pointer&amp;quot; or &amp;quot;handle&amp;quot; to the object inside the remote machine.&lt;br /&gt;
 &lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;)&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;, &#039;&#039;&#039;name&#039;&#039;&#039;)&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
:I.e. to write a reference to a pin, use:&lt;br /&gt;
::: &#039;&#039;somePin&#039;&#039;.&#039;&#039;&#039;value&#039;&#039;&#039;(&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;someObject&#039;&#039;))&lt;br /&gt;
&lt;br /&gt;
== Bridged Dart Elementary Blocks ==&lt;br /&gt;
planned for one of the next expecco versions&lt;br /&gt;
&lt;br /&gt;
== Bridged Scheme Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Note: As of rel26.1, this is a preliminary API documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;Bridged Scheme elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Scheme actions will execute in a Scheme interpreter (currently only Racket, but other dialects will follow).&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular actions, which execute inside expecco or another language interpreter.&lt;br /&gt;
However, due to Scheme being a functional language, and we do not want to depend on any object model (which we may have to port), the API is written to run on a bare scheme.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the lexical scope of the executed code:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy object by which the stream functions can send messages to the expecco Transcript (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;same for the standard output (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;same for the standard error (see below)&lt;br /&gt;
&amp;lt;!-- *&amp;lt;code&amp;gt; $ogger&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to generate log messages using expecco&#039;s Logger stream (see below) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;error&#039;&#039;&#039; &#039;&#039;infoString&#039;&#039; [ &#039;&#039;arg1&#039;&#039; ... ]) &amp;lt;br&amp;gt;Report a defect (in the test). Optional args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;fail&#039;&#039;&#039; &#039;&#039;infoString&#039;&#039; [ &#039;&#039;arg1&#039;&#039; ... ])  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;inconclusive&#039;&#039;&#039; &#039;&#039;infoString&#039;&#039; [ &#039;&#039;arg1&#039;&#039; ... ])  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;activitySuccess&#039;&#039;&#039; &#039;&#039;infoString&#039;&#039; [ &#039;&#039;arg1&#039;&#039; ... ]) &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pass&#039;&#039;&#039; &#039;&#039;infoString&#039;&#039; [ &#039;&#039;arg1&#039;&#039; ... ]) &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are accessible from Scheme actions. &lt;br /&gt;
Notice, that Stderr refers to expecco&#039;s stderr and Stdout refers to expecco&#039;s stdout. Both may be (and usually are) different from the Scheme interpreter&#039;s STDERR/STDOUT.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;cr&#039;&#039;&#039; &#039;&#039;stream&#039;&#039;)&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line; eg. &amp;lt;code&amp;gt;(cr Transcript)&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;show&#039;&#039;&#039; &#039;&#039;stream&#039;&#039; &#039;&#039;arg&#039;&#039; ...)&amp;lt;br&amp;gt;Adds a textual representation of the arguments, to the stream. Eg. &amp;lt;code&amp;gt;(show Stderr &amp;quot;the result is&amp;quot; 123 &amp;quot;\n&amp;quot;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;showCR&#039;&#039;&#039; &#039;&#039;stream&#039;&#039; &#039;&#039;arg&#039;&#039; ...)&amp;lt;br&amp;gt;A combination of (show ...), followed by a (cr).&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;nextPutAll&#039;&#039;&#039; &#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;nextPutLine&#039;&#039;&#039; &#039;&#039;string&#039;&#039;)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Dialog (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
--- unfinished --&lt;br /&gt;
*(&#039;&#039;&#039;confirm&#039;&#039;&#039; &#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple yes/no dialog; returns a boolean.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;request&#039;&#039;&#039; &#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;Opens a simple string-input dialog; returns a string or nil if cancel was pressed.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;requestPassword&#039;&#039;&#039; &#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;same, but the entered string is not shown on the screen&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;requestFilename&#039;&#039;&#039; &#039;&#039;msg&#039;&#039;)&amp;lt;br&amp;gt;asks for a filename&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;logFail&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a fail message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;logError&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;logWarning&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;logInfo&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;alert&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;warn&#039;&#039;&#039; &#039;&#039;messageString&#039;&#039;)&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for JavaScript compatibility).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Bridged Scheme) ====&lt;br /&gt;
*(&#039;&#039;&#039;environmentAt&#039;&#039;&#039; &amp;amp;lt;varName&amp;amp;gt;)&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from scheme  actions.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;environmentAtPut!&#039;&#039;&#039; &amp;amp;lt;varName&amp;amp;gt; &amp;amp;lt;newValue&amp;amp;gt;)&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from scheme actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-hasValue?&#039;&#039;&#039; &#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;Returns #tif the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-value&#039;&#039;&#039; &#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-valueIfAbsent&#039;&#039;&#039; &#039;&#039;pin&#039;&#039; &#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-valueIfPresent&#039;&#039;&#039; &#039;&#039;pin&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-isConnected?&#039;&#039;&#039; &#039;&#039;pin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Scheme) ====&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;pin-value!&#039;&#039;&#039; &#039;&#039;pin&#039;&#039; &#039;&#039;someValue&#039;&#039;)&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see &amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt; below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Scheme) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;(&#039;&#039;&#039;pin-value!&#039;&#039;&#039; ...)&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote ruby in another action.&lt;br /&gt;
This would make it impossible to get a handle from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; method solves this, by creating a &amp;quot;pointer&amp;quot; or &amp;quot;handle&amp;quot; to the object inside the remote machine.&lt;br /&gt;
 &lt;br /&gt;
*(&#039;&#039;&#039;makeRef&#039;&#039;&#039; &#039;&#039;object&#039;&#039;)&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*(&#039;&#039;&#039;makeRef&#039;&#039;&#039; &#039;&#039;object&#039;&#039; &#039;&#039;name&#039;&#039;)&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
:I.e. to write a reference to a pin, use:&lt;br /&gt;
::: (&#039;&#039;&#039;pin-value!&#039;&#039;&#039; &#039;&#039;somePin&#039;&#039; (&#039;&#039;&#039;makeRef&#039;&#039;&#039; &#039;&#039;someObject&#039;&#039;))&lt;br /&gt;
&lt;br /&gt;
== Bridged Octave Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Note: As of rel26.1, this is a preliminary API documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;Bridged Octave/Matlab elementary actions are still being developed and the API may change slightly until officially released.&lt;br /&gt;
&lt;br /&gt;
Bridged Octave actions will execute in a GNU Octave interpreter.&lt;br /&gt;
 &lt;br /&gt;
The API looks similar to the API of regular actions, which execute inside expecco or another language interpreter.&lt;br /&gt;
&lt;br /&gt;
==== Variables (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
The following variables are in the lexical scope of the executed code:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy object by which the stream functions can send messages to the expecco Transcript (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stdout &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;same for the standard output (see below)&lt;br /&gt;
*&amp;lt;code&amp;gt; Stderr &amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;same for the standard error (see below)&lt;br /&gt;
&amp;lt;!-- *&amp;lt;code&amp;gt; $ogger&amp;lt;/code&amp;gt; &amp;lt;br&amp;gt;a proxy which supports a few functions to generate log messages using expecco&#039;s Logger stream (see below) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Reporting (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
Notice these have been named with an &amp;quot;ex_&amp;quot; prefix to avoid name conflicts with the existing builtin error function and the others for name consistency.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ex_error&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039;, [&#039;&#039;arg1&#039;&#039;, ... ]) &amp;lt;br&amp;gt;Report a defect (in the test). Optional args are sliced into the string, if it contains &amp;quot;%i&amp;quot; placeholders. Stops execution. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ex_fail&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039;, [&#039;&#039;arg1&#039;&#039;, ... ])  &amp;lt;br&amp;gt;Report a failure (in the SUT). Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ex_inconclusive&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039;, [ &#039;&#039;arg1&#039;&#039;, ... ])  &amp;lt;br&amp;gt;Report an inconclusive test. Stops execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ex_activitySuccess&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039;, [ &#039;&#039;arg1&#039;&#039;, ... ]) &amp;lt;br&amp;gt;Finishes the current activity with success (same as &amp;quot;success()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;ex_pass&#039;&#039;&#039;(&#039;&#039;infoString&#039;&#039;, [ &#039;&#039;arg1&#039;&#039;, ... ]) &amp;lt;br&amp;gt;Finishes the current testCase with success.&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Transcript, Stderr and Stdout (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
The expecco &amp;quot;&amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Stderr&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;Stdout&amp;lt;/code&amp;gt;&amp;quot; are accessible from Scheme actions. &lt;br /&gt;
Notice, that Stderr refers to expecco&#039;s stderr and Stdout refers to expecco&#039;s stdout. Both may be (and usually are) different from the Scheme interpreter&#039;s STDERR/STDOUT.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;show&#039;&#039;&#039;(&#039;&#039;stream&#039;&#039;, &#039;&#039;arg&#039;&#039;, ...)&amp;lt;br&amp;gt;Adds a textual representation of the arguments, to the stream. Eg. &amp;lt;code&amp;gt;show(Stderr, &amp;quot;the result is&amp;quot;, 123, &amp;quot;\n&amp;quot;)&amp;lt;/code&amp;gt; sends it to expecco&#039;s stderr.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;showCR&#039;&#039;&#039;(&#039;&#039;stream&#039;&#039;, &#039;&#039;arg&#039;&#039;, ...)&amp;lt;br&amp;gt;A combination of (show ...), followed by a (cr).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutAll&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;, ...)&amp;lt;br&amp;gt;String writing&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;nextPutLine&#039;&#039;&#039;(&#039;&#039;string&#039;&#039;, ...)&amp;lt;br&amp;gt;String printing with cr&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;cr&#039;&#039;&#039;(&#039;&#039;stream&#039;&#039;)&amp;lt;br&amp;gt;Adds a linebreak (i.e. followup text will be shown on the next line; eg. &amp;lt;code&amp;gt;(cr Transcript)&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
In addition, stdout and stderr are also forwarded to the expecco Transcript window, depending on the settings in expecco (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tracing&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Show Stdout and Stderr on Transcript&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Dialog (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;confirm&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;, ...)&amp;lt;br&amp;gt;Opens a simple yes/no dialog; returns a boolean.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;request&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;, ...)&amp;lt;br&amp;gt;Opens a simple string-input dialog; returns a string or nil if cancel was pressed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestPassword&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;, ...)&amp;lt;br&amp;gt;same, but the entered string is not shown on the screen&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;requestFilename&#039;&#039;&#039;(&#039;&#039;msg&#039;&#039;, ...)&amp;lt;br&amp;gt;asks for a filename&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Logging (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logFail&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...) &amp;lt;br&amp;gt;Adds a fail message to the activity log. Multiple args are concatenated.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logError&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...) &amp;lt;br&amp;gt;Adds a error message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logWarning&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...) &amp;lt;br&amp;gt;Adds a warning to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;logInfo&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...) &amp;lt;br&amp;gt;Adds an info message to the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;alert&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...)&amp;lt;br&amp;gt;Adds a warning message to the activity log, and also shows a DialogBox, which has to be confirmed by the operator. The dialog box and confirmation can be disabled by a settings flag in the &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Log Settings&#039;&#039;&amp;quot; dialog (by default it is disabled).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;warn&#039;&#039;&#039;(&#039;&#039;messageString&#039;&#039;, ...)&amp;lt;br&amp;gt;Same as &#039;&#039;alert:&#039;&#039; (for compatibility with other languages).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Environment Access (Bridged Octave) ====&lt;br /&gt;
*&#039;&#039;&#039;environment_get&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt;)&amp;lt;br&amp;gt;Fetches and returns a value from the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;You can only read simple objects (numbers, booleans and strings) from octave actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;environment_set&#039;&#039;&#039;(&amp;amp;lt;varName&amp;amp;gt; &amp;amp;lt;newValue&amp;amp;gt;)&amp;lt;br&amp;gt;Writes a value into the expecco environment which is in scope of the current activity.&amp;lt;br&amp;gt;The variable must be writable.&amp;lt;br&amp;gt;You can only write simple objects (numbers, booleans and strings) from octave actions.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
*&#039;&#039;&#039;eval&#039;&#039;&#039; (&#039;&#039;smalltalkCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of Smalltalk code inside expecco.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;evalJS&#039;&#039;&#039; (&#039;&#039;javascriptCodeString&#039;&#039;) &amp;lt;br&amp;gt;Evaluate a piece of JavaScript code inside expecco.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Input Pins (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_value&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;Returns the value of the pin. Raises an error if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_valueIfAbsent&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;, &#039;&#039;alternativeValue&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or the value from alternativeValue if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_valueIfPresent&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;) &amp;lt;br&amp;gt;Returns the value of a pin or nil if the pin did not receive any value.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_hasValue&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;)&amp;lt;br&amp;gt;Returns true if the pin has received a value&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_isConnected&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;) &amp;lt;br&amp;gt;Returns true if the pin has a connection&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Output Pins (Bridged Octave) ====&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;pin_send_value&#039;&#039;&#039;(&#039;&#039;pin&#039;&#039;, &#039;&#039;someValue&#039;&#039;)&amp;lt;br&amp;gt;Writes the value to the pin. Only simple object can be transferred by value (nil, booleans, integers, floats, strings).&amp;lt;br&amp;gt;Anything else should be passed by reference (see &amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt; below).&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
==== Passing Objects by Reference (Bridged Octave) ====&lt;br /&gt;
By default, objects written to output pins via &amp;quot;&#039;&#039;&#039;pin_send_value&#039;&#039;&#039;(...)&amp;quot; will be marshalled to JSON, transferred to expecco and decoded there.&lt;br /&gt;
Effectively, a copy of the object is created, which looses its identity when sent back later to the remote ruby in another action.&lt;br /&gt;
This would make it impossible to get a handle from a remote action, which is to be sent to another action on the same remote machine.&lt;br /&gt;
The &amp;quot;&amp;lt;code&amp;gt;makeRef&amp;lt;/code&amp;gt;&amp;quot; method solves this, by creating a &amp;quot;pointer&amp;quot; or &amp;quot;handle&amp;quot; to the object inside the remote machine.&lt;br /&gt;
 &lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;)&amp;lt;br&amp;gt;creates a reference object, which can be written to a pin.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;object&#039;&#039;, &#039;&#039;&#039;name&#039;&#039;&#039;)&amp;lt;br&amp;gt;ditto, but gives it a user friendly name (eg. for the expecco log)&lt;br /&gt;
:I.e. to write a reference to a pin, use:&lt;br /&gt;
::: &#039;&#039;&#039;pin_send_value&#039;&#039;&#039;(&#039;&#039;somePin&#039;&#039;, &#039;&#039;&#039;makeRef&#039;&#039;&#039;(&#039;&#039;someObject&#039;&#039;))&lt;br /&gt;
&lt;br /&gt;
== DotNET Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Editing support for C# is provided with vsn 26.2. However, .NET objects can also be instantiated and methods be called via the transparent message forwarning mechanism provided by Smalltalk. This means, that you use Smalltalk code to send (Smalltalk-) messages to proxy objects, which forward the call information to the corresponding bridge object.&lt;br /&gt;
&lt;br /&gt;
You can also use bridged IronPython actions and refer to the assembly or objects from there.&lt;br /&gt;
&lt;br /&gt;
=== C# Actions ===&lt;br /&gt;
The API available follows the other bridged action APIs:&lt;br /&gt;
==== Input Pin Functions (bridged C#) ====&lt;br /&gt;
* object = inPin.value()&lt;br /&gt;
* objectOrNull = inPin.valueIfPresent()&lt;br /&gt;
* object = inPin.valueIfAbsent(&#039;&#039;default&#039;&#039;)&lt;br /&gt;
* bool = inPin.hasValue()&lt;br /&gt;
* bool = inPin.isConnected()&lt;br /&gt;
==== Output Pin Functions (bridged C#) ====&lt;br /&gt;
* outPin.value(&#039;&#039;value&#039;&#039;)&lt;br /&gt;
==== Variables (bridged C#) ====&lt;br /&gt;
* string = environmentAt(&#039;&#039;varName&#039;&#039;)&lt;br /&gt;
* environmentAtPut(&#039;&#039;varName&#039;&#039;, &#039;&#039;stringValue&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
==== Logging (bridged C#) ====&lt;br /&gt;
* logInfo(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* logWarning(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* logError(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* logFail(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
==== Dialogs (bridged C#) ====&lt;br /&gt;
* bool = Dialog.confirm(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* string = Dialog.request(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* string = Dialog.requestPassword(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
* string = Dialog.requestFilename(&#039;&#039;message&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
== VisualBasic Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
Support for VisualBasic Script elementary block execution is provided as an extension plugin, and requires a separate plugin license.&lt;br /&gt;
It is only available for expecco running on the MS Windows operating system.&lt;br /&gt;
&lt;br /&gt;
Code written as a VisualBasic elementary block is not executed directly by expecco. Instead, the code is forwarded to a VisualBasic scripting host which runs as another process either on the local or on a remote host. The scripting host must be a Microsoft Windows host (but expecco itself may run on any type of operating system). By using VisualBasic blocks, expecco&#039;s basic black box test functionality can be easily extended by many powerful gray- and white-box tests. Many libraries for device and equipment control, COM/DCOM and other technologies and UI interaction are possible with the VisualBasic plugin.&lt;br /&gt;
&lt;br /&gt;
Please consult the separate [[VBScript/en | VisualBasic plugin documentation]] for more detail.&lt;br /&gt;
&lt;br /&gt;
== Shell, Batch and other Script Elementary Blocks ==&lt;br /&gt;
There is no special API for those, except for pin-value expansion and stdin/stdout/stderr handling.&lt;br /&gt;
All of this is described in the [[ElementaryBlock_Element/en#Script_Action_Blocks | &amp;quot;Script Action Blocks&amp;quot; documentation]]&lt;br /&gt;
&lt;br /&gt;
== Remote expecco Elementary Blocks ==&lt;br /&gt;
&lt;br /&gt;
These run on a remote expecco system, and can be used to generate load (stress) or perform additional measurements.&lt;br /&gt;
Remote expecco actions will be available in or after the 24.2 expecco version.&lt;br /&gt;
&lt;br /&gt;
--- to be documented ---&lt;br /&gt;
&lt;br /&gt;
== Tutorial: Common Tasks ==&lt;br /&gt;
&lt;br /&gt;
This chapter gives code fragments and examples for common tasks.&lt;br /&gt;
&lt;br /&gt;
The underlying Smalltalk class library contains (among others) very powerful and robust collection, stream and number representation systems, of which many functions are useful for elementary block developers. The set of usable functions is much larger than for example in Java or C standard libraries. Thus for a newcomer to Smalltalk, it is highly recommended and fruitful to read the introduction texts and/or use the class browser for a deeper understanding. You can benefit from existing code and save a lot of development time in knowing a little about your class libraries.&lt;br /&gt;
&lt;br /&gt;
Also, it is a good idea to try the sample code in a &amp;quot;workspace&amp;quot; window or within the code editor,&lt;br /&gt;
by selecting the piece of code to be tried, and performing the &amp;quot;&#039;&#039;printIt&#039;&#039;&amp;quot; menu function.&lt;br /&gt;
Thus you can quickly test&amp;amp;try code fragments without a need for an elementary block and its setup.&lt;br /&gt;
&lt;br /&gt;
Or use the [[How_to_Program/en#MethodFinder:_Find_Functions_by_Example|MethodFinder]] tool to find operations.&lt;br /&gt;
&lt;br /&gt;
=== String Handling ===&lt;br /&gt;
&lt;br /&gt;
Notice, that in Smalltalk all collection indices are 1-based. I.e. the index of the first element is 1, and the last index is the collection&#039;s size. This is the same in Mathematica, but different in C, JavaScript, Java and others.&lt;br /&gt;
Thus Smalltalk loops over collection elements should run from 1 to the collection&#039;s size, not from zero to the size minus 1. You will get an index exception, if you try.&lt;br /&gt;
&lt;br /&gt;
Also notice, that index-based enumerations (i.e. loops from 1 to the size) are actually seldom needed, due to the powerful &amp;quot;&amp;lt;code&amp;gt;do:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;collect:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;select:&amp;lt;/code&amp;gt;&amp;quot; etc. family of enumeration methods.&lt;br /&gt;
These do all the index computations for you, and are often heavily tuned for better performance.&lt;br /&gt;
&lt;br /&gt;
Also notice, that in Smalltalk, String is a subclass of Collection, and most of the functions described below are actually not implemented in the String class, but inherited from a superclass. Take this into consideration, when searching for String utility functions in the class browser (i.e. look there first or click on the &amp;quot;&#039;&#039;See Inherited Methods&#039;&#039;&amp;quot; button in the class browser [[Datei:SeeInheritedInBrowser.png]] ).&lt;br /&gt;
On the other hand, the fact that most of those functions are implemented in the Collection superclass also means, that they work on many other collections (Arrays, ByteArray, OrderedCollection, Set, Dictionary etc.).&lt;br /&gt;
&lt;br /&gt;
If you are in doubt, open a [[Tools_Notepad/en|Workspace]] window, enter a piece of code and evaluate it (using the &amp;quot;&#039;&#039;printIt&#039;&#039;&amp;quot; menu function).&lt;br /&gt;
Or open the [[How_to_Program/en#Find_Functions_by_Example|Method Finder]] to find an operation given the desired outcome.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Copying Parts of a String ====&lt;br /&gt;
&lt;br /&gt;
To extract a substring, and the index and/or count is known, use one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; to: &#039;&#039;stopIndex&#039;&#039;&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyTo: &#039;&#039;stopIndex&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; count: &#039;&#039;n&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFirst: &#039;&#039;count&#039;&#039;   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ same as copyTo:&amp;lt;/span&amp;gt;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyLast: &#039;&#039;count&#039;&#039;    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the last count characters&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom: &#039;&#039;startIndex&#039;&#039; butLast: &#039;&#039;count&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ copy except the last count characters&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All of the above will copy including the character at the start- and stop index.&lt;br /&gt;
I.e.&lt;br /&gt;
    &#039;hello world&#039; copyFrom:2 to:5&lt;br /&gt;
will return &#039;ello&#039;. &lt;br /&gt;
&amp;lt;br&amp;gt;[[Datei:point_right.png|20px]]This is different from some C/Java functions, which usually expect the stopIndex to be one-after the last copied element.&lt;br /&gt;
===== Search &amp;amp; Copy =====&lt;br /&gt;
to search for a character and copy up to that character&#039;s position, use:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyUpTo: &#039;&#039;characterToSearch&#039;&#039; &lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyFrom:&#039;&#039;startIndex&#039;&#039; upTo: &#039;&#039;characterToSearch&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can also search backward from the end (i.e. the last occurrence of a character):&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; copyUpToLast: &#039;&#039;characterToSearch&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Finding Elements and Substrings ====&lt;br /&gt;
&lt;br /&gt;
To search for elements of a string (which are characters), use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOf: &#039;&#039;aCharacter&#039;&#039; &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOf: &#039;&#039;aCharacter&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
and:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; lastIndexOf: &#039;&#039;aCharacter&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; lastIndexOf: &#039;&#039;aCharacter&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
to search backward from the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br&amp;gt;[[Datei:point_right.png|20px]]The Smalltalk methods return a 1-based index, and 0 (zero) if not found&amp;lt;!--; JavaScript methods return a 0-based index and -1 if not found--&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]]Notice that a character constant is written in Smalltalk as &amp;lt;code&amp;gt;$&amp;lt;x&amp;gt;&amp;lt;/code&amp;gt;, where &amp;lt;x&amp;gt; is a printable character or a space. Non-printable characters must be specified by their name (&amp;quot;&amp;lt;code&amp;gt;Character return&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Character lf&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Character tab&amp;lt;/code&amp;gt;&amp;quot;) or their Unicode-point (decimal: &amp;quot;&amp;lt;code&amp;gt;Character value: 127&amp;lt;/code&amp;gt;&amp;quot; or hex: &amp;quot;&amp;lt;code&amp;gt;Character value: 16r1F00&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
If there are multiple characters to be searched for, pass a collection of searched characters to one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: &#039;&#039;aBunchOfCharacters&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: &#039;&#039;aBunchOfCharacters&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
&lt;br /&gt;
    &#039;hello world&#039; indexOfAny: &#039;eiou&#039; startingAt:3&lt;br /&gt;
&lt;br /&gt;
looks for the next vocal at or after position 3.&lt;br /&gt;
&lt;br /&gt;
Both receiver and argument may actually be any kind of Collection;&lt;br /&gt;
thus:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny: #( $a $A $e $E )&lt;br /&gt;
&lt;br /&gt;
works the same.&lt;br /&gt;
&lt;br /&gt;
Finally, there is a very generic search function, where you can pass a test-procedure as argument:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ...a boolean test on &#039;&#039;ch&#039;&#039; ...]&lt;br /&gt;
&lt;br /&gt;
will return the index of the next character for which your boolean check computes a true value.&lt;br /&gt;
For example, to search for the next digit, use:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ch isDigit]&lt;br /&gt;
&lt;br /&gt;
to search for a digit OR period OR dollar character, you can use one of:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; findFirst:[:ch | ch isDigit or:[ ch == $. or:[ ch == $$]]]&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfAny:&#039;0123456789$.&#039;&lt;br /&gt;
&lt;br /&gt;
use whichever you find more readable.&lt;br /&gt;
(there is also a &amp;quot;&amp;lt;code&amp;gt;findFirst:startingAt:&amp;lt;/code&amp;gt;&amp;quot;, and corresponding &amp;quot;&amp;lt;code&amp;gt;findLast:&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;findLast:startingAt:&amp;lt;/code&amp;gt;&amp;quot; for backward searches)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Because it is a common task to search for separators and other non-printable characters,&lt;br /&gt;
special methods exist for those:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSeparatorStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfNonSeparatorStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfControlCharacterStartingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where separators are the whitespace characters (space, tab, vt, cr and lf),&lt;br /&gt;
and control characters are all characters below ASCII 32.&lt;br /&gt;
&lt;br /&gt;
All of the index-search methods return a 0 (zero) if the character is not found.&lt;br /&gt;
&lt;br /&gt;
Substrings can be searched with:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039; caseSensitive: false&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: anotherString startingAt: startIndex&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSubCollection: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfSubCollection: &#039;&#039;anotherString&#039;&#039; startingAt: &#039;&#039;startIndex&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
There are also corresponding backward search variants &amp;quot;&amp;lt;code&amp;gt;lastIndexOfSubCollection:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Notice the somewhat generic names &amp;quot;&amp;lt;code&amp;gt;indexOfSubCollection:&amp;lt;/code&amp;gt;&amp;quot; instead of a more intuitive &amp;quot;&amp;lt;code&amp;gt;indexOfString:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
The reason is that these methods are inherited from collection, which does not care if the elements are&lt;br /&gt;
characters or other objects (&amp;lt;code&amp;gt;indexOfString:&amp;lt;/code&amp;gt; is an alias for &amp;lt;code&amp;gt;indexOfSubCollection:&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
This means, that you can use the same method to search for a slice in an array:&lt;br /&gt;
&lt;br /&gt;
    #(1 2 3 4 5 6 7 8 9 8 7 6 5 1 2 3 2 1) indexOfSubCollection:#(9 8 7)&lt;br /&gt;
&lt;br /&gt;
using the same code.&lt;br /&gt;
&lt;br /&gt;
To find all such methods in the class browser, search for implementors of &amp;quot;&amp;lt;code&amp;gt;*indexOf*&amp;lt;/code&amp;gt;&amp;quot;, and look at the matches in &amp;lt;code&amp;gt;Collection&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SequenceableCollection&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;CharacterArray&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== If you don&#039;t need the Index ====&lt;br /&gt;
&lt;br /&gt;
If you only need to check if a character or substring is present, but not its position,&lt;br /&gt;
you can use &amp;quot;&amp;lt;code&amp;gt;includes:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesString:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesString:caseSensitive:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesSubCollection:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;includesAny:&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;includesAll:&amp;lt;/code&amp;gt;&amp;quot; in a similar spirit.&lt;br /&gt;
These may be slightly faster and make the code more readable. They return a boolean.&lt;br /&gt;
&lt;br /&gt;
==== Caseless Searches ====&lt;br /&gt;
&lt;br /&gt;
For strings, special substring searches are available, which ignore case (upper/lower) differences:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; includesString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; indexOfString: &#039;&#039;anotherString&#039;&#039; caseSensitive: false&lt;br /&gt;
&lt;br /&gt;
==== Prefix and Suffix Checks ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; startsWith: &#039;&#039;anotherString&#039;&#039; &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; endsWith: &#039;&#039;anotherString&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
are obvious.&lt;br /&gt;
The powerful:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; startsWithAnyOf: &#039;&#039;aCollectionOfStrings&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
searches for multiple string prefixes. For example,&lt;br /&gt;
&lt;br /&gt;
    &#039;hello&#039; startsWithAnyOf: #( &#039;ab&#039; &#039;ce&#039; &#039;de&#039; )&lt;br /&gt;
&lt;br /&gt;
would look for all of them and return false in this concrete example.&lt;br /&gt;
Of course, there is a corresponding &amp;quot;&amp;lt;code&amp;gt;endsWithAnyOf:&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Splitting Parts of a String (or Collection) ====&lt;br /&gt;
&lt;br /&gt;
The simplest are:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asCollectionOfWords&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asCollectionOfLines&lt;br /&gt;
&lt;br /&gt;
which split at separators and line-ends respectively and return a collection as they say in their name.&lt;br /&gt;
&lt;br /&gt;
More generic is:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; js_split: charOrString&lt;br /&gt;
&lt;br /&gt;
which returns a collection of substrings split at &amp;quot;&#039;&#039;charOrString&#039;&#039;&amp;quot; elements. as the name suggests, you can pass either a single character or a substring as argument.&lt;br /&gt;
Thus:&lt;br /&gt;
&lt;br /&gt;
    &#039;hello world isn&#039;t this nice&#039; js_split:(Character space)&lt;br /&gt;
&lt;br /&gt;
will give you the strings &amp;lt;code&amp;gt;(&#039;hello&#039; &#039;world&#039; &#039;isnt&#039; &#039;this&#039; &#039;nice&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
Whereas:&lt;br /&gt;
    &#039;some : string : separated : by : space : colon space&#039; js_split:&#039; : &#039;&lt;br /&gt;
will return a collection containing: &amp;lt;code&amp;gt;(&#039;some&#039; &#039;string&#039; &#039;separated&#039; &#039;by&#039; &#039;space&#039; &#039;colon&#039; &#039;space&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Notice, that we used &amp;quot;&amp;lt;code&amp;gt;js_split:&amp;lt;/code&amp;gt;&amp;quot; in the above examples, which is the method used by JavaScript&#039;s &amp;quot;&amp;lt;code&amp;gt;split()&amp;lt;/code&amp;gt;&amp;quot; function. This is because in Smalltalk, the &amp;quot;&amp;lt;code&amp;gt;split:&amp;lt;/code&amp;gt;&amp;quot; method has a different semantics: the receiver is a &amp;quot;&#039;&#039;splitter&#039;&#039;&amp;quot;, and the argument is splitted by it.&lt;br /&gt;
&amp;lt;br&amp;gt;In Smalltalk, the splitter can be both a simple string or a [[Regex Pattern Info| regular expression]]. For example:&lt;br /&gt;
&lt;br /&gt;
    &#039;[a-z]*&#039; asRegex split:&#039;123abc456def789&#039;&lt;br /&gt;
&lt;br /&gt;
will generate the collection: &amp;lt;code&amp;gt;#(&#039;123&#039; &#039;456&#039; &#039;789&#039;)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To split into same-sized pieces, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; splitForSize: &#039;&#039;charCount&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
this may be less of interest for strings, but is handy to split fixed records of binary data (remember: these functions are implemented in a superclass of &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt;, from which &amp;lt;code&amp;gt;ByteArray&amp;lt;/code&amp;gt; also inherits).&lt;br /&gt;
&lt;br /&gt;
==== Joining and Concatenating Strings ====&lt;br /&gt;
&lt;br /&gt;
The simplest of them is the &amp;quot;,&amp;quot; (comma) operator. This takes two collections (and as such also Strings) and creates a new collection containing the concatenation of them.&lt;br /&gt;
Thus:&lt;br /&gt;
&lt;br /&gt;
    &#039;hello&#039; , &#039;world&#039;&lt;br /&gt;
&lt;br /&gt;
will create a new string containing &#039;helloworld&#039;,&lt;br /&gt;
and:&lt;br /&gt;
    &#039;hello&#039; , &#039; &#039; , &#039;world&#039;&lt;br /&gt;
&lt;br /&gt;
will give you &#039;hello world&#039;,&lt;br /&gt;
&amp;lt;br&amp;gt;and:&lt;br /&gt;
    #(1 2 3) , #(4 5 6)&lt;br /&gt;
will generate a 6-element array containing the elements 1 to 6.&lt;br /&gt;
&lt;br /&gt;
Notice that concatenation may become somewhat inefficient, if many strings are concatenated,&lt;br /&gt;
because many temporary string objects are created. Its time complexity is O(n&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;), where n is the number of strings concatenated.&lt;br /&gt;
&lt;br /&gt;
If you have to construct a string from many substrings, either use one of the join functions below with O(n) complexity,&lt;br /&gt;
or a writeStream with O(n log n) complexity (eg. the &amp;lt;code&amp;gt;streamContents:&amp;lt;/code&amp;gt; message).&lt;br /&gt;
Both handle the reallocations much more efficiently (actually: avoiding most of them).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To join a set of strings, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;asCollectionOfStrings&#039;&#039; asStringWith: &#039;&#039;separator&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
where separator may be a character, a separator string or nil.&lt;br /&gt;
For example:&lt;br /&gt;
    #( &#039;a&#039; &#039;b&#039; &#039;c&#039;) asStringWith:nil&lt;br /&gt;
gives &#039;abc&#039;,&lt;br /&gt;
and:&lt;br /&gt;
    #( &#039;a&#039; &#039;b&#039; &#039;c&#039;) asStringWith:&#039; : &#039;&lt;br /&gt;
returns: &#039;a : b : c&#039;&lt;br /&gt;
&lt;br /&gt;
Using a writeStream, write:&lt;br /&gt;
&lt;br /&gt;
    |w result|&lt;br /&gt;
 &lt;br /&gt;
    w := WriteStream on:(String new:10).&lt;br /&gt;
    w nextPutAll: &#039;a&#039;.&lt;br /&gt;
    w nextPutAll: &#039;b&#039;.&lt;br /&gt;
    ...&lt;br /&gt;
    result := w contents&lt;br /&gt;
&lt;br /&gt;
or, using a convenient utility method (which does exactly the same):&lt;br /&gt;
&lt;br /&gt;
    result := String streamContents:[:s |&lt;br /&gt;
        s nextPutAll: &#039;hello&#039;.&lt;br /&gt;
        s nextPutAll: &#039;world&#039;.&lt;br /&gt;
        ...&lt;br /&gt;
        s nextPutAll: &#039;Nice world&#039;&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
but please read more on streams in the stream chapter below.&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings (Method A) ====&lt;br /&gt;
&lt;br /&gt;
For text messages, you may want to construct a pretty user readable string which contains printed representations of other objects.&lt;br /&gt;
For this, use:&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument1&#039;&#039; with: &#039;&#039;argument2&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWith: &#039;&#039;argument1&#039;&#039; with: ... with: &#039;&#039;argumentN&#039;&#039; (up to 5 arguments)&lt;br /&gt;
  &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWithArguments: &#039;&#039;argumentCollection&#039;&#039; (any number of arguments)&lt;br /&gt;
 &lt;br /&gt;
using the &amp;quot;&amp;lt;code&amp;gt;{ .. }&amp;lt;/code&amp;gt;&amp;quot; array constructor (notice the periods as expression separators), this is usually written as:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; bindWithArguments: { &#039;&#039;argument1&#039;&#039; . &#039;&#039;argument2&#039;&#039; . ... . &#039;&#039;argumentN&#039;&#039; }&lt;br /&gt;
&lt;br /&gt;
The formatString itself may contain &amp;quot;%X&amp;quot; placeholders, which are replaced by corresponding&lt;br /&gt;
printed representations of the argumentX. The arguments will be converted to strings if they are not, thus arbitrary objects can be given as argument (although, in practice, these are usually numbers).&lt;br /&gt;
&lt;br /&gt;
If many arguments are to be passed in,&lt;br /&gt;
the placeholder names X may consist of a single digit (1-9) only for the first 9 arguments.&lt;br /&gt;
For other arguments, you must write &amp;quot;%(X)&amp;quot;. I.e. &#039;%(10)&#039; to get the tenth argument sliced at that position (1).&lt;br /&gt;
&lt;br /&gt;
The last of the above methods is a powerful tool, in that it does not only handle argumentCollections indexed by numbers (i.e. Array of arguments), but also Dictionaries, which are indexed by name.&lt;br /&gt;
&lt;br /&gt;
For example, if you have a Dictionary collection of a person record (in expecco: a compound datatype instance), with element keys &amp;quot;firstName&amp;quot;, &amp;quot;lastName&amp;quot; and &amp;quot;city&amp;quot;,&lt;br /&gt;
you can generate a nice printed string with:&lt;br /&gt;
&lt;br /&gt;
    |record|&lt;br /&gt;
 &lt;br /&gt;
    record := Dictionary new.  &amp;quot;/ example using a dictionary&lt;br /&gt;
    record at:&#039;firstName&#039; put: &#039;Fritz&#039;.&lt;br /&gt;
    record at:&#039;lastName&#039; put: &#039;Müller&#039;.&lt;br /&gt;
    record at:&#039;city&#039; put: &#039;Stuttgart&#039;.&lt;br /&gt;
 &lt;br /&gt;
    &#039;%(lastName), %(firstName) lives in %(city)&#039; bindWithArguments: record.&lt;br /&gt;
&lt;br /&gt;
gives you the string: &#039;Müller, Fritz lives in Stuttgart&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;In combination with a expecco compound datatype instance, this would be:&lt;br /&gt;
&lt;br /&gt;
    |person|&lt;br /&gt;
 &lt;br /&gt;
    person := myType new.&lt;br /&gt;
    person firstName:&#039;Fritz&#039;.&lt;br /&gt;
    person lastName:&#039;Müller&#039;.&lt;br /&gt;
    person city:&#039;Stuttgart&#039;.&lt;br /&gt;
  &lt;br /&gt;
    &#039;%(lastName), %(firstName) lives in %(city)&#039; bindWithArguments: person.&lt;br /&gt;
&lt;br /&gt;
1) Note: this has been relaxed in 19.2, where %10 is allowed. However, all digits up to the first non-digit character will make up the index. If you need a sliced in value followed by a digit, you&#039;d still have to use %(x).&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings with Printf (Method B) ====&lt;br /&gt;
There is also a formatting method similar to &amp;quot;&amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt;&amp;quot;. It takes a format string and a number of arguments and constructs a string representation.&lt;br /&gt;
As Smalltalk does not support variable numbers of arguments, these must be passed with different keyword messages:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg1&#039;&#039; with:&#039;&#039;arg2&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printfWith:&#039;&#039;arg1&#039;&#039; with:&#039;&#039;arg2&#039;&#039; with:&#039;&#039;arg3&#039;&#039;&lt;br /&gt;
    ... up to 5 arguments&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;formatString&#039;&#039; printf:&#039;&#039;argVector&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For the argVector, use the &amp;quot;{&amp;quot; .. &amp;quot;}&amp;quot; construct.&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
    &#039;%05d 0x%-7x %f&#039; printf:{ 123 . 517 . 1.234 }&lt;br /&gt;
generates the string:&lt;br /&gt;
    &#039;00123 0x205     1.234&#039;&lt;br /&gt;
&lt;br /&gt;
The above provides the functionality of C&#039;s &amp;quot;sprintf&amp;quot; - i.e. it generates a string as result. However, streams also understand printf-messages, so you can also print directly to a stream:&lt;br /&gt;
&lt;br /&gt;
    Transcript printf:&#039;%05x\n&#039; with:12345&lt;br /&gt;
or:&lt;br /&gt;
    Transcript printf:&#039;%05x %d %f %o\n&#039; withAll:{ 123. 234*5. 1.234. 254 }&lt;br /&gt;
&lt;br /&gt;
Notice, that printf translates the standard C-character escapes &amp;quot;\n&amp;quot;, ”\t&amp;quot; etc.&lt;br /&gt;
&lt;br /&gt;
==== Formatting Strings with Embedded Expressions (Method C) ====&lt;br /&gt;
A string constant prefixed with &amp;quot;e&amp;quot; is a so called expression-string. This may contain Smalltalk expressions enclosed in &amp;quot;&amp;lt;code&amp;gt;{..}&amp;lt;/code&amp;gt;&amp;quot;, which are sliced into the string (actually, the expression&#039;s printString is sliced in). In addition, C-style escape sequences like &amp;quot;\n&amp;quot; are recognized in e-strings.&lt;br /&gt;
&amp;lt;br&amp;gt;Example:&lt;br /&gt;
&lt;br /&gt;
    Transcript show: e&#039;today is {Date today} and the time is {Time now}\nAnd the dayName is {Date today dayName}&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Regex and Glob Matching ====&lt;br /&gt;
&lt;br /&gt;
Both match a string against a match pattern, but the syntax and functionality is different.&lt;br /&gt;
* Glob is much easier to use but less powerful. Glob is the match algorithm used in the Unix and MS-DOS filesystem (e.g. when saying &amp;quot;&amp;lt;code&amp;gt;ls *.foo&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;dir *.foo&amp;lt;/code&amp;gt;&amp;quot; on the command line).&lt;br /&gt;
* [[Regex Pattern Info| Regex]] is the algorithm used in tools like &amp;quot;grep&amp;quot; and many text processing systems and languages.&lt;br /&gt;
&lt;br /&gt;
Notice that regex patterns are different and not just a superset of glob patterns. Especially the meanings of &amp;quot;*&amp;quot; and &amp;quot;.&amp;quot; are different.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Please consult Wikipedia for more information on Regex [https://en.wikipedia.org/wiki/Regular_expression] and GLOB [https://en.wikipedia.org/wiki/Glob_%28programming%29].&lt;br /&gt;
A chapter on regex is also found in this [[Regex Pattern Info| wiki]].&lt;br /&gt;
&lt;br /&gt;
For a Glob match, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aGlobPattern&#039;&#039; match:&#039;&#039;aString&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aGlobPattern&#039;&#039; match:&#039;&#039;aString&#039;&#039; caseSensitive:false&lt;br /&gt;
&lt;br /&gt;
or, reversed argument order, if you prefer:&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matches:&#039;&#039;aGlobPattern&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matches:&#039;&#039;aGlobPattern&#039;&#039; caseSensitive:false&lt;br /&gt;
&lt;br /&gt;
For a regex match, use:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039; caseSensitive:false&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; matchesRegex:&#039;&#039;aRegexPattern&#039;&#039; ignoringCase:true  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ an alias to the above&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sorry for the inconsistent method naming which is due to the fact that the regex matcher originated in a public domain package, which was developed independently from the original ST/X system. In order to remain compatible with other Smalltalk dialects, the names were kept.&lt;br /&gt;
&lt;br /&gt;
The CharacterArray class provides a whole bunch of useful match methods (eg. to extract multiple occurrences of a pattern, to do prefix matches and to extract sub patterns from a complex match pattern). Please use the class browser (from the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu) to find them.&lt;br /&gt;
&lt;br /&gt;
==== Code Converting ====&lt;br /&gt;
&lt;br /&gt;
There are code converters for various character encodings in and below the CharacterEncoder class.&lt;br /&gt;
Most of them are obsolete or seldom used these days, as now most systems support Unicode (which was not the case, the ST/X was written 30 years ago and switched to Unicode in the 90&#039;s!).&lt;br /&gt;
&lt;br /&gt;
In general, you can get an instance of an encoder via a convenient CharacterEncoder interface:&lt;br /&gt;
&lt;br /&gt;
    CharacterEncoder encoderFor:&amp;lt;encoding&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or:&lt;br /&gt;
&lt;br /&gt;
    CharacterEncoder encoderToEncodeFrom:&amp;lt;encoding1&amp;gt; to:&amp;lt;encoding2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where encoding is a name, such as &#039;iso8859-1&#039;, &#039;unicode&#039;, &#039;utf8&#039;, &#039;utf16&#039;, &#039;ascii&#039;, &#039;jis7&#039; etc.&lt;br /&gt;
&lt;br /&gt;
Thus, to encode a string from Unicode (which is the internal encoding anyway) to Japanese JIS0201, use:&lt;br /&gt;
&lt;br /&gt;
    (CharacterEncoder encoderFor:#&#039;jis0201&#039;) encode:&#039;hello&#039;&lt;br /&gt;
&lt;br /&gt;
or to encode from Microsoft cp1253 to koi8-r, use:&lt;br /&gt;
&lt;br /&gt;
    (CharacterEncoder encoderToEncodeFrom:#&#039;cp1253&#039; to:#&#039;koi8-r&#039;) encode:&amp;lt;&#039;&#039;someStringInCP1253&#039;&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will probably not need that general interface, but use UTF-8 these days.&lt;br /&gt;
For those, the String class provides easier to use interface:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; utf8Encoded&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aString&#039;&#039; utf8Decoded&lt;br /&gt;
&lt;br /&gt;
==== Collection Slices ====&lt;br /&gt;
&lt;br /&gt;
A slice is a reference to a subcollection, which looks and behaves like any other collection, but shares the underlying data with the original collection. Thus modifications in either the original or slice are visible in the other and vice versa.&lt;br /&gt;
&lt;br /&gt;
To get a slice, use one of the &amp;quot;&amp;lt;code&amp;gt;from:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;from:to:&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;to:&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;from:count:&amp;lt;/code&amp;gt;&amp;quot; methods (the names are similar to the above mentioned &amp;quot;copy*&amp;quot; methods).&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    data := ... some big ByteArray read from a file ...&lt;br /&gt;
 &lt;br /&gt;
    record1 := data from:1 to:recordSize.&lt;br /&gt;
    record2 := data from:(recordSize+1) to:recordSize*2.&lt;br /&gt;
    etc.&lt;br /&gt;
&lt;br /&gt;
gives you the records from the big collection as individual objects. If any modification is made to any of the slices, that modification is actually made in the underlying data collection (i.e. C-Programmers may think of this as a &amp;quot;&#039;&#039;pointer into the data object&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Slices are especially useful with bulk data processing, to avoid the creation of individual record copies. &lt;br /&gt;
&lt;br /&gt;
However, they are a bit dangerous, as the programmer has to be always aware of possible side effects. If you are uncertain, do not pass a slice to another (unknown) function; instead use the corresponding copy methods.&lt;br /&gt;
&lt;br /&gt;
=== Stream Handling ===&lt;br /&gt;
&lt;br /&gt;
Streams can be both internal streams (streaming out-of or into a collection) or external streams.&lt;br /&gt;
External streams are always byte- or character-oriented and operate on files, sockets, pipes or i/o devices.&lt;br /&gt;
An internal stream&#039;s element type depends on the underlying collection, but String-streams are most common.&lt;br /&gt;
&lt;br /&gt;
The following presents only a very small excerpt of the full stream protocol.&lt;br /&gt;
Please refer to the online documentation of the Smalltalk/X stream classes.&lt;br /&gt;
&lt;br /&gt;
==== Creating (Internal Streams) ====&lt;br /&gt;
&lt;br /&gt;
streams for reading:&lt;br /&gt;
 rs := ReadStream on:&#039;&#039;aCollection&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
 rs := &#039;&#039;aCollection&#039;&#039; readStream&lt;br /&gt;
&lt;br /&gt;
streams for writing:&lt;br /&gt;
 ws := WriteStream on:(String new:&#039;&#039;initialSize&#039;&#039;)&lt;br /&gt;
 &lt;br /&gt;
 ws := &amp;amp;#39;&amp;amp;#39; writeStream&lt;br /&gt;
 &lt;br /&gt;
 ws := WriteStream on:(Array new)&lt;br /&gt;
&lt;br /&gt;
notice that the underlying collection is reallocated when more elements are added due to nextPut: operations.&lt;br /&gt;
The reallocations are done by doubling the size, resulting in O(n log n) complexity. If you have a rough idea on the final size, preallocating with an initialSize avoids or reduces the number of reallocations.&lt;br /&gt;
&lt;br /&gt;
==== Checking ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; atEnd&lt;br /&gt;
returns true iff the read stream &amp;quot;s&amp;quot; is positioned at the end.&lt;br /&gt;
 &#039;&#039;s&#039;&#039; size&lt;br /&gt;
returns the size of the read stream&#039;s buffer, or the number of elements written into a write stream.&lt;br /&gt;
&lt;br /&gt;
==== Positioning ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; position&lt;br /&gt;
&lt;br /&gt;
returns the stream&#039;s current read position, starting at 0 when at the beginning.&lt;br /&gt;
I.e. position represents the number of elements which have already been read or written.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; position:&#039;&#039;pos&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
set the position.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; rewind&lt;br /&gt;
&lt;br /&gt;
reset the position to the beginning&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; setToEnd&lt;br /&gt;
&lt;br /&gt;
set the position to the end (normally only useful for appending write streams)&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; backStep&lt;br /&gt;
&lt;br /&gt;
position one element backwards&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;s&#039;&#039; skip:n&lt;br /&gt;
&lt;br /&gt;
skip n elements when reading&lt;br /&gt;
&lt;br /&gt;
==== Reading ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; next&lt;br /&gt;
&lt;br /&gt;
retrieve the next element from the stream. Nil if there are no more elements.&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;rs&#039;&#039; next:&#039;&#039;count&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
retrieve the next &amp;quot;n&amp;quot; elements from the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; nextAvailable:&#039;&#039;count&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve the next &amp;quot;n&amp;quot; elements or whatever number of elements are available.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; upTo:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve elements up to an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; skipTo:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
skip over elements up to an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; through:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
retrieve elements up-to and including an element which is equal to &amp;quot;element&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;rs&#039;&#039; peek&lt;br /&gt;
&lt;br /&gt;
retrieve the next element from the stream but does not advance the read pointer. Nil if there are no more elements. The next call to any of the above will see this character (again).&lt;br /&gt;
&lt;br /&gt;
==== Writing ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPut:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append element to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; next:&#039;&#039;count&#039;&#039; put:&#039;&#039;element&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append element multiple times to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPutAll:&#039;&#039;aCollectionOfElements&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append all elements from the given collection to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; println&lt;br /&gt;
&lt;br /&gt;
append a newline character.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; cr&lt;br /&gt;
&lt;br /&gt;
also&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; nextPutLine:&#039;&#039;aCollectionOfElements&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append all elements from the given collection followed by a newline to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; print:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append a printed representation of anObject (for humans) to the stream.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; store:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append the printed representation of anObject (for the system) to the stream.&lt;br /&gt;
Unless the object has recursive references, a copy of the element can be reconstructed with &amp;lt;code&amp;gt;Object readFrom:&amp;lt;/code&amp;gt;&#039;&#039;aReadStream&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; println:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
append a printed representation of anObject (for humans) to the stream, followed by a newline.&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; printCR:&#039;&#039;anObject&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
the same&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;ws&#039;&#039; contents&lt;br /&gt;
&lt;br /&gt;
retrieve the stream&#039;s contents (typically, the characters buffered so far)&lt;br /&gt;
&lt;br /&gt;
==== File Streams ====&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;aString&#039;&#039; asFilename readStream&lt;br /&gt;
 &lt;br /&gt;
 &#039;&#039;aString&#039;&#039; asFilename writeStream&lt;br /&gt;
&lt;br /&gt;
See more below in the chapter on [[#File_Operations |file operations]].&lt;br /&gt;
&lt;br /&gt;
=== Numbers ===&lt;br /&gt;
&lt;br /&gt;
==== Reading Numbers from a String ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To read a number from a string, use the &amp;quot;readFrom:&amp;quot; method provided by the number classes,&lt;br /&gt;
where the argument is either a string, or a headstream.&lt;br /&gt;
A readstream is obtained with either &amp;quot;&amp;lt;code&amp;gt;(ReadStream on:&#039;&#039;aString&#039;&#039;)&amp;lt;/code&amp;gt;&amp;quot; or the more convenient &amp;quot;&amp;lt;code&amp;gt;(&#039;&#039;aString&#039;&#039; readStream)&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Thus, in general, code to read a number looks like:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039;&lt;br /&gt;
or:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;&#039;aString&#039;&#039;)&lt;br /&gt;
or:&lt;br /&gt;
    &amp;lt;class&amp;gt; &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (&#039;&#039;aString&#039;&#039; readStream)&lt;br /&gt;
&lt;br /&gt;
where &amp;quot;&amp;lt;class&amp;gt;&amp;quot; is one of &amp;quot;&amp;lt;code&amp;gt;Integer&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;Float&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;FixedPoint&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
If &amp;quot;&amp;lt;class&amp;gt;&amp;quot; is &amp;quot;&amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt;&amp;quot;, any type of number will be read and returned. Otherwise, only that type of number will be accepted (i.e. &amp;quot;&amp;lt;code&amp;gt;Integer readFrom:&#039;&#039;String&#039;&#039;&amp;lt;/code&amp;gt;&amp;quot;, will report an error if there is a decimal point in the string.&lt;br /&gt;
&lt;br /&gt;
If the string contains nothing but the number string, the above two code expressions behave the same.&lt;br /&gt;
However, there is an often overlooked difference in case of extra characters after the number:&lt;br /&gt;
&lt;br /&gt;
* the string-reader expects that the given string contains a representation of a corresponding number object, and NO extra characters before or after it. It will report an error otherwise.&lt;br /&gt;
&lt;br /&gt;
* in contrast, the stream reader will first skip any spaces, then read as many characters as required from the stream, return the number and leave the stream positioned after the number. It will report an error if no number can be read. More values can be read from the stream if required.&lt;br /&gt;
&lt;br /&gt;
Thus both:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234&#039;&lt;br /&gt;
and:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;1234&#039;).&lt;br /&gt;
&lt;br /&gt;
return the Integer object 1234.&lt;br /&gt;
&lt;br /&gt;
Whereas:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234bla&#039;&lt;br /&gt;
will raise an error, but:&lt;br /&gt;
    myStream := ReadStream &#039;&#039;&#039;on:&#039;&#039;&#039; &#039;1234bla&#039;.&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.&lt;br /&gt;
&lt;br /&gt;
returns the integer 1234 and leave the stream positioned on the &#039;bla&#039;. Thus further elements can be read from the stream later.&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;Integer readFrom:&amp;lt;/code&amp;gt;&amp;quot; will read an integer, but not a float.&lt;br /&gt;
Thus:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;1234.5&#039;&lt;br /&gt;
will raise an error, but:&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; (ReadStream on:&#039;1234.5&#039;).&lt;br /&gt;
&lt;br /&gt;
will return the Integer object 1234 and leave the stream positioned on the decimal point character.&lt;br /&gt;
&lt;br /&gt;
When expecting an arbitrary number (e.g. with or without decimal point),&lt;br /&gt;
use:&lt;br /&gt;
    Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039;&lt;br /&gt;
which will return either an integer object or a float object depending on what it gets.&lt;br /&gt;
&lt;br /&gt;
If you want to enforce getting a float, use&lt;br /&gt;
    Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039;&lt;br /&gt;
which returns the float &amp;quot;1234.0&amp;quot;, even when given the string &amp;quot;1234&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The above assumes that a period is the decimalpoint character; use:&lt;br /&gt;
    Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacter:&#039;&#039;&#039; &#039;&#039;decimalPointCharacter&#039;&#039;&lt;br /&gt;
if another character is expected (eg. $, for a German number),&lt;br /&gt;
or use:&lt;br /&gt;
    Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;&#039;decimalPointCharacters&#039;&#039;&lt;br /&gt;
to allow for a number of characters (given as Array of characters or as String).&lt;br /&gt;
Thus:&lt;br /&gt;
    Number readFrom:myString decimalPointCharacters:&#039;,.&#039;&lt;br /&gt;
will accept either English or German numbers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Error handling =====&lt;br /&gt;
&lt;br /&gt;
By default, the readers raise an exception, if any conversion error occurs.&lt;br /&gt;
This can be caught in an error handler as described elsewhere (hint: catch the error with &amp;quot;&amp;lt;code&amp;gt;on:do:&amp;lt;/code&amp;gt;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
However, the conversion routines can also be given a correction function as argument,&lt;br /&gt;
which is invoked in case of an error, and which provides a replacement value. This is easier and shorter to write then an exception handler.&lt;br /&gt;
&lt;br /&gt;
For this, all of the methods described are also present in a variant with an extra &amp;quot;&amp;lt;code&amp;gt;onError:&amp;lt;/code&amp;gt;&amp;quot; argument, which provides that replacement.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aString&#039;&#039; &#039;&#039;&#039;onError:&#039;&#039;&#039; [ 0 ]&lt;br /&gt;
&lt;br /&gt;
will return the number as usual if OK, but zero if not.&lt;br /&gt;
&amp;lt;br&amp;gt;Of course, arbitrary code can be provided inside this handler - especially it may show an error dialog and ask the user for a replacement, or return from the executed elementary block:&lt;br /&gt;
&lt;br /&gt;
    val := Integer&lt;br /&gt;
            &#039;&#039;&#039;readFrom:&#039;&#039;&#039;aString&lt;br /&gt;
            &#039;&#039;&#039;onError:&#039;&#039;&#039;[&lt;br /&gt;
                |ersatz|&lt;br /&gt;
                ersatz := Dialog &#039;&#039;&#039;request:&#039;&#039;&#039;&#039;Please enter a correct number&#039;.&lt;br /&gt;
                Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;ersatz&lt;br /&gt;
            ]&lt;br /&gt;
&lt;br /&gt;
===== Reading with a Different Decimal Point Character =====&lt;br /&gt;
&lt;br /&gt;
If the number was originally for a european, it may contain a decimal point different from &amp;quot;.&amp;quot; -&lt;br /&gt;
for example, in Germany you may encouter a monetary amount as &amp;quot;1245,99&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
For this, use:&lt;br /&gt;
&lt;br /&gt;
    Float &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,&#039;&lt;br /&gt;
&lt;br /&gt;
or (better):&lt;br /&gt;
&lt;br /&gt;
    FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,&#039;&lt;br /&gt;
&lt;br /&gt;
If your code has to deal with both US and German numbers, provide all possible decimal points in the string, as in:&lt;br /&gt;
&lt;br /&gt;
    FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; &#039;&#039;aStringOrStream&#039;&#039; &#039;&#039;&#039;decimalPointCharacters:&#039;&#039;&#039; &#039;,.&#039;&lt;br /&gt;
&lt;br /&gt;
===== Reading Multiple Numbers from a Stream =====&lt;br /&gt;
&lt;br /&gt;
A common task is to read multiple numbers from a single long string.&lt;br /&gt;
Of course, you could first split the string into pieces and use the above &amp;quot;readFrom:&amp;quot; on each.&lt;br /&gt;
&lt;br /&gt;
This may also be a quick&amp;amp;dirty solution, if the individual number strings are contained in fixed-length fields and there are no separators in between the fields (but read below for a better way to do this).&lt;br /&gt;
Take a look at the string handling examples on how to split strings.&lt;br /&gt;
&lt;br /&gt;
To read multiple numbers, the best solution is to first create a read stream on the string, then read the individual numbers:&lt;br /&gt;
&lt;br /&gt;
    myString := &#039;1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234&#039;.&lt;br /&gt;
    myStream := myString &#039;&#039;&#039;readStream&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
    n1 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the integer 1234 in n1&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the float 456.7 in n2&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the float 0.5 in n3&amp;lt;/span&amp;gt;&lt;br /&gt;
    n4 := FixedPoint &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the fixedPoint 2345.3456 in n4&amp;lt;/span&amp;gt;&lt;br /&gt;
    n5 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039; myStream.      &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gives the large integer 3234...34 in n5&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;readFrom:&amp;lt;/code&amp;gt;&amp;quot; first skips any separators (spaces) - therefore no extra code is needed to deal with those.&lt;br /&gt;
&lt;br /&gt;
If extra stuff needs to be skipped, use any of the existing stream functions (&amp;lt;code&amp;gt;skipFor:&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;skipUntil:&amp;lt;/code&amp;gt; etc.). If none does the job, you can look at individual characters and skip until a match is found.&lt;br /&gt;
For example, to read 3 numbers from the following string &#039;123 bla 456.8|0.5&#039;,&lt;br /&gt;
you could use:&lt;br /&gt;
&lt;br /&gt;
    s := &#039;123 bla 456.8|0.5&#039; readStream.&lt;br /&gt;
    n1 := Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s &#039;&#039;&#039;skipSeparators&#039;&#039;&#039;.&lt;br /&gt;
    s &#039;&#039;&#039;nextAlphanumericWord&#039;&#039;&#039;.  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over the &#039;bla&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s next.                  &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over one character&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
of course, the above code would not handle strings like &#039;123 bla bla 456.8|0.5&#039; or &#039;123 bla 456.8 |0.5&#039;.&lt;br /&gt;
&amp;lt;br&amp;gt;Using &amp;quot;peek&amp;quot;, which looks at the next character in the stream without consuming it,&lt;br /&gt;
we could to change the code to:&lt;br /&gt;
&lt;br /&gt;
    n1 := Integer &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    [ s &#039;&#039;&#039;peek&#039;&#039;&#039; &#039;&#039;&#039;isDigit&#039;&#039;&#039; ] &#039;&#039;&#039;whileFalse:&#039;&#039;&#039;[ s &#039;&#039;&#039;next&#039;&#039;&#039; ]. &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over the &#039;bla bla&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    n2 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
    s &#039;&#039;&#039;next&#039;&#039;&#039;.                                   &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ skips over one character&amp;lt;/span&amp;gt;&lt;br /&gt;
    n3 := Number &#039;&#039;&#039;readFrom:&#039;&#039;&#039;s.&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;&amp;lt;code&amp;gt;peek&amp;lt;/code&amp;gt;&amp;quot; returns nil, if the end of the stream is reached. And that &amp;quot;&amp;lt;code&amp;gt;nil isDigit&amp;lt;/code&amp;gt;&amp;quot; will report an error (because only characters can be asked for being a digit).&lt;br /&gt;
Thus, the code like the above is not prepared to read a variable number of numbers.&lt;br /&gt;
&lt;br /&gt;
===== Reading with Scanf =====&lt;br /&gt;
&lt;br /&gt;
There is also a C-like scanf utility, which can read numbers, strings, characters in various formats.&lt;br /&gt;
&lt;br /&gt;
    myString := &#039;1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234&#039;.&lt;br /&gt;
    values := &#039;%d %f %f %f %d&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039; myString.&lt;br /&gt;
&lt;br /&gt;
generates a collection of numbers in &amp;quot;values&amp;quot;: &lt;br /&gt;
    OrderedCollection(1234 456.7 0.5 2345.3456 3234234234234234234234234234234234234)&lt;br /&gt;
&lt;br /&gt;
The details and format characters are described in the PrintfScanf utility class, here is a short summary:&lt;br /&gt;
&lt;br /&gt;
Conversions (upper case same as lower case):&lt;br /&gt;
* &#039;b&#039;     binary (base 2)&lt;br /&gt;
* &#039;c&#039;     character or (first char of string)&lt;br /&gt;
* &#039;d&#039;     decimal&lt;br /&gt;
* &#039;e&#039;     float&lt;br /&gt;
* &#039;f&#039;     float&lt;br /&gt;
* &#039;g&#039;     float&lt;br /&gt;
* &#039;i&#039;     integer (alias for &#039;d&#039;)&lt;br /&gt;
* &#039;o&#039;     base-8 octal&lt;br /&gt;
* &#039;s&#039;     string&lt;br /&gt;
* &#039;u&#039;     integer&lt;br /&gt;
* &#039;x&#039;     base-16 hex&lt;br /&gt;
&lt;br /&gt;
Length prefix:&lt;br /&gt;
&lt;br /&gt;
* &#039;h&#039;     with float formats: reads as ShortFloat&lt;br /&gt;
* &#039;L&#039;     with float formats: reads as LongFloat&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
* &#039;%d %x&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00&#039;         -&amp;gt; OrderedCollection(1234 65280)&lt;br /&gt;
* &#039;%d %s&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00&#039;         -&amp;gt; OrderedCollection(1234 &#039;ff00&#039;)&lt;br /&gt;
* &#039;%d %x %b&#039; &#039;&#039;&#039;scanf:&#039;&#039;&#039;&#039;1234 ff00 1001&#039; -&amp;gt; OrderedCollection(1234 65280 9)&lt;br /&gt;
&lt;br /&gt;
==== Reading a Particular Number of Numbers from a Stream ====&lt;br /&gt;
&lt;br /&gt;
Assume that you are given a number which defines how many numbers to extract from a given string.&lt;br /&gt;
&lt;br /&gt;
Of course, you can use a &amp;quot;&amp;lt;code&amp;gt;start to: stop do:[:idx |...&amp;lt;/code&amp;gt;&amp;quot; loop,&lt;br /&gt;
but experienced Smalltalk programmers make use of the collection protocol,&lt;br /&gt;
as in:&lt;br /&gt;
    (1 to: count) collect:[:idx | Number readFrom:aStream ]&lt;br /&gt;
&lt;br /&gt;
Such a construct is needed e.g. when you have to parse a string, where the first entry defines how many numbers follow:&lt;br /&gt;
&lt;br /&gt;
    coll := (1 to: (Integer readFrom:myString)) collect:[:idx | Number readFrom:aStream ].&lt;br /&gt;
&lt;br /&gt;
which would parse the string &amp;quot;5 1.0 3.0 2.0 -1.0 .05&amp;quot; into a 5-element collection containing the converted numbers.&lt;br /&gt;
&lt;br /&gt;
==== Reading a Variable Number of Numbers from a Stream ====&lt;br /&gt;
&lt;br /&gt;
To do so, we should collect numbers as being read from the stream in a collection:&lt;br /&gt;
&lt;br /&gt;
    collectedNumbers := OrderedCollection new.&lt;br /&gt;
 &lt;br /&gt;
    [ aStream atEnd ] whileFalse:[&lt;br /&gt;
        collectedNumbers add: ( Number readFrom:aStream ).&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
or, if any non-digits and non-spaces between numbers should be skipped,&lt;br /&gt;
use:&lt;br /&gt;
&lt;br /&gt;
    collectedNumbers := OrderedCollection new.&lt;br /&gt;
 &lt;br /&gt;
    [ aStream atEnd ] whileFalse:[&lt;br /&gt;
        aStream skipUntil:[:char | char isDigit].&lt;br /&gt;
        collectedNumbers add:( Number readFrom:aStream ).&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
==== Using the Pattern Matcher to Extract Parts ====&lt;br /&gt;
&lt;br /&gt;
In rare situations, complex patterns need to be matched and numeric values&lt;br /&gt;
retrieved from the matched parts. For this, use a regex pattern matcher to first extract parts from the string, and then convert the substrings.&lt;br /&gt;
For example, to fetch numbers after certain keywords in a string, you could use:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ assuming that the string is of the form:&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/    &amp;lt;..arbitrary-text...&amp;gt;key1&amp;lt;number1&amp;gt;&amp;lt;...arbitrary text...&amp;gt;key2&amp;lt;number&amp;gt;&amp;lt;...arbitrary text...&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ where arbitrary text may even contain key1 and key2, but not followed by a number,&amp;lt;/span&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ we first use a regex to match, then convert the matched regex parts:&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    myString := &#039;bla bla key1 bla key11234more bla key2 bla key29876bla bla&#039;.&lt;br /&gt;
 &lt;br /&gt;
    parts := myString allRegexMatches:&#039;((key[12]))([0-9]+)&#039;.&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ now, parts contains #( &#039;key11234&#039; &#039;key29876&#039;&amp;lt;/span&amp;gt;&lt;br /&gt;
    numbers := parts collect:[:eachPart | Number readFrom: (eachPart copyFrom:5) ].&lt;br /&gt;
    &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ now, numbers contains #( 1234 9876 )&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
notice that &#039;&#039;parts&#039;&#039; delivers the matched strings i.e. the collection (&#039;key11234&#039; &#039;key29876&#039;),&lt;br /&gt;
so that we have to skip over the &#039;keyX&#039; prefix before extracting the numbers.&lt;br /&gt;
&lt;br /&gt;
=== File Operations ===&lt;br /&gt;
&lt;br /&gt;
Expecco (i.e. Smalltalk) represents file names as instances of a specialized class called &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot;. These look similar to strings, but provide an abstraction over details of the underlying file- and operating system.&lt;br /&gt;
 &lt;br /&gt;
This makes it possible to write portable code which runs on Windows, Linux and even VMS, even though these systems use very different filename separators and volume naming schemes.&lt;br /&gt;
&lt;br /&gt;
Thus, we recommend to use filename operations instead of string concatenation, e.g. to construct pathnames.&lt;br /&gt;
In Smalltalk, the abstract class &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot; is subclassed by concrete classes named &amp;quot;&amp;lt;code&amp;gt;PCFilename&amp;lt;/code&amp;gt;&amp;quot; or &amp;quot;&amp;lt;code&amp;gt;UnixFilename&amp;lt;/code&amp;gt;&amp;quot;. &lt;br /&gt;
You should not access those concrete classes explicitly by name! &lt;br /&gt;
Instead, always refer to &amp;quot;&amp;lt;code&amp;gt;Filename&amp;lt;/code&amp;gt;&amp;quot; and let Smalltalk decide, which concrete class to use.&lt;br /&gt;
(unless you know that you are dealing with a unix-style filename, independent of your operating system, which is e.g. the case if you deal with CVS names or you get file-URLS as strings).&lt;br /&gt;
&lt;br /&gt;
for now, a short summary:&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aString&#039;&#039; asFilename  - to get a Filename-instance for a given String instance &lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readStream - to get a readStream on the contents of a file&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; writeStream - to get a writeStream writing to a file&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; appendingWriteStream - to get a writeStream appending to the end of a file&lt;br /&gt;
&lt;br /&gt;
==== Checking ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; exists &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ true if the file exists&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isReadable &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ true if it is readable&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isWritable&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isExecutable &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ for folders, this means: &amp;quot;can be changed into&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isExecutableProgram&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; fileSize&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isNonEmptyDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isRegularFile&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isSymbolicLink&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; info &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gets all info; follows any symbolic link. Includes ownerID, groupID, access and modification times etc.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; linkInfo &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ gets all info of a symbolic link itself. Includes ownerID, groupID, access and modification times etc.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; accessTime&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; modificationTime&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; creationTime &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ (same as modificationTime on Unix systems)&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; fileType&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; mimeType&lt;br /&gt;
&lt;br /&gt;
==== File names ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; pathName&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ the containing directory, as a Filename instance&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryName &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ditto, as string&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; baseName&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; suffix&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; hasSuffix:&#039;&#039;aString&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isAbsolute&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; isRelative&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; / &#039;&#039;subPath&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ yes, &amp;quot;/&amp;quot; is an operator to construct the name of a file inside a folder&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; construct:&#039;&#039;subPath&#039;&#039; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ alternative to &amp;quot;/&amp;quot;&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Operations ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; makeDirectory&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveMakeDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ ensures that all folders along the path are also created.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; removeDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ raises an error, if the folder is not empty&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveRemoveDirectory &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ removes everything below also&amp;lt;/span&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; moveTo:&#039;&#039;newName&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; copyTo:&#039;&#039;newName&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; recursiveCopyTo:&#039;&#039;destinationName&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== Directory Contents ====&lt;br /&gt;
&lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryContents&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; directoryContentsDo:[:eachFile | ...]&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; filesMatching:aGLOBPatternString&lt;br /&gt;
&lt;br /&gt;
==== File Contents ====&lt;br /&gt;
    &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; contents&lt;br /&gt;
retrieves the contents as a collection of line strings.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; contentsAsString&lt;br /&gt;
retrieves the contents as one (possibly big) string.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; binaryContentsOfEntireFile&lt;br /&gt;
retrieves the contents as one (possibly big) byte array.&lt;br /&gt;
Be careful - this should not be used for huge files.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readingLinesDo:[:eachLineString | ... ]&lt;br /&gt;
better use this for large files. Ensures that the file is closed.&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;aFilename&#039;&#039; readingFileDo:[:stream | ... ]&lt;br /&gt;
or that to read inside the code block. Ensures that the file is closed.&lt;br /&gt;
&lt;br /&gt;
=== Shared Data and Synchronization ===&lt;br /&gt;
&lt;br /&gt;
A number of mechanisms for synchronisation and mutual access to shared data structures are available: &amp;lt;code&amp;gt;Semaphore&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RecursionLock&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Monitor&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SharedQueue&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SharedCollection&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;synchronized:&amp;lt;/code&amp;gt; method, which is understood by every object.&lt;br /&gt;
For details, please refer to the Smalltalk/X Online Documentation.&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
The following code examples contain versions for Smalltalk, JavaScript, Groovy and Node.js.&lt;br /&gt;
Notice that Groovy and Node.js actions are invoked via a remote procedure call ([[Glossary#RPC|RPC]]) mechanism, which means that they are much slower due to the communication, encoding, decoding and general round trip delays. Therefore, Groovy and Node.js blocks (bridged actions in general) should only be used to access data inside the system under test or to call functions which are not available in the base system (such as additional protocols or hardware access, for which only a JAR or node- or python package is available). Or, functions for which the call overhead is small compared to the runtime (i.e. for heavy computing tasks, it may very well make sense).&lt;br /&gt;
&lt;br /&gt;
Thus, most of the examples below are for demonstration purposes, not for real world scenarios (i.e. it will certainly slow down your test runs, if you do math via Groovy or even Node.js, as shown below). &lt;br /&gt;
&lt;br /&gt;
Also bear in mind, that the underlying numeric representations are less flexible and more error-prone if you do math outside Smalltalk:&lt;br /&gt;
in Groovy, because there will be no signalling of overflow/underflow situations. Especially with integer arithmetic, which may be outside the 32bit/64bit range. Also, Java has no exact fraction representations, which means that you may loose precision in floating point operations.&lt;br /&gt;
&lt;br /&gt;
Things are even worse in Node.js, which represents all numbers as double precision floats, giving roughly 53 bits of precision. Thus, in Node.js the two integers 12345678901234567890 and 12345678901234567891 will be reported as being equal! (this may change in a future Node version, though).&lt;br /&gt;
&lt;br /&gt;
[[Datei:point_right.png|20px]] Do NOT use Groovy or Node.js for numeric computations, if large integer values are involved (or use a Bignum package).&lt;br /&gt;
&lt;br /&gt;
=== Reading/Writing Pin Values ===&lt;br /&gt;
&lt;br /&gt;
Assuming that the block has two input pins, named &amp;quot;&amp;lt;code&amp;gt;in1&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;in2&amp;lt;/code&amp;gt;&amp;quot; and two output pins, named &amp;quot;&amp;lt;code&amp;gt;out1&amp;lt;/code&amp;gt;&amp;quot; and &amp;quot;&amp;lt;code&amp;gt;out2&amp;lt;/code&amp;gt;&amp;quot;,&lt;br /&gt;
all of String type,&lt;br /&gt;
the following blocks write concatenated strings to both outputs:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    out1 value:(in1 value , in2 value).&lt;br /&gt;
    out2 value:(in2 value , in1 value).&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside the JVM, which may be the system under test or another machine running Java)&lt;br /&gt;
 def execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
(runs inside a node VM, which may be the system under test or another machine running &amp;quot;node&amp;quot;)&lt;br /&gt;
 function execute() {&lt;br /&gt;
    out1.value( in1.value() + in2.value() );&lt;br /&gt;
    out2.value( in2.value() + in1.value() );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Python =====&lt;br /&gt;
(runs inside a Python interpreter, which may be the system under test or another machine running &amp;quot;python&amp;quot;)&lt;br /&gt;
 def execute():&lt;br /&gt;
    out1.value( in1.value() + in2.value() )&lt;br /&gt;
    out2.value( in2.value() + in1.value() )&lt;br /&gt;
&lt;br /&gt;
===== C =====&lt;br /&gt;
 static void execute() {&lt;br /&gt;
    char* s1 = stringValue(in1);&lt;br /&gt;
    char* s2 = stringValue(in2);&lt;br /&gt;
    char buffer[512];&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s%s&amp;quot;, s1, s2);&lt;br /&gt;
    putString(out1, buffer);&lt;br /&gt;
 &lt;br /&gt;
    snprintf(buffer, sizeof(buffer), &amp;quot;%s%s&amp;quot;, s2, s1);&lt;br /&gt;
    putString(out1, buffer);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Note: be aware, that due to the Remote Procedure Call ([[Glossary#RPC|RPC]]), the calling overhead of bridged actions is in the order of milliseconds, &lt;br /&gt;
whereas actions executed inside expecco (Smalltalk and JavaScript) are executed typically within a few hundred nanoseconds.&lt;br /&gt;
&lt;br /&gt;
Thus, bridged actions are typically used to invoke longer running, complex operations or to trigger services, which run autonomous, or to talk to interfaces/devices. They are normally not be used for trivial operations like string manipulation or arithmetic.&lt;br /&gt;
&lt;br /&gt;
=== Reading/Writing Environment Variables ===&lt;br /&gt;
&lt;br /&gt;
Assuming that a String-typed environment variable named &amp;quot;&#039;&#039;IncDec&#039;&#039;&amp;quot; and an Integer-typed variable named &amp;quot;&#039;&#039;Counter&#039;&#039;&amp;quot; exist in the project&#039;s environment, and are writable,&lt;br /&gt;
the following blocks read and write to either variable:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    if ( environmentAt(&amp;quot;IncDec&amp;quot;) == &amp;quot;inc&amp;quot; ) {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) + 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) - 1);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    (self environmentAt:&#039;IncDec&#039;) = &#039;inc&#039; ifTrue:[&lt;br /&gt;
        self environmentAt:&#039;Counter&#039; put:(self environmentAt:&#039;Counter&#039;)+1.&lt;br /&gt;
    ] ifFalse:[&lt;br /&gt;
        self environmentAt:&#039;Counter&#039; put:(self environmentAt:&#039;Counter&#039;)-1.&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside the JVM, which may be the system under test or another machine running Java).&lt;br /&gt;
Notice that the environment-access from inside Groovy involves even more overhead, as those require another RPC call from Groovy back to expecco. When executed, the code below will make 4 full remote-procedure call roundtrips (1 for the call and return value, one for &amp;quot;environmentAt(IncDec)&amp;quot;, one for &amp;quot;environmentAt(Counter)&amp;quot; and a fourth one for &amp;quot;environmentAt_put()&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
 def execute() {&lt;br /&gt;
    if ( environmentAt(&amp;quot;IncDec&amp;quot;) == &amp;quot;inc&amp;quot; ) {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) + 1);&lt;br /&gt;
    } else {&lt;br /&gt;
        environmentAt_put(&amp;quot;Counter&amp;quot;, environmentAt(&amp;quot;Counter&amp;quot;) - 1);&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Sending Messages to the Transcript ===&lt;br /&gt;
The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; refers to the expecco console, if it has been opened (via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; menu). If it is not open, &amp;quot;Trnscript&amp;quot; will refer to the standard error stream (Stderr).&lt;br /&gt;
In place of &amp;quot;Transcript&amp;quot;, the following examples also work for &amp;quot;Stdout&amp;quot; and &amp;quot;Stderr&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    for (var y=1; y&amp;lt;=10; y++) {&lt;br /&gt;
        for (var x=1; x&amp;lt;=10; x++) {&lt;br /&gt;
            Transcript.show( x * y );&lt;br /&gt;
            Transcript.show( &amp;quot; &amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        Transcript.cr();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    Transcript showCR:&#039;---------------------&#039;.&lt;br /&gt;
    1 to:10 do:[:y |&lt;br /&gt;
        1 to:10 do:[:x |&lt;br /&gt;
            Transcript show:(x * y); show:&#039; &#039;.&lt;br /&gt;
        ].&lt;br /&gt;
        Transcript cr.&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
&lt;br /&gt;
A few of the common messages and objects for logging and printing are also made available to Groovy code. Of course, a hidden inter-process mechanism is used, which forwards those calls back to expecco (remember: the Groovy code runs inside the system under test). The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; object seen by Groovy code is such a proxy object which implements a subset of the Smalltalk Transcript object but passes the argument strings via IPC back to expecco.&lt;br /&gt;
So although the code looks similar to the above, the internal implementation (and timing) is completely different, because these calls are implemented as RPC calls from Groovy back to expecco.&lt;br /&gt;
&lt;br /&gt;
(runs inside JavaVM when executed)&lt;br /&gt;
 def execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    for (int y=1; y&amp;lt;=10; y++) {&lt;br /&gt;
        for (int x=1; x&amp;lt;=10; x++) {&lt;br /&gt;
            Transcript.show( x * y );&lt;br /&gt;
            Transcript.show( &amp;quot; &amp;quot; );&lt;br /&gt;
        }&lt;br /&gt;
        Transcript.cr();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
For compatibility with existing Java/Groovy code, the functions &amp;lt;code&amp;gt;print()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;println()&amp;lt;/code&amp;gt; can also be used&lt;br /&gt;
(in addition to the above used &amp;lt;code&amp;gt;show()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;showCR()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cr()&amp;lt;/code&amp;gt; functions)&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
&lt;br /&gt;
A subset of the logging and printing functions are available to Node code. Of course, a hidden inter-process mechanism is used, which forwards those calls back to expecco (remember: the code runs inside the system under test). The &amp;lt;code&amp;gt;Transcript&amp;lt;/code&amp;gt; object seen by Node code is such a proxy object which implements a subset of the Smalltalk Transcript object, but passes the argument strings via IPC back to expecco.&lt;br /&gt;
&lt;br /&gt;
So although the code looks similar to the above, the internal implementation (and timing) is completely different, because these calls are implemented as RPC calls from Node back to expecco.&lt;br /&gt;
&lt;br /&gt;
(runs inside Node when executed)&lt;br /&gt;
 function execute() {&lt;br /&gt;
    Transcript.showCR(&amp;quot;---------------------&amp;quot;);&lt;br /&gt;
    Transcript.show( &amp;quot;hello &amp;quot; );&lt;br /&gt;
    Transcript.show( &amp;quot;world&amp;quot; );&lt;br /&gt;
    Transcript.cr();&lt;br /&gt;
    Transcript.show( &amp;quot;A message with embedded args: %1 and %2\n&amp;quot;, &amp;quot;foo&amp;quot;, 123);&lt;br /&gt;
 }&lt;br /&gt;
For compatibility with existing Node programs, you can also use &amp;quot;&amp;lt;code&amp;gt;console.log()&amp;lt;/code&amp;gt;&amp;quot; &lt;br /&gt;
and &amp;quot;&amp;lt;code&amp;gt;console.error()&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Square Root Block ===&lt;br /&gt;
&lt;br /&gt;
A function, which computes the square root of its input value, could be implemented like that:&lt;br /&gt;
(the names of the pins are: &#039;&#039;in&#039;&#039; and &#039;&#039;out&#039;&#039;, their data type is &#039;&#039;Number):&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = in.value;          // Reading input pin value&lt;br /&gt;
    out.value( inValue.sqrt() ); // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
alternative:&lt;br /&gt;
 execute() {&lt;br /&gt;
    var inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = in.value;              // Reading input pin value&lt;br /&gt;
    out.value( Math.sqrt(inValue) ); // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |inValue|&lt;br /&gt;
 &lt;br /&gt;
    inValue := in value.       &amp;quot;/ Reading input pin value&lt;br /&gt;
    out value: inValue sqrt.   &amp;quot;/ Writing to output pin&lt;br /&gt;
&lt;br /&gt;
===== Groovy=====&lt;br /&gt;
(runs inside a JVM/the SUT, when executed).&amp;lt;br&amp;gt;As mentioned above, this kind of operation should definitely be executed in Smalltalk/JavaScript inside expecco, and not in the system under test, due to the [[Glossary|RPC]] overheads.&lt;br /&gt;
 def execute {&lt;br /&gt;
    Object inValue;&lt;br /&gt;
 &lt;br /&gt;
    inValue = inPin.value();           // Reading input pin value&lt;br /&gt;
    outPin.value(Math.sqrt(inValue));   // Writing to output pin&lt;br /&gt;
 }&lt;br /&gt;
(Notice: &amp;quot;in&amp;quot; is a reserved keyword in Groovy and cannot be used as pin name)&lt;br /&gt;
&lt;br /&gt;
===== Node=====&lt;br /&gt;
(runs inside Node, when executed).&lt;br /&gt;
 function execute {&lt;br /&gt;
    outPin.value(Math.sqrt(inPin.value()));  &lt;br /&gt;
 }&lt;br /&gt;
(Notice: &amp;quot;in&amp;quot; is a reserved keyword in Node and cannot be used as pin name)&lt;br /&gt;
&lt;br /&gt;
=== Random-Fail Block ===&lt;br /&gt;
&lt;br /&gt;
A block, which randomly fails (to demonstrate exception handling), could be implemented like:&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var dice;&lt;br /&gt;
 &lt;br /&gt;
    dice = Random.nextIntegerBetween_and_(1,6);&lt;br /&gt;
    if (dice &amp;lt;= 2) {&lt;br /&gt;
        fail();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |dice|&lt;br /&gt;
 &lt;br /&gt;
    dice := Random nextIntegerBetween:1 and:6.&lt;br /&gt;
    (dice &amp;lt;= 2) ifTrue:[&lt;br /&gt;
        self fail.&lt;br /&gt;
    ].&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
(runs inside a JVM/the SUT, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    Random rand = new Random();&lt;br /&gt;
    int dice = rand.nextInt(5)+1;&lt;br /&gt;
 &lt;br /&gt;
    if (dice &amp;lt;= 2) {&lt;br /&gt;
        fail();&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Calling other Actions ===&lt;br /&gt;
&lt;br /&gt;
Script code can call other action blocks via the &amp;quot;&amp;lt;code&amp;gt;call&amp;lt;/code&amp;gt;&amp;quot; method/function.&lt;br /&gt;
Notice, that the call is &amp;quot;&#039;&#039;by name&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;by ID&#039;&#039;&amp;quot;, and the called function is specified by a string argument.&lt;br /&gt;
The following examples assume that action blocks named &amp;quot;&#039;&#039;Action_A&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Action_B&#039;&#039;&amp;quot; are present, and that &amp;quot;Action_B&amp;quot; expects two numeric arguments and returns a value through its single output pin. &lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
 &lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;);&lt;br /&gt;
    result = call(&amp;quot;Action_B&amp;quot;, 123.0, 9999); &lt;br /&gt;
    Transcript.showCR(&amp;quot;got result: %1&amp;quot;, result);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/PRE&amp;gt;&amp;lt;/CODE&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
(runs inside expecco, when executed)&lt;br /&gt;
 execute&lt;br /&gt;
    |result|&lt;br /&gt;
 &lt;br /&gt;
    self call:&#039;Action_A&#039;.&lt;br /&gt;
    result := self call:&#039;Action_B&#039; _:123.0 _:9999). &lt;br /&gt;
    Transcript showCR:(&#039;got result: %1&#039; bindWith:result).&lt;br /&gt;
&lt;br /&gt;
===== Groovy =====&lt;br /&gt;
runs inside a JVM/the SUT, when executed, but the called actions are expecco actions; &lt;br /&gt;
i.e. the call performs a remote-procedure-call back to expecco, to execute the called action, and continue in the JVM&#039;s action when finished.&lt;br /&gt;
 execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
 &lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;);&lt;br /&gt;
    result = call(&amp;quot;Action_B&amp;quot;, 123.0, 9999); &lt;br /&gt;
    Transcript.showCR(&amp;quot;got result: %1&amp;quot;, result);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Node =====&lt;br /&gt;
runs inside the node interpreter, when executed.&lt;br /&gt;
The call performs a remote-procedure-call back to expecco, to execute the called action, and continue in the node action when finished.&lt;br /&gt;
&lt;br /&gt;
Notice, that due to the single threaded callback oriented nature of node,&lt;br /&gt;
the value from the called function is passed back via a callback function,&lt;br /&gt;
not as return value. This is required because the &amp;quot;call&amp;quot; is actually performing&lt;br /&gt;
a remote procedure call into expecco (i.e. interprocess communication).&lt;br /&gt;
It is also currently not possible to call another node action from a node action (neither directly, nor indirectly).&lt;br /&gt;
&lt;br /&gt;
 function execute() {&lt;br /&gt;
    var result;&lt;br /&gt;
    &lt;br /&gt;
    Transcript.showCR(&amp;quot;calling from Node...&amp;quot;);&lt;br /&gt;
    call(&amp;quot;Action_A&amp;quot;, function(err, result) {&lt;br /&gt;
        call(&amp;quot;Action_B&amp;quot;, 100, 200, function(err, result) {&lt;br /&gt;
            Transcript.showCR(&amp;quot;got value: %1&amp;quot;, result);&lt;br /&gt;
            success();&lt;br /&gt;
        });&lt;br /&gt;
    });&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Using the Smalltalk/X Class Library (Smalltalk and JavaScript Blocks Only) ===&lt;br /&gt;
&lt;br /&gt;
Please note, that besides these direct interfaces with the expecco system described here, you can also use the whole class library of the runtime system. Please check the corresponding [http://live.exept.de/doc/online/english/programming/TOP.html Smalltalk/X Documentation] as well as the [http://live.exept.de/ClassDoc Documentation of the Class APIs].&lt;br /&gt;
&lt;br /&gt;
expecco includes a fully featured class browser, to explore the underlying system&#039;s code.&lt;br /&gt;
&lt;br /&gt;
You will see the source code, if you have checked the &amp;quot;&#039;&#039;Install Source Code&#039;&#039;&amp;quot; checkbox during the installation procedure (if you did not, redo the installation, and only check this box). You can also access the source code via the public eXept CVS repository.&lt;br /&gt;
&lt;br /&gt;
The class browser is opened via the main-menu&#039;s &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Class Browser&#039;&#039;&amp;quot; item. It is documented in full detail in the [http://live.exept.de/doc/online/english/programming/TOP.html Smalltalk/X Documentation].&lt;br /&gt;
&lt;br /&gt;
Here are a few more examples, using that class library:&lt;br /&gt;
&lt;br /&gt;
=== Bulk-Data Reading from a File ===&lt;br /&gt;
&lt;br /&gt;
The following code reads a measurement data block of 100000 floating point values from file. The file was created beforehand by a recorder device, which was triggered by a dll-callout.&lt;br /&gt;
For the demonstration, the code below does not read its values from input pins. In a real world application, the size of the file and its fileName would probably be passed in via input pins, of course.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
 execute() {&lt;br /&gt;
    var N;        &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// should be read from an input-pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    var fileName; &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;// should be read from an input-pin&amp;lt;/span&amp;gt;&lt;br /&gt;
    var dataArray;&lt;br /&gt;
    var fileStream;&lt;br /&gt;
 &lt;br /&gt;
    N = 100000;&lt;br /&gt;
    fileName = &#039;dataFile.dat&#039;;&lt;br /&gt;
    fileStream = fileName.asFilename().readStream();&lt;br /&gt;
    dataArray = Array.new(N);&lt;br /&gt;
    for (i=1; i&amp;lt;=N; i++) {&lt;br /&gt;
        dataArray[i] = fileStream.nextIEEESingle();&lt;br /&gt;
    }&lt;br /&gt;
    out.value(dataArray);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |N fileName dataArray fileStream|&lt;br /&gt;
 &lt;br /&gt;
    N := 100000.&lt;br /&gt;
    fileName := &#039;dataFile.dat&#039;.&lt;br /&gt;
    fileStream := fileName asFilename readStream.&lt;br /&gt;
    dataArray := (1 to:N) collect:[:i | fileStream nextIEEESingle].&lt;br /&gt;
    out value:dataArray.&lt;br /&gt;
an alternative is:&lt;br /&gt;
    ...&lt;br /&gt;
    dataArray := N timesCollect:[:i | fileStream nextIEEESingle].&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
=== Opening/Using Smalltalk/X Applications, Dialogs and Components ===&lt;br /&gt;
&lt;br /&gt;
Any existing Smalltalk/X utility (both the one&#039;s which are provided with the base system, and even those coming from additional loaded Smalltalk code) can be called and used. For example, the following uses the builtin file dialog to ask for a directory.&lt;br /&gt;
&lt;br /&gt;
===== JavaScript =====&lt;br /&gt;
 execute() {&lt;br /&gt;
    var answer;&lt;br /&gt;
 &lt;br /&gt;
    answer = Dialog.requestDirectory(&amp;quot;Please select an output folder:&amp;quot;);&lt;br /&gt;
    if ( answer.notEmptyOrNil() ) {&lt;br /&gt;
        out.value( answer );&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |answer|&lt;br /&gt;
 &lt;br /&gt;
    answer := Dialog requestDirectory: &#039;Please select an output folder:&#039;.&lt;br /&gt;
    answer notEmptyOrNil ifTrue:[&lt;br /&gt;
        out value: answer&lt;br /&gt;
    ]&lt;br /&gt;
&lt;br /&gt;
Take a look at the &amp;quot;Dialog&amp;quot; class (using &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Tools&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Class Browser&#039;&#039;&amp;quot;), &lt;br /&gt;
where you&#039;ll find many common standard dialogs, for confirmations, simple questions, file dialogs etc.&lt;br /&gt;
&lt;br /&gt;
=== Loading Additional Smalltalk/X Code ===&lt;br /&gt;
&lt;br /&gt;
You can even create whole library or application packages, compile it as separate package, and load it dynamically to be used from within an elementary block. Assuming that a package named &amp;quot;myPackage.dll&amp;quot; (or &amp;quot;myPackage.so&amp;quot; under Unix/Linux) containing an application class named &amp;quot;MyApplication&amp;quot; has been created and is located in the expecco bin folder, the code can be loaded and executed with:&lt;br /&gt;
&lt;br /&gt;
===== Smalltalk =====&lt;br /&gt;
 execute&lt;br /&gt;
    |answer|&lt;br /&gt;
 &lt;br /&gt;
    Smalltalk loadPackage:&#039;myPackage&#039;. &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;&amp;quot;/ checks if already loaded, to only load the first time called&amp;lt;/span&amp;gt;&lt;br /&gt;
    MyApplication open.&lt;br /&gt;
&lt;br /&gt;
To create your own applications or addons, download the free [http://www.smalltalk-x.de Smalltalk/X development IDE ] for development and package building.&lt;br /&gt;
&lt;br /&gt;
== Expecco and Smalltalk API Stability ==&lt;br /&gt;
&lt;br /&gt;
The Smalltalk/X class library has been around for more than 30 years now,&lt;br /&gt;
and of course grew over time.&lt;br /&gt;
We have always tried hard to keep the API backward compatible, in not removing existing methods, even when new methods appeared, which provided a similar or superset functionality.&lt;br /&gt;
&lt;br /&gt;
Thus, code written 30 years ago can still depend on the interface and it is still working unchanged.&lt;br /&gt;
&lt;br /&gt;
We will continue to keep this backward compatibility in the future,&lt;br /&gt;
to avoid breaking customer code, whenever possible (there were very few exceptions in the past, where obvious bugs had to be fixed, and customer code already depended on the wrong behavior).&lt;br /&gt;
&lt;br /&gt;
That said, we must emphasize on that being only true for the ST/X class libraries themselves, and any officially published expecco APIs from this document.&lt;br /&gt;
&lt;br /&gt;
If you use internal expecco functionality (which you may find when browsing in the class browser),&lt;br /&gt;
we cannot guarantee backward compatibility in future versions.&lt;br /&gt;
If you feel a need for using such an interface, please consult/inform eXept to either get help on a cleaner solution, and/or inform us that the API is used and to get your used interface be marked as &amp;quot;stable EXPECCO_API&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Appendix ==&lt;br /&gt;
&lt;br /&gt;
=== Smalltalk Language Syntax (BNF) ===&lt;br /&gt;
&lt;br /&gt;
See also: [http://rosettacode.org/wiki/Category:Smalltalk Smalltalk Short Description (in rosettacode wiki)], [http://live.exept.de/doc/online/english/getstart/tut_2.html Smalltalk Basics]&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Notice: an elementary Smalltalk action&#039;s &amp;quot;execute&amp;quot; method is a unary method (no argument).&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; there can be only one single such method in an elementary action (private functions should be defined as Smalltalk blocks)&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; This is standard Smalltalk language, with Smalltalk/X language extensions&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;;&amp;lt;/span&amp;gt;&lt;br /&gt;
 method ::= selectorSpec body&lt;br /&gt;
 &lt;br /&gt;
 selectorSpec&amp;gt; ::= unarySelectorSpec&lt;br /&gt;
                   | binarySelectorSpec&lt;br /&gt;
                   | keywordSelectorSpec&lt;br /&gt;
 &lt;br /&gt;
 unarySelectorSpec ::= symbol&lt;br /&gt;
 &lt;br /&gt;
 binarySelectorSpec ::= binopSymbol identifier&lt;br /&gt;
 &lt;br /&gt;
 keywordSelectorSpec ::= ( keywordSymbol identifier )+&lt;br /&gt;
 &lt;br /&gt;
 body ::= [ &amp;quot;|&amp;quot; localVarList &amp;quot;|&amp;quot; ]  [statements]&lt;br /&gt;
 &lt;br /&gt;
 localVarList ::= ( identifier )+&lt;br /&gt;
 &lt;br /&gt;
 statements ::= statement&lt;br /&gt;
                | statement &amp;quot;.&amp;quot;&lt;br /&gt;
                | statement &amp;quot;.&amp;quot; statements&lt;br /&gt;
 &lt;br /&gt;
 statement ::= expression&lt;br /&gt;
               | returnStatement&lt;br /&gt;
 &lt;br /&gt;
 returnStatement ::= &amp;quot;^&amp;quot; expression&lt;br /&gt;
 &lt;br /&gt;
 expression ::= identifier &amp;quot;:=&amp;quot; expression&lt;br /&gt;
                | keywordExpression&lt;br /&gt;
 &lt;br /&gt;
 keywordExpression ::= binaryExpression&lt;br /&gt;
                       | binaryExpression ( keywordSymbolPart binaryExpression )+&lt;br /&gt;
 &lt;br /&gt;
 binaryExpression ::= unaryExpression&lt;br /&gt;
                      | unaryExpression ( binopSymbol unaryExpression )+&lt;br /&gt;
 &lt;br /&gt;
 unaryExpression ::= primary&lt;br /&gt;
                     | primary ( unarySymbol )+&lt;br /&gt;
 &lt;br /&gt;
 primary ::= identifier&lt;br /&gt;
             | literalConstant&lt;br /&gt;
             | expandedStringExpression&lt;br /&gt;
             | braceArray&lt;br /&gt;
             | &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
             | block&lt;br /&gt;
             | &amp;quot;self&amp;quot;&lt;br /&gt;
             | &amp;quot;super&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 identifier ::= ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot;)   ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 literalConstant ::= integerConstant&lt;br /&gt;
                     | radixIntegerConstant&lt;br /&gt;
                     | floatConstant&lt;br /&gt;
                     | arrayConstant&lt;br /&gt;
                     | byteArrayConstant&lt;br /&gt;
                     | stringConstant&lt;br /&gt;
                     | characterConstant&lt;br /&gt;
                     | &amp;quot;true&amp;quot;&lt;br /&gt;
                     | &amp;quot;false&amp;quot;&lt;br /&gt;
                     | &amp;quot;nil&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 integerConstant ::= ( &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 radixIntegerConstant ::= base &amp;quot;r&amp;quot; baseDigits+&lt;br /&gt;
 &lt;br /&gt;
 base ::= integerConstant (valid are: 2-31)&lt;br /&gt;
 &lt;br /&gt;
 baseDigits := &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; (valid are &amp;quot;0&amp;quot;..&amp;quot;0&amp;quot;+base-1 and &amp;quot;a&amp;quot;..&amp;quot;a&amp;quot;+base-10-1 and &amp;quot;A&amp;quot;..&amp;quot;A&amp;quot;+base-10-1)&lt;br /&gt;
 &lt;br /&gt;
 floatConstant ::= [ &amp;quot;-&amp;quot; ] [ digits+ ] &amp;quot;.&amp;quot; [ digits+ ] [ (&amp;quot;e&amp;quot; | &amp;quot;E&amp;quot; | &amp;quot;d&amp;quot; | &amp;quot;D&amp;quot;) [ &amp;quot;-&amp;quot;] digits+ ]&lt;br /&gt;
 &lt;br /&gt;
 arrayConstant ::= &amp;quot;#(&amp;quot; literalConstant* &amp;quot;)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 byteArrayConstant ::= &amp;quot;#[&amp;quot; integerConstant(0..255)* &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 stringConstant ::= &#039; characters...  &#039; &lt;br /&gt;
                    | cString&lt;br /&gt;
 &lt;br /&gt;
 characterConstant ::= &amp;quot;$&amp;quot; character&lt;br /&gt;
  &lt;br /&gt;
 block ::= &amp;quot;[&amp;quot; [ blockArgList ] body &amp;quot;]”&lt;br /&gt;
 &lt;br /&gt;
 blockArgList ::= (identifier&amp;quot;:&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 comment ::= &amp;quot; &amp;quot; &amp;quot; any-character* &amp;quot; &amp;quot; &amp;quot; | eolComment&lt;br /&gt;
 &lt;br /&gt;
 unarySymbol ::= identifier&lt;br /&gt;
 &lt;br /&gt;
 binopSymbol ::= ( &amp;quot;+&amp;quot; | &amp;quot;-&amp;quot; | &amp;quot;*&amp;quot; | &amp;quot;/&amp;quot; | &amp;quot;\&amp;quot; | &amp;quot;,&amp;quot; | &amp;quot;@&amp;quot; | &amp;quot;%&amp;quot; | &amp;quot;&amp;amp;&amp;quot; | &amp;quot;=&amp;quot; | &amp;quot;&amp;lt;&amp;quot; | &amp;quot;&amp;gt;&amp;quot; | &amp;quot;~&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 keywordSymbolPart ::= identifier&amp;quot;:&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 keywordSymbol ::= keywordSymbolPart+&lt;br /&gt;
 &lt;br /&gt;
 symbolConstant ::= &amp;quot;#&amp;quot;unarySymbol&lt;br /&gt;
                    | &amp;quot;#&amp;quot;binarySymbol&lt;br /&gt;
                    | &amp;quot;#&amp;quot;keywordSymbol&lt;br /&gt;
                    | &amp;quot;#&#039;&amp;quot;any-character*&amp;quot;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==== Smalltalk/X Language Extensions (BNF) ====&lt;br /&gt;
&lt;br /&gt;
Smalltalk/X provides a few very useful syntax extensions w.r.t. standard Ansi Smalltalk:&lt;br /&gt;
&lt;br /&gt;
 eolComment ::= &amp;quot; &amp;quot;/ &amp;quot; any-character-up-to-end-of-line&lt;br /&gt;
 &lt;br /&gt;
 tokenComment ::= &amp;quot; &amp;quot;&amp;lt;&amp;lt;&amp;quot;TOKEN&lt;br /&gt;
                     ...  &lt;br /&gt;
                     any number of lines not beginning with TOKEN&lt;br /&gt;
                     (where TOKEN is any valid identifier string)&lt;br /&gt;
                     ...&lt;br /&gt;
                     TOKEN&lt;br /&gt;
 &lt;br /&gt;
 braceArray ::= &amp;quot;{&amp;quot; [ expression | expression ( &amp;quot;.&amp;quot; expression )+ ] &amp;quot;}&amp;quot; (an array with computed elements)&lt;br /&gt;
 &lt;br /&gt;
 literalObject ::= &amp;quot;#{&amp;quot; ( fieldName: constant )+ &amp;quot;}&amp;quot;  (a constant object with getters for fields)&lt;br /&gt;
 &lt;br /&gt;
 immediateObject ::= &amp;quot;{&amp;quot; ( fieldName: expression )+ &amp;quot;}&amp;quot; (an immediate object with getters and setters)&lt;br /&gt;
 &lt;br /&gt;
 cString ::= c&#039;string with C-escapes&#039;&lt;br /&gt;
 &lt;br /&gt;
 eString ::= e&#039;string with C-escapes and {embedded expressions}&#039;&lt;br /&gt;
 &lt;br /&gt;
 iString ::= i&#039;string with C-escapes and {embedded expressions} which is also internationalized&#039;&lt;br /&gt;
 &lt;br /&gt;
 typedArrayLiteral ::= #u8(...)     &amp;quot;/ unsigned byte array constant&lt;br /&gt;
                       | #s8(...)   &amp;quot;/ signed byte array constant&lt;br /&gt;
                       | #u16(...)  &amp;quot;/ unsigned int16 array constant&lt;br /&gt;
                       | #s16(...)  &amp;quot;/ signed int16 array constant&lt;br /&gt;
                       | #u32(...)  &amp;quot;/ unsigned int32 array constant&lt;br /&gt;
                       | #s32(...)  &amp;quot;/ signed int32 array constant&lt;br /&gt;
                       | #u64(...)  &amp;quot;/ unsigned int64 array constant&lt;br /&gt;
                       | #s64(...)  &amp;quot;/ signed int64 array constant&lt;br /&gt;
                       | #f32(...)  &amp;quot;/ single precision IEEE float array constant&lt;br /&gt;
                       | #f64(...)  &amp;quot;/ double precision IEEE float array constant&lt;br /&gt;
  &lt;br /&gt;
 cStyleInt ::= 0xXXX&lt;br /&gt;
               | 0oOOO&lt;br /&gt;
               | 0bBBB&lt;br /&gt;
 &lt;br /&gt;
 indexedAccess ::= array-expr &amp;quot;[&amp;quot; index-expr &amp;quot;]&amp;quot;&lt;br /&gt;
                   | array-expr &amp;quot;[&amp;quot; index1-expr &amp;quot;][&amp;quot; index2-expr &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 indexedStore ::= array-expr &amp;quot;[&amp;quot; index-expr &amp;quot;]&amp;quot; := &amp;lt;expr&amp;gt;&lt;br /&gt;
                  | array-expr &amp;quot;[&amp;quot; index1-expr &amp;quot;][&amp;quot; index2-expr &amp;quot;]&amp;quot; := &amp;lt;expr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== JavaScript Language Syntax (BNF) ===&lt;br /&gt;
&lt;br /&gt;
-- incomplete w.r.t. expression syntax -- to be added&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Notice: an elementary JavaScript action&#039;s &amp;quot;execute&amp;quot; function&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; must be a unary function (no argument).&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; However, it is possible to define additional (private) helper functions.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; These will only be visible within that single elementary action&#039;s code.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; Also notice the syntax extensions for character constants and the &amp;quot;return from&amp;quot; statement.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:#007F00&amp;quot;&amp;gt;;; &amp;lt;/span&amp;gt;&lt;br /&gt;
 method ::= functionSpec functionBody&lt;br /&gt;
 &lt;br /&gt;
 functionSpec ::= [&amp;quot;async&amp;quot;] &amp;quot;function&amp;quot; identifier &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 functionBody ::= &amp;quot;{&amp;quot; (statement)+ &amp;quot;}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 statement ::= varDeclaration&lt;br /&gt;
                      | ifStatement&lt;br /&gt;
                      | whileStatement&lt;br /&gt;
                      | doStatement&lt;br /&gt;
                      | forStatement&lt;br /&gt;
                      | tryCatchStatement&lt;br /&gt;
                      | switchStatement&lt;br /&gt;
                      | returnStatement&lt;br /&gt;
                      | &amp;quot;{&amp;quot; (statement)+ &amp;quot;}&amp;quot;&lt;br /&gt;
                      | expression&lt;br /&gt;
 &lt;br /&gt;
 varDeclaration ::= &amp;quot;var&amp;quot; identifier ( &amp;quot;,&amp;quot;  identifier)* &amp;quot;;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 ifStatement ::= &amp;quot;if&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; statement&lt;br /&gt;
                         [ &amp;quot;else&amp;quot; statement ]&lt;br /&gt;
 &lt;br /&gt;
 whileStatement ::= &amp;quot;while&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; statement&lt;br /&gt;
  &lt;br /&gt;
 doStatement ::= &amp;quot;do&amp;quot; statement &amp;quot;while&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;  &amp;quot;;&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 forStatement ::= &amp;quot;for&amp;quot; &amp;quot;(&amp;quot; [expression] &amp;quot;;&amp;quot; [expression] &amp;quot;;&amp;quot; [expression] &amp;quot;)&amp;quot; statement&lt;br /&gt;
 &lt;br /&gt;
 tryCatchStatement ::= &amp;quot;try&amp;quot; statement (catchClause | finallyClause | catchFinallyClause)&lt;br /&gt;
 &lt;br /&gt;
 catchClause ::= &amp;quot;catch&amp;quot;  &amp;quot;(&amp;quot; identifier [identifier] &amp;quot;)&amp;quot; statement&lt;br /&gt;
 &lt;br /&gt;
 finallyClause ::= &amp;quot;finally&amp;quot;  statement&lt;br /&gt;
 &lt;br /&gt;
 catchFinallyClause ::= catchClause finallyClause&lt;br /&gt;
 &lt;br /&gt;
 switchStatement ::= &amp;quot;switch&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot; &amp;quot;{&amp;quot; (&amp;quot;case constantExpression &amp;quot;:&amp;quot; statement)+ [ &amp;quot;default:&amp;quot; statement+ &amp;quot;}&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 returnStatement ::= &amp;quot;return&amp;quot; expression [ &amp;quot;from&amp;quot; identifier ]&lt;br /&gt;
 &lt;br /&gt;
 expression ::= term ( (&amp;quot;+&amp;quot; | &amp;quot;-&amp;quot;) term)*&lt;br /&gt;
                | &amp;quot;await&amp;quot; expression&lt;br /&gt;
 &lt;br /&gt;
 term ::= factor ( (&amp;quot;*&amp;quot; | &amp;quot;/&amp;quot; | &amp;quot;%&amp;quot; ) factor)*&lt;br /&gt;
 &lt;br /&gt;
 factor ::= powExpr ( &amp;quot;**&amp;quot;  powExpr)*&lt;br /&gt;
 &lt;br /&gt;
 powExpr ::= &amp;quot;typeof&amp;quot; &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
                | &amp;quot;!&amp;quot; factor&lt;br /&gt;
                | &amp;quot;-&amp;quot; factor&lt;br /&gt;
                | &amp;quot;++&amp;quot; factor&lt;br /&gt;
                | &amp;quot;--&amp;quot; factor&lt;br /&gt;
                | primary &amp;quot;--&amp;quot;&lt;br /&gt;
                | primary &amp;quot;++&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 primary ::= identifier&lt;br /&gt;
                   | literalConstant&lt;br /&gt;
                   | arrayExpression&lt;br /&gt;
                   | &amp;quot;(&amp;quot; expression &amp;quot;)&amp;quot;&lt;br /&gt;
                   | block&lt;br /&gt;
                   | &amp;quot;this&amp;quot;&lt;br /&gt;
                   | &amp;quot;super&amp;quot;&lt;br /&gt;
                   | &amp;quot;new&amp;quot; classIdentifier [ &amp;quot;(&amp;quot; constant &amp;quot;)&amp;quot; ]&lt;br /&gt;
                   | functionDefinition&lt;br /&gt;
                   | lambdaFunction&lt;br /&gt;
 &lt;br /&gt;
 functionDefinition ::= &amp;quot;function&amp;quot; [functionName] &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; functionBody&lt;br /&gt;
 &lt;br /&gt;
 lambdaFunction ::= &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; &amp;quot;=&amp;gt;&amp;quot; functionBody&lt;br /&gt;
                   | arg &amp;quot;=&amp;gt;&amp;quot; functionBody&lt;br /&gt;
                   | &amp;quot;(&amp;quot;  [argList] &amp;quot;)&amp;quot; &amp;quot;=&amp;gt;&amp;quot; expression&lt;br /&gt;
                   | arg &amp;quot;=&amp;gt;&amp;quot; expression&lt;br /&gt;
  &lt;br /&gt;
 identifier ::= ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot;)   ( &amp;quot;_&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;z&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;Z&amp;quot; | &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )*&lt;br /&gt;
 &lt;br /&gt;
 literalConstant ::= integerConstant&lt;br /&gt;
                              | radixIntegerConstant&lt;br /&gt;
                              | floatConstant&lt;br /&gt;
                              | arrayConstant&lt;br /&gt;
                              | byteArrayConstant&lt;br /&gt;
                              | stringConstant&lt;br /&gt;
                              | characterConstant&lt;br /&gt;
                              | &amp;quot;true&amp;quot;&lt;br /&gt;
                              | &amp;quot;false&amp;quot;&lt;br /&gt;
                              | &amp;quot;null&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 integerConstant ::= ( &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; )+&lt;br /&gt;
 &lt;br /&gt;
 radixIntegerConstant ::= hexIntegerConstant | octalIntegerConstant | binaryIntegerConstant&lt;br /&gt;
 &lt;br /&gt;
 hexIntegerConstant ::= &amp;quot;0x&amp;quot;hexDigit+&lt;br /&gt;
 &lt;br /&gt;
 hexDigit := &amp;quot;0&amp;quot;-&amp;quot;9&amp;quot; | &amp;quot;A&amp;quot;-&amp;quot;F&amp;quot; | &amp;quot;a&amp;quot;-&amp;quot;f&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 octalIntegerConstant ::= &amp;quot;0&amp;quot;octalDigit+&lt;br /&gt;
 &lt;br /&gt;
 octalDigit := &amp;quot;0&amp;quot;-&amp;quot;7&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 binaryIntegerConstant ::= &amp;quot;0b&amp;quot;binaryDigit+&lt;br /&gt;
 &lt;br /&gt;
 binaryDigit := &amp;quot;0&amp;quot; | &amp;quot;1&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 floatConstant ::= [ &amp;quot;-&amp;quot; ] [ digits+ ] &amp;quot;.&amp;quot; [ digits+ ] [ (&amp;quot;e&amp;quot; | &amp;quot;E&amp;quot; | &amp;quot;d&amp;quot; | &amp;quot;D&amp;quot;) [ &amp;quot;-&amp;quot;] digits+ ]&lt;br /&gt;
 &lt;br /&gt;
 arrayConstant ::= &amp;quot;[&amp;quot; [literalConstant (&amp;quot;,&amp;quot; literalConstant)*] &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 arrayExpression ::= &amp;quot;[&amp;quot; [expression (&amp;quot;,&amp;quot; expression)*] &amp;quot;]&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 stringConstant ::= apos character* apos &lt;br /&gt;
                  | quote character* quote&lt;br /&gt;
 &lt;br /&gt;
 characterConstant ::= &amp;quot;$&amp;quot; character&lt;br /&gt;
 &lt;br /&gt;
 apos ::= &amp;quot;&#039;&amp;quot;&#039; (single quote)&lt;br /&gt;
 &lt;br /&gt;
 quote ::= &amp;quot; &amp;quot; &amp;quot; (double quote)&lt;br /&gt;
 &lt;br /&gt;
 comment ::= &amp;quot;/*&amp;quot; any-character* &amp;quot; */ &amp;quot; | eolComment&lt;br /&gt;
 &lt;br /&gt;
 eolComment ::= &amp;quot; // &amp;quot; any-character-up-to-end-of-line&lt;br /&gt;
&lt;br /&gt;
Notice the nonstandard extension for single character constants&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Back to [[ Online_Documentation#Code_API_Overview Online Documentation ]]&lt;br /&gt;
&lt;br /&gt;
[[Category: Advanced/en]]&amp;lt;br&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29981</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29981"/>
		<updated>2025-02-18T15:56:43Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Future Release 24.2 (February 2025) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Future Release 24.2 (February 2025) ==&lt;br /&gt;
*Feature: WindowsAutomation: &amp;quot;Mouse Wheel Simulation&amp;quot; support&lt;br /&gt;
*Feature: support for &amp;quot;Any&amp;quot; and template typed parameters in testcase (of testplan)&lt;br /&gt;
*Feature: negated [[Testplan_Editor/en#Condition_Variables|condition variable]] check&lt;br /&gt;
*Feature: edit lock when loading a suite from AIDYMO&lt;br /&gt;
*Feature: menu entries to save attachments to disk &lt;br /&gt;
*Feature: support for an external XML editor in Settings-&amp;gt;External Tools and Attachment&lt;br /&gt;
*Feature: [[Testsuite_Editor-Metadata_Editor/en#Include_Flat|flat vs. hierarchical imported menu actions]]&lt;br /&gt;
*Feature: The Mobile Testing Plugin has been migrated to use Appium 2, while Appium 1 is still supported. There is a new version of the [[Mobile_Testing_Plugin#Windows|Mobile Testing Supplement]] with Appium 2.&lt;br /&gt;
*Fix/Feature: severity level limit is passed on in sub-test plans with the option of tightening the severity level per test plan level&lt;br /&gt;
*Fix: Project Difference Viewer showed wrong tab for steps inside the test/demo diagram&lt;br /&gt;
*Fix: exchange connection function of diagram editor left an invisible connection at the pin. Lead to wrong output value forwarding during the current session, but cured itself when saving and reloading.&lt;br /&gt;
*Fix: inconsistent behavior of the Smalltalk &amp;quot;angle&amp;quot; message fixed; now returns degrees from both Complex and Point instances. To get radians, use the &amp;quot;theta&amp;quot; message. This change only affects any elementary action which calls that method.&lt;br /&gt;
*Improvement: function and operation of variable pins ([[Scheme_Editor/en#Variable_Number_of_Pins|Scheme_Editor/Variable_Number_of_Pins]])&lt;br /&gt;
*Improvement: change modification date of the project when shrinkwrapping an imported library&lt;br /&gt;
*Improvement: less memory allocation during ELF generation&lt;br /&gt;
*Improvement: more info in tooltips in browser&#039;s &amp;quot;Errors&amp;quot;, &amp;quot;Style&amp;quot; and &amp;quot;Special&amp;quot; tabs&lt;br /&gt;
*Improvement: stability of websocket connections to AIDYMO/web&lt;br /&gt;
*Improvement: Datatypes: Differently named user types on the same primary type or Any can now be defined and stored in a project, but possibly loosing information when loading in older expecco versions. Reimporting a changed datatype definition doesn&#039;t rely the name primarily.&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt; ([[Qt_Inject_Windows/en#Logging|Qt-Logging]])&lt;br /&gt;
*Feature: Qt-Testing: Qt-Connections now use the ConnectionManager like the other Gui test technologies&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: [[Testsuite_Editor-ExecutionSettings_Editor/en|Settings for execution]] (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved refactoring for compound blocks: &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: Enhanced expecco reflection library&lt;br /&gt;
*Feature: Logprocessors can be executed for embedded testplans&lt;br /&gt;
*Feature: Logging of background actions can be individually enabled and disabled for testplans and nested testplans&lt;br /&gt;
*Feature: Support for script actions written in the [[Installing_additional_Frameworks/en#Julia_Installation|Julia]] programming language&lt;br /&gt;
*Feature: Powershell actions: support functions for writing to pins, logging, opening dialogs, etc. &lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;br /&gt;
*Fix: Acitivity logs of asynchronous events in background actions are now displayed correctly in the background activity log.&lt;br /&gt;
*Fix: Qt: Drag and drop improved by revising the &amp;quot;Move mouse event&amp;quot; (Windows)&lt;br /&gt;
*Fix: Disabling logs of sub-activities (if successful, if not successful, etc.)&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29973</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29973"/>
		<updated>2025-02-17T09:53:54Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Future Release 24.2 (February 2025) */ Appium 2 support&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Future Release 24.2 (February 2025) ==&lt;br /&gt;
*Feature: WindowsAutomation: &amp;quot;Mouse Wheel Simulation&amp;quot; support&lt;br /&gt;
*Feature: support for &amp;quot;Any&amp;quot; and template typed parameters in testcase (of testplan)&lt;br /&gt;
*Feature: negated [[Testplan_Editor/en#Condition_Variables|condition variable]] check&lt;br /&gt;
*Feature: edit lock when loading a suite from AIDYMO&lt;br /&gt;
*Feature: menu entries to save attachments to disk &lt;br /&gt;
*Feature: support for an external XML editor in Settings-&amp;gt;External Tools and Attachment&lt;br /&gt;
*Feature: [[Testsuite_Editor-Metadata_Editor/en#Include_Flat|flat vs. hierarchical imported menu actions]]&lt;br /&gt;
*Feature: The Mobile Testing Plugin has been migrated to use Appium 2, while Appium 1 is still supported. There is a new version of the [[Mobile_Testing_Plugin#Windows|Mobile Testing Supplement]] with Appium 2.&lt;br /&gt;
*Fix/Feature: severity level limit is passed on in sub-test plans with the option of tightening the severity level per test plan level&lt;br /&gt;
*Fix: Project Difference Viewer showed wrong tab for steps inside the test/demo diagram&lt;br /&gt;
*Fix: exchange connection function of diagram editor left an invisible connection at the pin. Lead to wrong output value forwarding during the current session, but cured itself when saving and reloading.&lt;br /&gt;
*Fix: inconsistent behavior of the Smalltalk &amp;quot;angle&amp;quot; message fixed; now returns degrees from both Complex and Point instances. To get radians, use the &amp;quot;theta&amp;quot; message. This change only affects any elementary action which calls that method.&lt;br /&gt;
*Improvement: function and operation of variable pins ([[Scheme_Editor/en#Variable_Number_of_Pins|Scheme_Editor/Variable_Number_of_Pins]])&lt;br /&gt;
*Improvement: change modification date of the project when shrinkwrapping an imported library&lt;br /&gt;
*Improvement: less memory allocation during ELF generation&lt;br /&gt;
*Improvement: more info in tooltips in browser&#039;s &amp;quot;Errors&amp;quot;, &amp;quot;Style&amp;quot; and &amp;quot;Special&amp;quot; tabs&lt;br /&gt;
*Improvement: stability of websocket connections to AIDYMO/web&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt; ([[Qt_Inject_Windows/en#Logging|Qt-Logging]])&lt;br /&gt;
*Feature: Qt-Testing: Qt-Connections now use the ConnectionManager like the other Gui test technologies&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: [[Testsuite_Editor-ExecutionSettings_Editor/en|Settings for execution]] (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved refactoring for compound blocks: &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: Enhanced expecco reflection library&lt;br /&gt;
*Feature: Logprocessors can be executed for embedded testplans&lt;br /&gt;
*Feature: Logging of background actions can be individually enabled and disabled for testplans and nested testplans&lt;br /&gt;
*Feature: Support for script actions written in the [[Installing_additional_Frameworks/en#Julia_Installation|Julia]] programming language&lt;br /&gt;
*Feature: Powershell actions: support functions for writing to pins, logging, opening dialogs, etc. &lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;br /&gt;
*Fix: Acitivity logs of asynchronous events in background actions are now displayed correctly in the background activity log.&lt;br /&gt;
*Fix: Qt: Drag and drop improved by revising the &amp;quot;Move mouse event&amp;quot; (Windows)&lt;br /&gt;
*Fix: Disabling logs of sub-activities (if successful, if not successful, etc.)&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29972</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29972"/>
		<updated>2025-02-17T09:42:58Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */ new supplement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
The &#039;&#039;Mobile Testing Plugin&#039;&#039; adds mechanisms to test and automate Android and iOS devices. This includes both real and emulated devices - it does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 2.0.1.1]&lt;br /&gt;
:Migration to Appium 2. The Appium server starts as default without the path &#039;&#039;wd/hub/&#039;&#039;.&lt;br /&gt;
:Appium 2.11.0&lt;br /&gt;
:Node 20.9.0&lt;br /&gt;
:adb 1.0.41 from platform-tools 35.0.1&lt;br /&gt;
*expecco 24.1: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; chromedriverStartTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
The error &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; occurs whenever an element is used that is no longer there. If that happens during your test and the element should have been there, try using the locator (xPath) instead to fetch the element again.&lt;br /&gt;
&lt;br /&gt;
In some cases this error can also occur even if you already use a locator at the action block. This is because the locator is always resolved first and the corresponding element is fetched and the action is then executed with this element. If the app refreshes the element exactly between the resolving and fetching part and the execution, creating a new element, this error occurs. If it happens at a specific point in your test, your best option is to catch the error and retry.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29971</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29971"/>
		<updated>2025-02-17T09:39:52Z</updated>

		<summary type="html">&lt;p&gt;Matilk: new supplement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 2.0.1.1]&lt;br /&gt;
:Umstieg auf Appium 2. Der Appium-Server startet standardmäßig ohne den Path &#039;&#039;wd/hub/&#039;&#039;.&lt;br /&gt;
:Appium 2.11.0&lt;br /&gt;
:Node 20.9.0&lt;br /&gt;
:adb 1.0.41 aus platform-tools 35.0.1&lt;br /&gt;
*expecco 24.1: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; chromedriverStartTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein Element verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator (XPath), um das Element neu zu holen.&lt;br /&gt;
&lt;br /&gt;
In manchen Fällen kann dieser Fehler auch dann auftreten, wenn Sie am Baustein bereits Locator angegeben haben. Das liegt daran, dass immer zuerst der Locator aufgelöst und das entsprechende Element geholt wird und dann die Aktionen mit dem Element ausgeführt wird. Wenn die App das Element genau zwischen dem Zeitpunkt des Auflösens und Holens und der Ausführung der Aktion aktualisiert und dabei ein neues Element erzeugt, kommt es zu diesem Fehler. Passiert das an einer bestimmten Stelle in Ihrem Test, bleibt nichts anderes als den Fehler abzufangen und es erneut zu versuchen.&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29869</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29869"/>
		<updated>2024-12-19T16:31:01Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Future Release 24.2 (4Q 2024) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Future Release 24.2 (January 2025) ==&lt;br /&gt;
*Feature: WindowsAutomation: &amp;quot;Mouse Wheel Simulation&amp;quot; support&lt;br /&gt;
*Feature: Any and template typed parameters in testcase (of testplan)&lt;br /&gt;
*Feature: Negated [[Testplan_Editor/en#Condition_Variables|condition variable]] check&lt;br /&gt;
*Fix: Project Difference Viewer showed wrong tab for steps inside the test/demo diagram&lt;br /&gt;
*Fix: Exchange connection function of diagram editor left an invisible connection at the pin. Lead to wrong output value forwarding during the current session, but cured itself when saving and reloading.&lt;br /&gt;
*Improving the function and operation of variable pins ([[Scheme_Editor/en#Variable_Number_of_Pins|Scheme_Editor/Variable_Number_of_Pins]])&lt;br /&gt;
*Fix/Feature: Severity level limit is passed on in sub-test plans with the option of tightening the severity level per test plan level&lt;br /&gt;
*Improvement: Change modification date of the project when shrink wrapping an imported library&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt; ([[Qt_Inject_Windows/en#Logging|Qt-Logging]])&lt;br /&gt;
*Feature: Qt-Testing: Qt-Connections now use the ConnectionManager like the other Gui test technologies&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: [[Testsuite_Editor-ExecutionSettings_Editor/en|Settings for execution]] (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved refactoring for compound blocks: &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: Enhanced expecco reflection library&lt;br /&gt;
*Feature: Logprocessors can be executed for embedded testplans&lt;br /&gt;
*Feature: Logging of background actions can be individually enabled and disabled for testplans and nested testplans&lt;br /&gt;
*Feature: Support for script actions written in the [[Installing_additional_Frameworks/en#Julia_Installation|Julia]] programming language&lt;br /&gt;
*Feature: Powershell actions: support functions for writing to pins, logging, opening dialogs, etc. &lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;br /&gt;
*Fix: Acitivity logs of asynchronous events in background actions are now displayed correctly in the background activity log.&lt;br /&gt;
*Fix: Qt: Drag and drop improved by revising the &amp;quot;Move mouse event&amp;quot; (Windows)&lt;br /&gt;
*Fix: Disabling logs of sub-activities (if successful, if not successful, etc.)&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin/en&amp;diff=29685</id>
		<title>Selenium WebDriver Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin/en&amp;diff=29685"/>
		<updated>2024-08-22T15:16:05Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* FAQ */ Firefox after Update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Selenium_WebDriver_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Use the &#039;&#039;Selenium WebDriver Plugin&#039;&#039; to test or automate interactions of applications running in a web-browser (*). The plugin can be (and usually is) used with the [[Expecco_GUI_Tests_Extension_Reference|GUI Browser]], which helps in the creation of tests. Moreover, the GUI Browser can record UI sessions, which can later be customised or refactored as required.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Selenium WebDriver Plugin&#039;&#039; replaces the previous [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]], which was based on the now outdated Selenium RC framework.&amp;lt;br&amp;gt;&lt;br /&gt;
The new web driver uses the [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver] for automation, and replaces the previous interface.&lt;br /&gt;
(see https://www.guru99.com/introduction-webdriver-comparison-selenium-rc.html  for background information and a description of the differences.)&lt;br /&gt;
Read [[#Transferring_Old_Selenium_Tests|this section]] for information how to transfer testsuites using the old plugin.&lt;br /&gt;
&lt;br /&gt;
(*) actually, there exists WebDriver interfaces to control Windows or OS X desktop applications. Thus, this plugin can be used in a number of additional scenarios.&lt;br /&gt;
&lt;br /&gt;
=Settings=&lt;br /&gt;
This plugin uses the Java bridge and therefore needs a Java installation. You can specify it in the settings under &#039;&#039;Plugins&#039;&#039; -&amp;gt; &#039;&#039;Java Bridge&#039;&#039;. The important field is &#039;&#039;Java Installation Path&#039;&#039;, where you can set a JDK or JRE. If nothing is set, expecco tries to find java in the PATH.&lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
There are settings for the Selenium WebDriver Plugin itself as well. You find them under &#039;&#039;Plugins&#039;&#039; -&amp;gt; &#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;. There you can for example set the address of a remote running Selenium server or another Jar file for Selenium. The settings for the different browser types are divided into the two subpages &#039;&#039;Most Popular Browsers&#039;&#039; and &#039;&#039;Other Browsers&#039;&#039;. There you can set the path to the browser executable or to the webdriver to use. You can leave all these fields empty and expecco will search for them automatically&lt;br /&gt;
&lt;br /&gt;
=Browser Support=&lt;br /&gt;
This plugin supports (among others) the Chrome/Chromium, Edge, Firefox, Internet Explorer  and Opera browsers. &lt;br /&gt;
&amp;lt;br&amp;gt;Safari under OSX must be at least version 10, and OSX must be at least El Capitan.&lt;br /&gt;
The plugin uses the WebDriver interface for communication; therefore, browsers running both on the local or on a remote machine can be tested and/or controlled.&lt;br /&gt;
In addition, many other browsers, UIs and devices support the WebDriver protocol, and can thus be automated/tested with expecco.&lt;br /&gt;
&lt;br /&gt;
==Update WebDriver==&lt;br /&gt;
Each browser has a driver (&amp;quot;&#039;&#039;WebDriver&#039;&#039;&amp;quot;) for opening and controlling a browser window. &lt;br /&gt;
Usually, the driver is a separate program which translates WebDriver requests into browser-specific interface calls. However, there are also browsers and programs which have the WebDriver protocol already built in (eg. Safari).&lt;br /&gt;
&lt;br /&gt;
The expecco installation package includes current driver versions for common browsers. However, as the browsers are updated continuously, sometimes even automatically, you sooner or later may have to download a new driver version. In that case put it in the folder inside your expecco installation directory where the other versions are stored as well, at:&lt;br /&gt;
 &amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib/XXX&amp;lt;/code&amp;gt;&lt;br /&gt;
(of course, with &amp;quot;\”s instead of &amp;quot;/&amp;quot;s on Microsoft Windows operating systems), where &amp;quot;XXX&amp;quot; denotes the operating system (Windows, Linux, OSX etc.).&lt;br /&gt;
&amp;lt;!--To use a different driver, check the &amp;quot;Advanced&amp;quot; toggle in the connection dialog and add the driver&#039;s path to the settings (see below).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the connection dialog, expecco may show a warning, that the driver version is incompatible with the browser version. In some cases this may only be due to the fact, that this version was not known at the time of delivery. Some combinations may work despite the warning, but we cannot guarantee that for each individual case.&lt;br /&gt;
&lt;br /&gt;
Therefore you can always check the &amp;quot;&#039;&#039;Do not show this warning again&#039;&#039;&amp;quot; toggle, if such a warning is shown, to have expecco remember that combination as &amp;quot;compatible&amp;quot; in your settings, and not warn again. You should only do that, if you are sure that your tests will still be executed correctly. As we sometimes get compatibility problems ourselves and cannot always immediately find the reason, we advice you, to update the driver.&lt;br /&gt;
&lt;br /&gt;
For Chrome and Microsoft Edge, where each new browser version comes with a new driver version, you find a button in the connection dialog, to download matching driver versions by expecco.&lt;br /&gt;
&lt;br /&gt;
You find new driver versions at the following addresses:&lt;br /&gt;
{|&lt;br /&gt;
|Chrome/Chromium&lt;br /&gt;
|[https://sites.google.com/chromium.org/driver/ ChromeDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Edge&lt;br /&gt;
|[https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ Microsoft WebDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|[https://github.com/mozilla/geckodriver/releases GeckoDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|[https://selenium-release.storage.googleapis.com/index.html IEDriverServer]&lt;br /&gt;
|-&lt;br /&gt;
|Opera&lt;br /&gt;
|[https://github.com/operasoftware/operachromiumdriver/releases Opera driver]&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|[https://webkit.org/blog/6900/webdriver-support-in-safari-10 Safari Support]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Download a suitable version and place it at an appropriate location in the above mentioned directory. expecco will then find and use it. &amp;lt;!-- You can extend the file name to have multiple versions in parallel. --&amp;gt; Alternatively, you can set the path to a driver either in the [[#Advanced_Settings | connection editor]] or in the [[#Plugin_Settings | plugin settings]].&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Please verify that the driver&#039;s version is compatible with the browser version. If in doubt, consult the version history (e.g. for Chrome: https://chromedriver.storage.googleapis.com/2.25/notes.txt).&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice: For Internet Explorer, &amp;quot;&amp;lt;code&amp;gt;Protected Mode&amp;lt;/code&amp;gt;&amp;quot; settings must be set to the same value for all zones, to be able to start a connection.  (in the Internet Explorer, open &amp;quot;Settings&amp;quot; - &amp;quot;Internet Options&amp;quot; - &amp;quot;Security&amp;quot;, and set the value of &amp;quot;protected mode&amp;quot; to the same in all 4 zones; otherwise, you&#039;ll get error- and warning dialogs when connecting). See also the [https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration required configuration] to use InternetExplorerDriver.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Also notice: the plugin uses JavaScript for some advanced functions, and those functions require that JavaScript is enabled in the browser. This is especially needed to use the GUI browser and the recorder. Test execution may be possible without JavaScript, as long as no actions are used which rely on JavaScript.&lt;br /&gt;
If you get an error like &amp;lt;code&amp;gt;&amp;quot;org.openqa.selenium.JavascriptException: Error executing JavaScript&amp;quot;&amp;lt;/code&amp;gt;,&lt;br /&gt;
make sure that JavaScript is enabled in the browser and that the versions of the browser and the associated driver are compatible.&lt;br /&gt;
&lt;br /&gt;
=Additional Uses=&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/appium/appium-for-mac AppiumForMac]&lt;br /&gt;
|WebDriver to control OS X apps (i.e. also non-Browsers)&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/microsoft/WinAppDriver WinAppDriver]&lt;br /&gt;
|WebDriver to control Windows Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Notice, that these interfaces usually provide a subset of the functionality provided by special plugins, such as Java-GUI or WindowsAutomation plugins. Usually, they are ok to manipulate the top level window or to confirm simple dialogs, but less usable for more complex UI tests.&lt;br /&gt;
&lt;br /&gt;
= Quick Start =&lt;br /&gt;
== Open Browser / Connecting ==&lt;br /&gt;
* Start expecco&lt;br /&gt;
* Click on &amp;quot;&#039;&#039;New Testsuite&#039;&#039;&amp;quot;&lt;br /&gt;
* Click on the GUI-Browser symbol ([[Datei:GUIBrowser.png|24px]])&lt;br /&gt;
* A new Tab appears, containing the GUI-Browser&lt;br /&gt;
* Click on &amp;quot;&#039;&#039;Connect&#039;&#039;&amp;quot; and choose &amp;quot;&#039;&#039;Selenium Testing&#039;&#039;&amp;quot;. The  [[#Connection Editor | Connection Dialog]] appears (see details below)&lt;br /&gt;
* Choose the type of browser (eg. &amp;quot;&amp;lt;code&amp;gt;firefox&amp;lt;/code&amp;gt;&amp;quot; and enter the URL of the tested web site (eg. &amp;quot;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.myHost.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;) and )&lt;br /&gt;
* Click on &amp;quot;Connect&amp;quot;&lt;br /&gt;
* A browser is started automatically, and the page is shown&lt;br /&gt;
* As soon as the connection is established,  the page&#039;s elements are shown in the GUIBrowser&#039;s left tree view&lt;br /&gt;
&lt;br /&gt;
== Start a Recording ==&lt;br /&gt;
* After a connection has been established, click on the record icon ([[Datei:Recording.png|16px]]) in the GUIBrowser.&lt;br /&gt;
&lt;br /&gt;
== Inspecting Elements ==&lt;br /&gt;
* Select an element in the browser&#039;s element-tree, or move the mouse over it in &amp;quot;follow-mouse mode&amp;quot;. If your browser does not support this &amp;quot;follow-mouse&amp;quot; mode, try opening a recorder, and move the mouse there.&lt;br /&gt;
The element&#039;s attributes are shown in the lower-center attribute/property list.&lt;br /&gt;
== Manually adding Actions and Checks ==&lt;br /&gt;
* In addition to recording, actions and checks can also be selected from the upper-centre action list. Select one there and either try it immediately or add it to the recording sequence via the add-action button at the top far right.&lt;br /&gt;
&lt;br /&gt;
=Connecting=&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Verbindungsdialog&amp;quot;&amp;gt;Connection Editor==&lt;br /&gt;
The connection editor defines, changes or starts a connection. Open the GUI browser, click on &amp;quot;&#039;&#039;Connect&#039;&#039;&amp;quot; and select &amp;quot;&#039;&#039;Selenium Testing (WebDriver)&#039;&#039;&amp;quot;. You can also create attachments or files containing connection parameters (&amp;quot;&#039;&#039;connection settings&#039;&#039;&amp;quot;) without actually connecting to/opening a new browser connection via the &amp;quot;&#039;&#039;Save Connection Settings&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
When opened, the connection editor presents a number of fields and load/save buttons in its toolbar menu:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverConnectDialog.png]]&lt;br /&gt;
&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Open an attachment containing connection settings from an open project. This settings will be added to the editor. Already entered inputs that are not conflicting will remain unchanged.&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Open a saved settings file (*.csf). Its settings will be added to the editor. Already entered inputs that are not conflicting will remain unchanged.&lt;br /&gt;
#&#039;&#039;Save settings as attachment&#039;&#039;: Save all entered settings as attachment in an open project.&lt;br /&gt;
#&#039;&#039;Save settings as JSON attachment&#039;&#039;: Save all entered settings in JSON format as attachment in an open project.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039;: Save all entered settings to a file (*.csf).&lt;br /&gt;
#&#039;&#039;Version info&#039;&#039;: Opens a window showing the used versions of the Selenium server, the selected browser and its driver.&lt;br /&gt;
#&#039;&#039;Online documentation&#039;&#039;: Open this online documentation page.&lt;br /&gt;
#&#039;&#039;Connection name&#039;&#039;: Enter the name of the connection used to show it in the GUI browser. (Optional)&lt;br /&gt;
#&#039;&#039;Browser type&#039;&#039;: Choose the type of browser to use. Ensure it is installed and the version of the used driver is compatible with the browser version.&lt;br /&gt;
#&#039;&#039;URL&#039;&#039;: Enter the URL to open at startup. To open an empty browser window, leave this field empty. To open a local file use the &amp;quot;&amp;lt;code&amp;gt;file://&amp;lt;/code&amp;gt;&amp;quot; scheme, e.g. &amp;quot;&amp;lt;code&amp;gt;file:///C:/Users/admin/Desktop/index.html&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
#&#039;&#039;Advanced view&#039;&#039;: Toggle the view to enter [[#Advanced Settings|advanced settings]].&lt;br /&gt;
#&#039;&#039;Information on the selected browser&#039;&#039;: Here, the selected browser type is shortly characterized.&lt;br /&gt;
#&#039;&#039;Information on the settings&#039;&#039;: It shows which Selenium, browser and driver version will be used regarding the current settings. If you have set [[#Advanced Settings|advanced settings]], they will also be displayed here.&lt;br /&gt;
&lt;br /&gt;
===Advanced Settings===&lt;br /&gt;
Besides the used browser and the start URL, more settings and possibly &amp;quot;&#039;&#039;capabilities&#039;&#039;&amp;quot; may be required. To see click on the &amp;quot;Advanced&amp;quot; toggle. Depending on the selected browser type you get different entry fields.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Remote Server&#039;&#039;: To open a browser on a remote host, start a Selenium server there and set this field to its address. You can also enter a local address if you do not want the Selenium server to start automatically or if it is already running. See the next section [[#Remote Connections|Remote Connections]] on how to start a Selenium server.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Headless&#039;&#039;: to open the browser in &amp;quot;headless&amp;quot; mode, i.e. without a window. Not all browsers/drivers support this mode.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Binary&#039;&#039;: Enter the path to the binary of the selected browser. Use this if the browser cannot be found automatically by Selenium, or if you have another browser version installed or to be tested against.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Driver&#039;&#039;: For each browser, a particular driver is needed for automation. New browser versions often also need a new driver version. If you don&#039;t want or cannot use the driver provided by expecco, set its path here.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Command Line Options&#039;&#039;: arguments passed to the browser-command. For example the chrome browser supports a &amp;quot;--disable-extensions&amp;quot; command line argument, firefox supports &amp;quot;--safe-mode&amp;quot; and &amp;quot;--profile&amp;quot;. These options are browser- and possibly browser-version specific. Most browsers allow for a &amp;quot;--help&amp;quot; argument, which you may try in a shell window to find out.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Firefox Profile&#039;&#039;: For Firefox, it is possible to set a &#039;&#039;Firefox Profile&#039;&#039;, containing specific settings. If no profile is set, each connection will use a new empty one.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Capabilities&#039;&#039;: Selenium connections can use several capabilities to define the connection&#039;s behavior. To add specific capabilities, set them in this field. Write &amp;quot;&#039;&#039;&amp;lt;capability name&amp;gt;: &amp;lt;value&amp;gt;&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;&amp;lt;capability name&amp;gt; = &amp;lt;value&amp;gt;&#039;&#039;&amp;quot;, one entry per line.&amp;lt;p&amp;gt;The set of capabilities needed or supported are browser- and driver specific. Please refer to the concrete driver&#039;s documentation as found via the driver links above. Common capabilities are: &amp;quot;app&amp;quot; or &amp;quot;application&amp;quot;, &amp;quot;url&amp;quot;, etc. For drivers which communicate with mobile devices, the capabilities also select which device to use and/or wether an emulator should be started.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;You can also set properties for the Firefox browser - for this, use the same syntax as for capabilities, but add a leading &#039;&#039;$&#039;&#039; to the property name.&amp;lt;/p&amp;gt;Properties used by expecco internally (such as browser type, url or remote host) are prefixed by a &amp;quot;#&amp;quot;-character.&lt;br /&gt;
&lt;br /&gt;
==Remote Connections==&lt;br /&gt;
To start a browser on a remote computer, copy the Selenium server and the required driver to that computer. You find the files in your expecco installation at &amp;quot;&amp;lt;code&amp;gt;packages\exept\expecco\plugin\seleniumWebDriver\lib&amp;lt;/code&amp;gt;&amp;quot;. Start the Selenium server (on the remote host) with:&lt;br /&gt;
 java -jar selenium-server-standalone-3.6.0.jar&lt;br /&gt;
By default, the server will listen on port 4444. To use another port, set it with the &amp;quot;&amp;lt;code&amp;gt;-port &amp;amp;lt;nr&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;quot; command line argument. To connect to that server, set the &amp;quot;&#039;&#039;remote server&#039;&#039;&amp;quot; parameter of the connection to &amp;quot;&#039;&#039;&amp;lt;Server-Address&amp;gt;:4444/wd/hub&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Check and possibly configure your firewall to allow transmission through the port.&lt;br /&gt;
&lt;br /&gt;
== Headless Browsing ==&lt;br /&gt;
&amp;quot;&#039;&#039;Headless Browsing&#039;&#039;&amp;quot; means: &amp;quot;&#039;&#039;without a window&#039;&#039;&amp;quot;,  and is useful to test web-pages for reachability, performance and structure. You can either use the HTMLUnit browser type, which simulates a browser, or run against one of the real browsers in headless mode. Notice, that not all browsers support this headless mode - we recommend using &amp;quot;firefox&amp;quot; or &amp;quot;chrome&amp;quot; for this.&lt;br /&gt;
&lt;br /&gt;
Also notice, that in order to verify that a web page&#039;s interaction with a browser works correctly, you should test against real browsers.&lt;br /&gt;
For an introduction on what &amp;quot;headless browsing&amp;quot; means, see for example [https://www.guru99.com/selenium-with-htmlunit-driver-phantomjs.html https://www.guru99.com/selenium-with-htmlunit-driver-phantomjs.html].&lt;br /&gt;
&lt;br /&gt;
Notice: the HTMLUnit driver has been removed from the latest selenium distribution and is also no longer supplied with expecco (it was not a good test tool anyway, as it behaved differently from real browsers).&lt;br /&gt;
&amp;lt;br&amp;gt;If required, download from [https://github.com/SeleniumHQ/htmlunit-driver https://github.com/SeleniumHQ/htmlunit-driver].&lt;br /&gt;
&lt;br /&gt;
==Connection Blocks==&lt;br /&gt;
SeleniumWebDriverLibrary offers a number of blocks to start a Selenium connection within a testrun. The &#039;&#039;connection name&#039;&#039; identifies the connection during the run, if the test uses multiple connections and switches between them (eg. if multiple browser windows are open simultaneously). To start a connection with predefined settings, save them in the connection dialog (as attachment), and use the &amp;quot;[&#039;&#039;Connect From File&#039;&#039;]&amp;quot; action block.&lt;br /&gt;
&lt;br /&gt;
=Plugin Settings=&lt;br /&gt;
To use certain browser installations or drivers as default, for every connection, set them in the settings dialog of the plugin (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Selenium WebDriver Extension&#039;&#039;&amp;quot;). Settings for specific browsers can be found under &amp;quot;&#039;&#039;Most Popular Browsers&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Other Browsers&#039;&#039;&amp;quot;. The settings there are used as default, unless overwritten by an individual connection configuration.&lt;br /&gt;
&lt;br /&gt;
===Execution Delay for Chrome===&lt;br /&gt;
In some cases it can happen when using the Chrome browser that blocks with element actions, for example a click, run successfully in the test, but the actual action was not executed at all. This is a known bug [https://github.com/MPDL/imeji-gui-testing/issues/37], [https://github.com/SeleniumHQ/selenium/issues/4075] that needs to be fixed by Selenium or Chromedriver. The error can be prevented by either calling the click via JavaScript&amp;amp;nbsp;– to do this, set &#039;&#039;invokeDirectly&#039;&#039; to &#039;&#039;true&#039;&#039; at the click block&amp;amp;nbsp;– or wait briefly before the action. Execution via JavaScript has the disadvantage that it is less close to the click of a real user and, for example, clicks on elements work even if they are hidden by other elements. In general, blocks with element actions automatically wait until the corresponding element is available. In the cases described here, however, this is not sufficient. Therefore you will find the setting &#039;&#039;execution delay&#039;&#039; in the plugin settings for Chrome. During execution, the system waits accordingly long between each action. If you experience the described error, you can increase its value. Of course, a higher value has an effect on the test run executio times.&lt;br /&gt;
&lt;br /&gt;
=Recorder=&lt;br /&gt;
The following description applies to all GUI technologies which support remote recording in the integrated expecco recorder: the behaviour of the recorder is (apart from small differences due to technology-specific limitations) the same across different connections.&lt;br /&gt;
&lt;br /&gt;
Use of this recorder has some advantages over direct recording in the browser:&lt;br /&gt;
* it can be used with remote machines/connections/mobil devices&amp;lt;br&amp;gt;especially for mobile devices, which may be all located in a separate (server-) room&lt;br /&gt;
* it provides precise control over which event is to be recorded.&amp;lt;br&amp;gt;For example, for clicks, there are alternative ways to record: as &amp;quot;press-release&amp;quot;, as &amp;quot;click&amp;quot;, as &amp;quot;move-then-click&amp;quot;, as &amp;quot;move-then-press-delay-release&amp;quot;. Depending on the page&#039;s underlying event handling (typically done in JavaScript), either one may be required.&lt;br /&gt;
&lt;br /&gt;
Once connected to a browser, the integrated recorder can be used to record a test case. Start the recorder by selecting the appropriate connection in the GUI browser&#039;s left tree and click the &#039;&#039;record&#039;&#039; button. The recorder opens a new window. Each click in the window records an action. More actions are available in the menu. Recorded actions are added to the &#039;&#039;workspace&#039;&#039; of the GUI browser to form a sequence of interactions. This sequence can be edited, parametrized or replayed immediately. When finished, it should be saved into the suite as a new &amp;quot;Test Action&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
General actions can be found either directly in the menu bar or there in the Browser Tools menu (see below). To record actions on elements, either change the selection of the element tool in the menu bar (see below) and click on the element or select the corresponding action from the context menu by right-clicking on the element. For text input, you can also place the cursor over the element and enter the text. The input dialog for this action opens. It is also possible to record the imputs &#039;&#039;backspace&#039;&#039;, &#039;&#039;return&#039;&#039; and &#039;&#039;tab&#039;&#039; that way.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverRecorder.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Components of the recorder window&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Pause recording&#039;&#039;&#039;: If the control lamp is red, the recorder is in &amp;quot;&#039;&#039;recording&#039;&#039;&amp;quot;-mode. Pause the recording by clicking on this lamp. The lamp will turn to grey. In this state you can execute actions with the recorder, but they are not recorded. Click again to resume the recording.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Update the screenshot on the element tree. Necessary if the recorder view does not fit the browser content.&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: The element under the cursor is selected in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the cursor gets a red frame.&lt;br /&gt;
#&#039;&#039;&#039;Element Tools&#039;&#039;&#039;: Select which tool to use for recording. You can choose between all actions that use a certain element. The selected action is triggered by each click in the view and the element is determined by the click position. Not selected actions are available by right click.&lt;br /&gt;
#&#039;&#039;&#039;Browser Tools&#039;&#039;&#039;: Actions not refering to ocertain elements, like scrolling or actions on the current URL or the title, can be triggered here.&lt;br /&gt;
#&#039;&#039;&#039;Page navigation&#039;&#039;&#039;: Actions for page navigation: &#039;&#039;Back&#039;&#039;, &#039;&#039;Forward&#039;&#039; and &#039;&#039;Refresh Page&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Alert Handling&#039;&#039;&#039;: Click this button if the browser shows an alert, to be able to select the actions for alert handling.&lt;br /&gt;
#&#039;&#039;&#039;Online Documentation&#039;&#039;&#039;: Open this online documentation.&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the browsers. Actions can be triggered by mouse depending on the selected tool. If a new action can be entered, the frame of the window is green, red otherwise. Scrolling is forwarded to the browser, but not recorded.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Screen Size&#039;&#039;&#039;: Change the size of the window to show the whole screenshot.&lt;br /&gt;
#&#039;&#039;&#039;Set Screen Scale to Fit Window&#039;&#039;&#039;: Scale the screenshot to fully fit in the window&lt;br /&gt;
#&#039;&#039;&#039;Scale&#039;&#039;&#039;: Changes the scale of the screenshot. Can also be adjusted by scrolling with pressed &amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt; key.&lt;br /&gt;
#&#039;&#039;&#039;Notifications&#039;&#039;&#039;: Shows notifications, e.g. if an action cannot be recorded. The last notification is displayed until it is closed by the button on its right side.&amp;lt;br&amp;gt;&#039;&#039;&#039;Window Tabs&#039;&#039;&#039;: As of expecco 23.1, tabs are displayed above the display for each open window as soon as a connection has more than one browser window. Whether the browser displays this as a tab or in its own window does not matter. You can use the tabs in the recorder to switch the current window and also record this switch.&amp;lt;br&amp;gt;&#039;&#039;&#039;Frame context&#039;&#039;&#039;: As of expecco 23.1, you can see below the display in which frame context you are currently in (see the section [[#Embedded_Content|Embedded Content]]). You can click on the entries to switch to a higher context and record this switch. If you have compound paths enabled, the display will update when you select an embedded item.&lt;br /&gt;
&lt;br /&gt;
=Embedded Content=&lt;br /&gt;
In HTML it is possible to include content from another page within one page. The most common element to do this is an iframe (inline frame). The content of an iframe can also be accessed with Selenium, but first you have to switch to this context. In the SeleniumWebDriverLibrary there are corresponding blocks to switch to the context of an iframe, to switch to the parent context and to switch back to the default content, i.e. the top context. All element blocks always resolve the applied paths within the current context. In the GUI browser, you will see an additional element for embedded content, which you can expand to see its elements.&lt;br /&gt;
&lt;br /&gt;
==Compound Paths==&lt;br /&gt;
Since expecco 23.1 there is the possibility to also use compound paths at the blocks to access the content of an iframe directly from the standard content. For this purpose, simply the path to the iframe and the path within the iframe content are combined into one. It is important here that no elements may be omitted at the transition, i.e. the front part must end with the iframe element and the back part must begin with &#039;&#039;/body&#039;&#039;. In between the paths may be shortened and it is of course also possible to access elements nested to any depth in this way. Both techniques can be used on the blocks as desired, the only important thing is that the paths are always resolved in the context in which Selenium is currently located.&lt;br /&gt;
&lt;br /&gt;
If you want to record the combined paths or use them in the GUI Browser, check the box &#039;&#039;Record Compound Paths&#039;&#039; in the &#039;&#039;GUI Browser&#039;&#039; menu under &#039;&#039;Recording&#039;&#039;. This will create and display a compound path for embedded elements relative to the current context, instead of only within its own context as before. You can also address these elements directly in the recorder or find them via Follow-Mouse.&lt;br /&gt;
&lt;br /&gt;
=Shadow Elements=&lt;br /&gt;
Shadow DOMs allow you to encapsulate parts of a page from the remaining document. They provide a way to attach hidden shadow elements to an element. You can find a more detailed explanation for example here: [https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM Using shadow DOM - Web APIs | MDN].&lt;br /&gt;
&lt;br /&gt;
The SeleniumWebDirverLibrary has the block &#039;&#039;[Web] Get Shadow DOM&#039;&#039;, which gives you the topmost elements, which then can be used like other WebElements.&lt;br /&gt;
&lt;br /&gt;
As the elements are hidden, they are not directly displayed in the GUI browser. However, since expecco 23.1 you can check in the context menu of the elements in the GUI browser the option to find shadow elements. They then will be displayed when updating the children of an element, if there are any, but not when updating the whole tree. If the option is checked, the elements are also available in the recorder.&lt;br /&gt;
&lt;br /&gt;
==Compound Paths==&lt;br /&gt;
Similar to elements inside a frame, shadow elements can be accessed by compound paths. These paths can be used directly at the library blocks and the block &#039;&#039;[Web] Get Shadow DOM&#039;&#039; is not required. The paths are of the form&lt;br /&gt;
 &amp;lt;host path&amp;gt;/shadowRoot/&amp;lt;shadow path&amp;gt;&lt;br /&gt;
where &#039;&#039;&amp;lt;host path&amp;gt;&#039;&#039; denotes the path to the element that has the shadow DOM attached, and &#039;&#039;&amp;lt;shadow path&amp;gt;&#039;&#039; denotes the path inside the shadow DOM to the desired element. &#039;/shadowRoot&#039; serves as marker where the switch to the shadow DOM is needed.&lt;br /&gt;
&lt;br /&gt;
=Authentication Alerts=&lt;br /&gt;
If a Web page uses HTTP authentication with Basic Authentication, an alert window for entering the user name and password opens when the page is loaded. This window cannot be accessed directly with Selenium. In the GUI browser, it is displayed as an alert. An exception to this is Chrome, where the driver does not respond to any request as long as the dialog is open. At this point, the plugin cannot even determine whether an authentication dialog is open or whether the driver is not responding for other reasons.&lt;br /&gt;
&lt;br /&gt;
For local connections under Windows, authentication can be performed using Windows Access. In the SeleniumWebDriverLibrary there are specific authentication blocks for individual browser types as well as the block &#039;&#039;Authenticate at Alert&#039;&#039;, which executes the corresponding block depending on the connection. There are different restrictions for the different browser types:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Chrome:&#039;&#039;&#039; The credentials are sent to a chrome window, so it only works if not more than one are open. In this case, the single block has the option to specify the title of the window.&lt;br /&gt;
:&#039;&#039;&#039;Edge&#039;&#039;&#039;: With Microsoft Edge a login is not supported.&lt;br /&gt;
:&#039;&#039;&#039;Firefox&#039;&#039;&#039;: Sends the credentials to a Firefox dialog box and therefore only works if there are not multiple ones.&lt;br /&gt;
:&#039;&#039;&#039;Internet Explorer&#039;&#039;&#039;: With Internet Explorer a login is not supported.&lt;br /&gt;
&lt;br /&gt;
As an additional option, you can also log in using the URL. Instead of the page &amp;lt;nowiki&amp;gt;https://www.example.com&amp;lt;/nowiki&amp;gt; call the URL &amp;lt;nowiki&amp;gt;https://user:password@www.example.com&amp;lt;/nowiki&amp;gt;. It is important that &#039;&#039;:&#039;&#039; and &#039;&#039;@&#039;&#039; do not appear in the user name or password. This method may not be supported by every browser.&lt;br /&gt;
&lt;br /&gt;
With the [[WindowsAutomation_Reference_2.0/en|WindowsAutomation2]]-Plugin it is also possible to execute such a login with all browser types.&lt;br /&gt;
&lt;br /&gt;
=Transferring Old Selenium Tests=&lt;br /&gt;
This Plugin replaces the previous [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]], which is based on [https://www.seleniumhq.org/projects/remote-control/ Selenium RC]. Selenium RC is no longer supported by their authors and it will also no longer be maintained by exept. The successor is [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver], also referred to as Selenium 2. &lt;br /&gt;
&lt;br /&gt;
Recording of test actions using [https://www.seleniumhq.org/projects/ide/ Selenim IDE] is also outdated, as the plugin is not supported by newer browsers. The &#039;&#039;Selenium WebDriver Plugin&#039;&#039; uses its own [[#Recorder|Recorder]] instead.&lt;br /&gt;
&lt;br /&gt;
Tests which were created with the old &#039;&#039;Selenium WebTest Plugin&#039;&#039; using SeleniumLibrary can be executed with the new Selenium WebDriver. &lt;br /&gt;
For this, go to the plugin settings of &amp;quot;&#039;&#039;Webtest Legacy (Selenium)&#039;&#039;&amp;quot; and check &amp;quot;&#039;&#039;Use WebDriver for execution&#039;&#039;&amp;quot;. Please verify that your tests are still running after this change, as there is no 100% backward compatibility (which is outside the scope of expecco). However, most of the old test actions should run without problems.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*&#039;&#039;&#039;Scrollbars cannot be handled in the recorder&#039;&#039;&#039;&lt;br /&gt;
:The scrollbar of the browser which is diplayed if a page is larger than the browser window is no controllable web element. Mostly it is useless to scroll by a certain amount in a test where the size of the browser window is not defined. Instead, use the block &amp;lt;code&amp;gt;[Web] Scroll Element into View&amp;lt;/code&amp;gt; to scroll a relevant element to the visible region. The default click block used by the recorder already includes this action (&amp;lt;code&amp;gt;[WebElement] Click (Scroll Element into View)&amp;lt;/code&amp;gt;). If you scroll on the recorder window, the action will also be applied to the browser, but is not recorded. If you actually want to scroll by a certain amount, there is an appropriate entry in the browser actions, and more blocks in the SeleniumWebDriverLibrary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Block fails if element becomes visible too late&#039;&#039;&#039;&lt;br /&gt;
:All blocks that use an element path have built in that they wait until a corresponding element appears. However, there are cases where an element is already there, but not yet visible. If you click on the element you will get an error. Possible errors in this context are &amp;lt;code&amp;gt;org.openqa.selenium.ElementNotInteractableException: element not interactable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;. In this case, use the &amp;lt;code&amp;gt;[Web] Wait for Visibility of Element&amp;lt;/code&amp;gt; block or &amp;lt;code&amp;gt;[Web] Wait for Element to Be Clickable&amp;lt;/code&amp;gt; before interacting with the element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Error message &amp;lt;code&amp;gt;Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:The error &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt; can occur with the Chrome browser. This means that the used element is not visible. See the point above on that. The error is also known in combination with elements in a dropdown list, i.e. when clicking or moving the mouse over a &amp;lt;nowiki&amp;gt;&amp;lt;option&amp;gt;&amp;lt;/nowiki&amp;gt; element within a &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt; element. Such elements are generally not clickable. Instead, use a suitable &amp;lt;code&amp;gt;[Web] Select&amp;lt;/code&amp;gt; block with the &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt; element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Error message: &amp;lt;code&amp;gt;Stale Element Reference Exception&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:The error &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; occurs whenever a WebElement is used that is no longer there. If that happens during your test and the element should have been there, try using the locator instead to fetch the element again. Maybe the error occurs because the test is currently in a different frame context as the element. If you are using [[#Compound_Paths|compound paths]], the element should switch by itself to the correct context when it is used.&lt;br /&gt;
:In rare cases this error can also occur in expecco itself, if at somewhere in the GUI browser or the recorder such a WebElement is used. You should then be able to abort and try again. Should the error persist, switch to the default content and refresh the tree in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Block runs successfully, but without effect&#039;&#039;&#039;&lt;br /&gt;
:This case can occur with Chrome. The element is available, the action does not throw an error, but nothing is executed. Usually it helps to wait briefly before the execution, see [[#Execution_Delay_for_Chrome | Execution Delay for Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Executions using Chrome are slower&#039;&#039;&#039;&lt;br /&gt;
:To fix a problem when executing with Chrome, a delay is defined in the plugin settings for Chrome. Check if this value is possibly too high; see [[#Execution_Delay_for_Chrome | Execution Delay for Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Errors like: &amp;quot;org.openqa.selenium.InvalidArgumentException: Expected &amp;quot;handle&amp;quot; to be a string...&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
:This occurs if the driver does not match the browser (any more). Please read the above chapter &amp;quot;[[#Update WebDriver|Update WebDriver]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Key Chords with Shortcuts are not working&#039;&#039;&#039;&lt;br /&gt;
:Pressing keys simultaneously can be simulated using Key Chords. They can also be used to send shortcuts. However, not all inputs will work, as they are only sent to the page content, not to the browser itself. Combinations like &#039;&#039;Ctrl + t&#039;&#039; to open a new browser tab probably wont&#039;t work, &#039;&#039;Ctrl + a&#039;&#039; and &#039;&#039;Ctrl  c&#039;&#039; on the other hand should be effective.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Additional Window Handles for Opera&#039;&#039;&#039;&lt;br /&gt;
:The Opera browser returns more window handles as there are opened tabs or windows. They represent Opera internal features like &#039;&#039;Speed Dial&#039;&#039; or &#039;&#039;Better Address Bar Experience&#039;&#039; (BABE), which are embedded in the browser window, but not displayed like regular tabs. You can switch to these tabs using an appropriate action block, however not all actions are possible then, which can be used with the normal tabs. For example you cannot close them and they don&#039;t provide a screenshot. Therefore it is better to not even switch to their contexts. So be careful when switching to a tab by index, as the Opera tabs are among the others and the index might be a different one than for the other browser types.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Chrome: Choose your search engine&#039;&#039;&#039;&lt;br /&gt;
:Newer versions of Chrome show an [https://www.google.com/chrome/choicescreen/ overlay] at startup, where you have to choose a search engine. Usually, this choice is saved in the user profile. However, if you don&#039;t explicitly set a Chrome profile for the connection, each connect will use an empty profile and this question will always show up.&lt;br /&gt;
&lt;br /&gt;
:In most cases, the test can run in the back despite the overlay. However, the overlay counts as tap or window, meaning the block &#039;&#039;[Web] Get Window Handles&#039;&#039; for an example returns a window handle for it and you can switch to it. But you have options to get rid of it:&lt;br /&gt;
:* &#039;&#039;--disable-search-engine-choice-screen&#039;&#039;: In the [[#Advanced_Settings|advanced settings]] you can add the option &amp;lt;code&amp;gt;--disable-search-engine-choice-screen&amp;lt;/code&amp;gt; and the overlay won&#039;t show up.&lt;br /&gt;
:* &#039;&#039;Choose&#039;&#039;: You can extend your test, so it actually chooses a search engine and closes the overlay. There are two things you need to bear in mind. First, you have to switch there using a &#039;&#039;Switch to Window&#039;&#039; block (e.g. by index &#039;&#039;2&#039;&#039; or with an empty title) and back to your original tab afterwards as well. Secondly, the interesting elements in the overlay are [[#Shadow_Elements|shadow elements]] and as such not directly displayed in the GUI-Browser.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Firefox: &amp;lt;code&amp;gt;Process unexpectedly closed with status 0&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Error pattern: The connection to the Firefox browser fails with the error message &amp;lt;code&amp;gt;org.openqa.selenium.WebDriverException: Process unexpectedly closed with status 0&amp;lt;/code&amp;gt;. However, the browser eventually opens without there being a connection in expecco.&lt;br /&gt;
:A known cause of this issue is that the browser is started for the first time after an update, which the browser cannot handle properly in the automated state. The second attempt should then be successful. To prevent this error, make sure that you always start the browser normally the first time after an update.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29684</id>
		<title>Selenium WebDriver Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29684"/>
		<updated>2024-08-22T15:02:28Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* FAQ */ Firefox nach Update&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Selenium_WebDriver_Plugin/en|English Version]]&lt;br /&gt;
=Achtung=&lt;br /&gt;
Das Webtest Selenium WebDriver Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Zur Automatisierung wird [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver] verwendet (Driver für gängige Browser werden von uns mitgeliefert), der das bisher verwendete Selenium RC ersetzt. Dies wurde einerseits notwendig, da die SeleniumRC Schnittstelle von neuen Browsern nicht mehr unterstützt wird, andererseits, sinnvoll, da auch andere UI Technologien mit diesem Protokoll angesprochen werden können. &lt;br /&gt;
&lt;br /&gt;
Sie können dieses Protokoll nur noch mit älteren Browsern verwenden, und wir empfehlen dringend, auf die neue Version umzusteigen. &amp;lt;br&amp;gt;Hinweise zur Migration älterer Testsuiten finden Sie [[#Portierung_alter_Selenium-Tests | unten]].&lt;br /&gt;
&lt;br /&gt;
=Einleitung=&lt;br /&gt;
Mit dem Selenium WebDriver Plugin können Sie Tests von Webapplikationen erstellen oder auch diese automatisieren (*). Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests oder automatisierten Browseraktionen unterstützt. Zudem ist damit das Aufzeichnen von Abläufen möglich.&lt;br /&gt;
&lt;br /&gt;
(*) tatsächlich gibt es auch WebDriver-Schnittstellen um z.B. Windows-Apps oder OPS-Fenster zu manipulieren. Insofern gibt es für dieses Plugin weitere Einsatzbereiche.&lt;br /&gt;
&lt;br /&gt;
=Einstellungen=&lt;br /&gt;
Das Plugin verwendet die Java-Bridge und benötigt daher eine Java-Installation. Sie können diese in den Einstellungen unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Java Bridge&#039;&#039; angeben. Wichtig ist hier das Feld &#039;&#039;Pfad zur Java-Installation&#039;&#039;, wo Sie ein JDK oder JRE angeben können. Ist nichts angegeben, versucht expecco java im PATH zu finden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Für das Selenium WebDriver Plugin selbst gibt es ebenfalls Einstellungsmöglichkeiten, die Sie unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Webtest (Selenium WebDriver)&#039;&#039; finden. Hier können Sie zum Beispiel die Adresse zu einem remote laufenden Selenium-Server angeben oder eine andere Jar-Datei für Selenium angeben. Einstellungen zu den verschiedenen Browser-Typen teilen sich auf die Unterseiten &#039;&#039;Beliebte Browser&#039;&#039; und &#039;&#039;Andere Browser&#039;&#039; auf. Dort können Sie den Pfad zur Browser-Ausführungsdatei oder zum Webdriver angeben, der verwendet werden soll. Diese Felder können Sie alle leer lassen, expecco wird dann automatisch danach suchen.&lt;br /&gt;
&lt;br /&gt;
=Browser-Unterstützung=&lt;br /&gt;
Das Plugin unterstützt die Browser Chrome/Chromium, Edge, Firefox, Internet Explorer und Opera. &lt;br /&gt;
&amp;lt;br&amp;gt;Safari unter OSX muss zumindest in der Version 10 vorliegen und OSX muss mindestens die El Capitan Version sein.&lt;br /&gt;
Zur Kommunikation wird die WebDriver Schnittstelle verwendet; somit kann der getestete Browser sowohl lokal als auch auf einem entfernten Rechner laufen.&lt;br /&gt;
&lt;br /&gt;
Da inzwischen eine Vielzahl von weiteren Browsen, Geräten und graphischen Oberflächen eine WebDriver Schnittstelle anbieten, können auch diese - z.T. mit eingeschränktem Funktionsumfang - über diese automatisiert werden. So gibt es z.B. auch Schnittstellen für Windows Mobilgeräte oder Desktopanwendungen.&lt;br /&gt;
&lt;br /&gt;
== WebDriver aktualisieren==&lt;br /&gt;
Für jeden Browsertyp gibt es einen Driver, über den das Starten und Ansteuern der Browserfenster funktioniert. Für die wichtigsten Browser finden sich im Lieferumfang aktuelle Driverversionen. Da die Browser fortlaufend aktualisiert werden, teilweise sogar automatisch, müssen Sie früher oder später neue Driverversionen herunterladen. Legen Sie diese dann in Ihrem expecco-Installationsverzeichnis bei den anderen Versionen ab, und zwar unter:&lt;br /&gt;
 &amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib/XXX&amp;lt;/code&amp;gt;&lt;br /&gt;
(unter Microsoft Windows Betriebssystemen mit &amp;quot;\” anstatt &amp;quot;/&amp;quot;), wobei &amp;quot;XXX&amp;quot; für das Betriebssystem steht (Windows, Linux, OSX etc.).&lt;br /&gt;
&lt;br /&gt;
Im Verbindungsdialog warnt expecco, wenn eine Driverversion nicht zur Browserversion passt. In manchen Fällen kann das aber auch nur daran liegen, dass  diese Version zum Zeitpunkt der Auslieferung noch nicht bekannt war. Manche Kombinationen können trotz der Warnung funktioniert, aber das können wir im Einzelfall nicht garantieren.&lt;br /&gt;
&lt;br /&gt;
Daher können Sie bei einer solchen Warnung immer die Option &amp;quot;&#039;&#039;Diese Warnung nicht mehr anzeigen&#039;&#039;&amp;quot; anwählen, damit diese Driver-Browser-Versionskombination in ihren Settings als &amp;quot;kompatibel&amp;quot; vermerkt wird, und in Zukunft nicht mehr gemeldet wird. Dies sollten Sie aber nur machen, wenn Sie sicher sind, dass Ihre Tests nach wie vor korrekt ausgeführt werden. Da wir hier selbst bisweilen auf Kompatibilitätsprobleme stoßen, und nicht immer gleich klar ist, woran es liegt, empfehlen wir aber den Driver zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
Für Chrome und Microsoft Edge, bei denen es für jede neue Browserversion auch eine neue Driverversion gibt, finden Sie im Verbindungsdialog einen Button, um mit expecco die passende Version herunterzuladen.&lt;br /&gt;
&lt;br /&gt;
Neuere Versionen der Driver bekommen Sie an folgenden Adressen:&lt;br /&gt;
{|&lt;br /&gt;
|Chrome/Chromium&lt;br /&gt;
|[https://sites.google.com/chromium.org/driver/ ChromeDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Edge&lt;br /&gt;
|[https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ Microsoft WebDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|[https://github.com/mozilla/geckodriver/releases GeckoDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|[https://selenium-release.storage.googleapis.com/index.html IEDriverServer]&lt;br /&gt;
|-&lt;br /&gt;
|Opera&lt;br /&gt;
|[https://github.com/operasoftware/operachromiumdriver/releases OperaDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|[https://webkit.org/blog/6900/webdriver-support-in-safari-10 Safari Support]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Laden Sie sich eine passende Version herunter und legen Sie sie im oben genannten Verzeichnis an der entsprechenden Stelle ab. Expecco wird sie dann finden und verwenden. &amp;lt;!-- Sie können den Namen der Datei erweitern, um mehrere Versionen nebeneinander verwenden zu können. --&amp;gt; Alternativ können Sie auch in expecco den Pfad zu einem Driver angeben, entweder im [[#Erweiterte_Einstellungen | Verbindungseditor]] oder in den [[#Plugin-Einstellungen | Plugin-Einstellungen]].&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Bitte verifizieren Sie, daß die Version des Drivers kompatibel ist mit der des Browsers. Im Zweifel suchen Sie nach der Versionshistorie (z.B. für Chrome: https://chromedriver.storage.googleapis.com/2.25/notes.txt).&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Für den Internet Explorer ist zu beachten, dass der geschützte Modus für alle Zonen gleich eingestellt sein muss, damit eine Verbindung möglich ist. (im Internet Explorer: &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Internetoptionen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Sicherheit&#039;&#039;&amp;quot; öffnen, und bei allen 4 Zonen &amp;quot;geschützter&amp;quot; Bereich gleich einstellen; ansonsten kommen beim Verbindungsaufbau Fehler- und Warndialoge). Siehe außerdem die [https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration erforderliche Konfiguration] zur Verwendung des InternetExplorerDrivers.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Das Plugin verwendet für einige Funktionen JavaScript. Stellen Sie daher sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist, insbesondere wenn Sie den GUI-Browser oder den Recorder verwenden wollen. Das Ausführen von Tests ist auch ohne JavaScript möglich, solange keine Aktionen verwendet werden, welche JavaScript benötigen oder explizit ausführen.&amp;lt;br&amp;gt;Sollten Sie einen Fehler der Art &amp;quot;&amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: Error executing JavaScript&amp;lt;/code&amp;gt;&amp;quot; bekommen, stellen Sie sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist und Browser- und zugehörige WebDriver-Version kompatibel sind.&lt;br /&gt;
&lt;br /&gt;
= Headless Browser =&lt;br /&gt;
Mit &amp;quot;&#039;&#039;Headless&#039;&#039;&amp;quot; bezeichnet man eine Anwendung, welche ohne Bedienoberfläche abläuft. Einige der Browser unterstützen einen &amp;quot;headless&amp;quot; Modus,  bei dem kein Browserfenster angezeigt wird. Der Browser operiert dabei in einem &amp;quot;unsichtbaren Fenster&amp;quot; führt aber alle Operationen aus, und liefert auch die selbe Elementhierarchie.&lt;br /&gt;
Bei einigen Browsern sind allerdings die Screenshot (Bild vom Fenster bzw. von Elementen) eingeschränkt bzw. gar nicht verfügbar.&amp;lt;br&amp;gt;Den &amp;quot;headless&amp;quot; Modus können Sie beim Verbindungsaufbau in den &amp;quot;&#039;&#039;Advanced Settings&#039;&#039;&amp;quot; angeben.&lt;br /&gt;
&lt;br /&gt;
= HTML Unit Browser =&lt;br /&gt;
Bei diesem &amp;quot;&#039;&#039;Pseudobrowser&#039;&#039;&amp;quot; handelt es sich um eine weitere &amp;quot;&#039;&#039;headless&#039;&#039;&amp;quot; Variante, welche ganz ohne Renderengine operiert, und lediglich die Elementhierarchie sowie Javascript unterstützt. Sein Verhalten kann stark von dem &amp;quot;echter&amp;quot; Browser abweichen.&lt;br /&gt;
&lt;br /&gt;
Diesen Browsertyp können Sie verwenden, wenn ihr Test das Verhalten des Webservices (also der Servierseite) betrifft, und nicht das Verhalten der Anwendung im Browser (End-User-Experience) im Fokus hat. Zum Beispiel kann der &amp;quot;HTML Unit Browser&amp;quot; zum Generieren von Last oder gleichzeitigen Aktionen gegenüber dem Server dienen.&lt;br /&gt;
Da sich dieser Browser im Verhalten z.T. stark von dem echter Browser unterscheidet sollte er nur (wenn überhaupt) in besonderen Fällen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
= Schneller Einstieg =&lt;br /&gt;
== Browser öffnen / verbinden ==&lt;br /&gt;
* Starten Sie expecco&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Neue Testsuite&#039;&#039;&amp;quot;&lt;br /&gt;
* Klicken Sie auf das GUI-Browser Symbol ([[Datei:GUIBrowser.png|24px]])&lt;br /&gt;
* Es erscheint der GUI-Browser in einem neuen Reiter&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; und wählen Sie &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot; aus. Dann erscheint der [[#Verbindungseditor | Verbindungsdialog]] (Details siehe unten)&lt;br /&gt;
* Im Verbindungsdialog geben Sie die zu testende Webseite ein (z.B. &amp;quot;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.myHost.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;) und wählen den Browsertyp (z.B. &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;firefox&amp;lt;/code&amp;gt;&amp;quot;) aus&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot;&lt;br /&gt;
* Ein Browser wird nun automatisch gestartet, und die Seite angezeigt.&lt;br /&gt;
* Sobald die Verbindung steht, wird im GUIBrowser die Seitenstruktur als Baum angezeigt, und im rechten Diagramm-Fenster erscheint ein passender Verbindungsbaustein. Dieser wird nicht automatisch aufgezeichnet, da man diesen normalerweise nicht in jeder aufgezeichneten Sequenz haben will (mehr dazu unten).&lt;br /&gt;
&lt;br /&gt;
== Recording aufnehmen ==&lt;br /&gt;
* Klicken Sie auf das Recording Symbol im GUI-Browser.&lt;br /&gt;
[[Datei:Recording_Start.png | 200px]]&lt;br /&gt;
* Ein Recorderfenster erscheint (eine Beschreibung der Bedienelemente finden Sie unten)&lt;br /&gt;
* Sie zeichnen nun direkt im Rekorder auf.&amp;lt;br&amp;gt;&lt;br /&gt;
* Klicks werden je nach Einstellung als Klick, Mausbewegung, Drag&amp;amp;Drop etc. aufgezeichnet.&amp;lt;br&amp;gt;Während der Aufzeichnung können Sie zwischen diesen Werkzeugen wechseln:&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Recorder_Werkzeuge.png | 300px]]&lt;br /&gt;
* die aufgezeichneten Aktionen werden im Tab &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; dargestellt. Sie können dort noch bearbeitet werden.&lt;br /&gt;
* Zum Beenden der Aufzeichnung klicken Sie entweder auf den &amp;quot;&#039;&#039;Stop Recording&#039;&#039;&amp;quot; Knopf im GUI Browser, oder schließen das Rekorderzenster. Es ist auch möglich, das Aufzeichnen temporär zu Pausieren, indem sie im Rekorder auf den &amp;quot;&#039;&#039;Aufnahme&#039;&#039;&amp;quot;-Knopf oben links drücken.&lt;br /&gt;
* Nach dem Aufzeichnen können sie die Sequenz un ihre Testsuite als Testfall oder Teilsequenz übernehmen.&lt;br /&gt;
&lt;br /&gt;
== Aufgezeichnete Aktion wiedergeben ==&lt;br /&gt;
&lt;br /&gt;
* Im Reiter &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; kann die aktuelle Aufzeichnung sofort wiedergegeben werden (&amp;quot;&#039;&#039;Play&#039;&#039;&amp;quot;-Knopf drücken)&amp;lt;br&amp;gt;Beachten Sie, daß ihre Webseite üblicherweise im gleichen Zustand sein sollte - gegebenenfalls sollten Sie also den &amp;quot;&#039;&#039;Back&#039;&#039;&amp;quot;-Knopf oder eine andere Navigation anwenden, um dies sicher zu stellen.&lt;br /&gt;
* Die Sequenz kann bearbeitet werden. Dazu können entweder weitere Aktionen aufgenommen werden, oder zusätzliche Aktionen entweder via Drag&amp;amp;Drop oder über das Kontextmenü (bzw. &amp;lt;kbd&amp;gt;&amp;lt;CTRL-N&amp;lt;/kbd&amp;gt;) angelegt werden. Häufig werden zusätzliche Delay- oder Verifikations-Bausteine benötigt, die sie hiermit an geeigneter Stelle einfügen können.&lt;br /&gt;
&lt;br /&gt;
=Verbindungsaufbau=&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Verbindungsdialog&amp;quot;&amp;gt;Verbindungseditor==&lt;br /&gt;
Mit dem Verbindungseditor werden Verbindungen definiert, geändert und aufgebaut. Sie erreichen ihn, indem Sie den GUI-Browser öffnen und dort auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; klicken und dann &amp;quot;&#039;&#039;Selenium Testing (WebDriver)&#039;&#039;&amp;quot; auswählen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverConnectDialog.png]]&lt;br /&gt;
&lt;br /&gt;
#&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;: Öffnet einen Anhang im expecco Projekt mit Verbindungseinstellunge. Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen aus Datei&#039;&#039;: Öffnet eine gespeicherte Einstellungsdatei (*.csf). Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in JSON-Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen im JSON-Format als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in Datei speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern.&lt;br /&gt;
#&#039;&#039;Versionsinfo&#039;&#039;: Zeigt ein Fenster mit den verwendeten Versionen des Selenium-Servers, des ausgewählten Browser und dessen Driver an.&lt;br /&gt;
#&#039;&#039;Online-Dokumentation&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;Verbindungsname&#039;&#039;: Tragen Sie hier den Namen ein, unter dem die Verbindung im GUI-Browser angezeigt werden soll. (Optional)&lt;br /&gt;
#&#039;&#039;Browsertyp&#039;&#039;: Wählen Sie hier aus, welchen Browser Sie verwenden möchten. Stellen Sie sicher, dass dieser installiert ist und die Version des verwendeten Drivers zur Browserversion passt.&lt;br /&gt;
#&#039;&#039;URL&#039;&#039;: Tragen Sie hier die URL ein, die zu Beginn aufgerufen werden soll. Sie können das Feld auch frei lassen, dann wird ein leeres Browser-Fenster geöffnet. Um eine lokale Datei zu öffnen, verwenden Sie das Schema &amp;quot;&amp;lt;code&amp;gt;file://&amp;lt;/code&amp;gt;&amp;quot;, z.B. &amp;quot;&amp;lt;code&amp;gt;file:///C:/Users/admin/Desktop/index.html&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
#&#039;&#039;Erweiterte Ansicht&#039;&#039;: Wechselt zur Ansicht für die Eingabe von [[#Erweiterte Einstellungen|erweiterten Einstellungen]].&lt;br /&gt;
#&#039;&#039;Informationen zum gewählten Browser&#039;&#039;: Hier wird der ausgewählte Browsertyp kurz vorgestellt.&lt;br /&gt;
#&#039;&#039;Informationen zu den Einstellungen&#039;&#039;: Hier wird angezeigt, welche Selenium-, Browser- und Driver-Version mit den aktuellen Einstellungen verwendet wird. Falls Sie [[#Erweiterte Einstellungen|erweiterten Einstellungen]] gesetzt haben, werden diese hier ebenfalls aufgelistet.&lt;br /&gt;
&lt;br /&gt;
===Warnung &amp;amp;uuml;ber m&amp;amp;ouml;gliche Inkompatibilit&amp;amp;auml;t ===&lt;br /&gt;
Manche Browser benötigen einen versionsspezifischen Webdriver, da die verwendeten Kommunikationsprotokolle unterschiedlich sein können. &lt;br /&gt;
&lt;br /&gt;
Da regelmässig neue Browserversionen erscheinen, und damit einhergehend auch neue Versionen des zug. Webdrivers benötigt werden, kann. es sein, dass die mit expecco mitgelieferten Webdriver nicht mehr zur aktuellen Browserversion passen. Dies trat in der Vergangenheit insbes. beim Chromebrowser mehrfach auf.&lt;br /&gt;
 &lt;br /&gt;
Um auf eventuelle Probleme hinzuweisen hält expecco intern eine Liste von Paaren der von exept bereits getesteten Browser- zu Webdriverversion. Falls ihr Browser aktueller ist, und nicht in der Liste enthalten ist, erscheint eine Warnung im Infobereich.&lt;br /&gt;
&lt;br /&gt;
Diese erscheint nur zu Ihrer Information - in den meisten Fällen funktioniert die Interaktion mit dem Browser auch dann. Allerdings ist es in jedem Fall sinnvoll, den Driver zu aktualisieren, um solche Probleme auszuschliessen.&lt;br /&gt;
Wenn die Kombination ohne Probleme läuft, ist es möglich, die aktuelle Kombination in die Liste einzutragen (drücken Sie dazu auf &amp;quot;Diese Kombination ist in Ordnung&amp;quot;). Dann erschient der Warndialog nicht mehr.&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Einstellungen===&lt;br /&gt;
Neben dem zu verwendenden Browser und der Start-URL kann man noch weitere Einstellungen für eine Verbindung vornehmen. Wechseln Sie dazu im Verbindungsmenü die Ansicht über den entsprechenden Menü-Eintrag. Je nachdem, welchen Browsertypen Sie ausgewählt haben, bekommen Sie andere Eingabefelder.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Remote Server&#039;&#039;: Falls der Browser auf einem entfernten Rechner gestartet werden soll, starten Sie dort einen Selenium-Server und geben Sie dessen Adresse in diesem Feld an. Natürlich können Sie auch eine lokale Adresse angeben, wenn nicht automatisch ein Selenium-Server gestartet werden soll. Lesen Sie hierzu auch den nächsten Abschnitt [[#Remote-Verbindungen|Remote-Verbindungen]].&lt;br /&gt;
*&#039;&#039;Binary&#039;&#039;: Geben Sie den Pfad zum Binary des ausgewählten Browsers an, wenn dieser nicht automatisch von Selenium gefunden wird oder Sie eine weitere Version installiert haben.&lt;br /&gt;
*&#039;&#039;Driver&#039;&#039;: Zu jedem Browser wird ein spezieller Driver zur Automatisierung benötigt. Für neue Versionen des Browsers braucht man häufig auch eine neue Version des entsprechenden Drivers. Wenn Sie nicht den von expecco installierten Driver verwenden wollen, geben Sie hier einen entsprechenden Pfad an.&lt;br /&gt;
*&#039;&#039;Firefox Profile&#039;&#039;: Für Firefox gibt es zusätzlich die Möglichkeit, ein Profil bzw. Template anzugeben, das spezifische Einstellungen enthält. Wenn keines angegeben wird, wird für jede Verbindung ein neues, leeres Profil angelegt.&lt;br /&gt;
*&#039;&#039;Capabilities&#039;&#039;: Für Selenium-Verbindungen sind einige Capabilities definiert, mit denen sich Verbindungs-Eigenschaften oder auch das Browserverhalten festlegen lassen. &lt;br /&gt;
Solche Capabilities können Sie sie in diesem Feld angeben. Schreiben Sie dazu &#039;&#039;&amp;lt;capability name&amp;gt;: &amp;lt;value&amp;gt;&#039;&#039; oder &#039;&#039;&amp;lt;capability name&amp;gt; = &amp;lt;value&amp;gt;&#039;&#039;; jeweils ein Eintrag pro Zeile. Außerdem können Sie hier auch Eigenschaften für den Firefox-Browser setzen. Die Eingabe hierfür erfolgt wie für die Capabilities, nur dass sie dem Namen der Eigenschaft ein &#039;&#039;$&#039;&#039; voranstellen müssen.&lt;br /&gt;
&lt;br /&gt;
:Angegebene Capabilities werden durch die Methode &#039;&#039;setCapability()&#039;&#039; gesetzt. Insbesondere bei der Verwendung von Chrome gibt es einige Einstellungsoptionen, die sich nicht mit dieser Methode setzen lassen, sondern beispielsweise über &#039;&#039;setExperimentalOption()&#039;&#039; angegeben werden müssen. Zu diesem Zweck haben Sie außerdem die Möglichkeit, in diesem Feld einen Methodenaufruf mit Werten anzugeben. Diese Methode wird dann auf das entsprechende Options- bzw. Capabilities-Objekt angewandt. Um die Struktur der Eingabe von normalen Capabilities beizubehalten, müssen Sie am Ende noch &#039;&#039;:&#039;&#039; oder &#039;&#039;=&#039;&#039; setzen, aber keinen Wert danach. Beispiel: &#039;&#039;setExperimentalOption(“useAutomationExtension”, false)=&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Lokale-Verbindungen==&lt;br /&gt;
Um einen Browser auf ihrer lokalen Maschine zu starten, werden lediglich die Felder &amp;quot;&#039;&#039;URL&#039;&#039;&amp;quot; sowie &amp;quot;&#039;&#039;Browsertyp&#039;&#039;&amp;quot; benötigt. Als Voreinstellung für den Browser wird &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; erscheinen.&lt;br /&gt;
&lt;br /&gt;
==Remote-Verbindungen==&lt;br /&gt;
Um einen Browser auf einem entfernten Rechner zu starten, müssen Sie zunächst den Selenium-Server und die benötigten Driver auf diesen Rechner kopieren. Auf dem Zielrechner muss Java installiert sein. Sie finden die Dateien in Ihrer expecco-Installation unter &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib&amp;lt;/code&amp;gt;&amp;quot;. Sie können sich auch von [https://www.selenium.dev/downloads/ Selenium] eine aktuelle Version herunterladen.&lt;br /&gt;
&amp;lt;br&amp;gt;Starten Sie dann den Selenium-Sever (auf dem entfernten Rechner) mit:&lt;br /&gt;
 java -jar selenium-server-standalone-3.141.59.jar&lt;br /&gt;
(die Versionsnummer wird in Ihren Fall eine andere sein)&lt;br /&gt;
&lt;br /&gt;
Standardmäßig wird der Server dann auf dem Port 4444 Verbindungen annehmen. Um einen anderen Port zu verwenden, &lt;br /&gt;
geben Sie diesen auf der Kommandozeile mit &amp;quot;&amp;lt;code&amp;gt;-port &amp;amp;lt;nr&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;quot; an. &lt;br /&gt;
&amp;lt;br&amp;gt;Um von expecco eine Verbindung über diesen Server herzustellen, geben Sie beim Verbindungsaufbau als Remote-Server &lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:4444/wd/hub&lt;br /&gt;
an.&lt;br /&gt;
&lt;br /&gt;
Das Starten des Selenium-Servers bzw. die Verbindung muss eventuell von der Firewall zugelassen werden.&lt;br /&gt;
&lt;br /&gt;
Falls der Server beim Verbinden die jeweiligen Driver nicht finden, legen Sie diese ins selbe Verzeichnis, in dem Sie den Server starten, oder fügen Sie das Verzeichnis in dem der Driver liegt zum Pfad hinzu. Beachten Sie dabei, dass expecco verschiedene Versionen eines Driver-Typs mitliefert und diese durch einen Namenszusatz unterscheidet. Aufgrund dieser Zusätze erkennt der Server die Dateien aber häufig nicht.&lt;br /&gt;
&lt;br /&gt;
Für neue Versionen von &#039;&#039;&#039;Microsoft Edge&#039;&#039;&#039;, die Chromium basieren, starten Sie anstatt eines Selenium-Servers direkt den MSEdgeDriver (&amp;quot;msedgedriver.exe&amp;quot;) in der Version, die zur Edge-Version auf diesem Rechner passt.&lt;br /&gt;
  msedgedriver.exe [--port=9515]&lt;br /&gt;
Wenn Sie keine Portnummer angeben, wird der Service auf dem Port 9515 gestartet. Geben Sie dann beim Verbindungsaufbau in expecco als Remote-Server die Adresse&lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:9515&lt;br /&gt;
an. Die Erweiterung &amp;quot;/wd/hub&amp;quot; ist hier nicht erforderlich.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsbausteine==&lt;br /&gt;
Der Verbindungsaufbau, welcher im GUI Browser interaktiv erfolgt, muss natürlich bei einem automatisierten Ablauf über einen Aktionsbaustein erfolgen.&lt;br /&gt;
Dazu gibt es in der SeleniumWebDriverLibrary im Ordner &amp;quot;&#039;&#039;Connection&#039;&#039;&amp;quot; verschiedene Bausteine, welche die Verbindungsparameter von verschiedenen Quellen erhalten:&lt;br /&gt;
* Connect&amp;lt;br&amp;gt;Dieser Baustein erhält die Verbindungsparameter über Eingangspins&lt;br /&gt;
* Connect from File&amp;lt;br&amp;gt;Hier werden die Einstellungen aus einer Datei (Anhang) gelesen (typischerweise im JSON Format)&lt;br /&gt;
* Connect from Spec&amp;lt;br&amp;gt;Die Verbindungsparameter werden in einem Dictionaryobjekt geliefert&lt;br /&gt;
* Reuse or Start Connection&amp;lt;br&amp;gt;Im Gegensatz zu obigen Bausteinen, welche immer eine neue Browserverbindung aufbauen (i.e. ein neues Browserfenster öffnen), wird dieser Baustein zunächst prüfen, ob bereits eine Verbindung besteht, und diese gegebenenfalls wiederverwenden. Dieser Baustein kann daher mehrfach (i.e. zu Beginn von Teilsequenzen) platziert werden, und damit die Teilsequenzen sowohl innerhalb eines komplexeren Gesamttests als auch &amp;quot;stand-alone&amp;quot;, d.h. einzeln ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Alle &amp;quot;Connect&amp;quot; Bausteine benötigen die Angabe eines &amp;quot;&#039;&#039;Verbindungsnamens&#039;&#039;&amp;quot;.&lt;br /&gt;
Dieser hat die Aufgabe, die Verbindung im weiteren Testverlauf zu identifizieren, wenn zwischen mehreren Verbindungen gewechselt wird, und zum Abbauen der Verbindung. &lt;br /&gt;
&lt;br /&gt;
Wenn Sie im GUI Browser im Elementbaum auf eine Verbindung klicken, erscheint in der rechten &amp;quot;Test&amp;quot; Kachel ein Connect Baustein mit entsprechend vorgelegten Parametern. Diesen können Sie bei Bedarf gleich in die Rekordersequenz übertragen, oder (besser) als separate Aktion speichern (es ist sinnvoll, den Verbindungsaufbau von den aufgezeichneten Teilsequenzen zu trennen; damit haben Sie es später leichter, andere Browser zu verwenden, die Parameter der Verbindung zu ändern und auch neue Teilsequenzen aufzuzeichnen oder zu modifizieren.&lt;br /&gt;
&lt;br /&gt;
Verbindungen mit komplexen Einstellungen werden typischerweise im Verbindungsdialog angelegt, und die Einstellungen von dort über die Menüfunktion &amp;quot;&#039;&#039;Sichern in Anhang/Datei&#039;&#039;&amp;quot; in einer Datei gesichert. So können Sie verschiedene Konfigurationen in einzelnen Dateianhängen in ihrer Testsuite oder auch außerhalb aufbewahren. Zum Verbinden verwenden Sie dann den Aktionsbaustein &amp;quot;[&#039;&#039;Connect From File&#039;&#039;]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Plugin-Einstellungen=&lt;br /&gt;
Wenn Sie eine bestimmte Browser-Installationen oder Driver standardmäßig als Voreinstellung verwenden möchten, können Sie diese in den Einstellungen des Plugins eintragen. Sie finden sie über das Menü unter dem Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot;. Einstellungen für spezifische Browser finden Sie unter den Unterpunkten &amp;quot;&#039;&#039;Beliebteste Browser&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;Andere Browser&#039;&#039;&amp;quot;.&lt;br /&gt;
Die dortigen Einstellungen gelten als Voreinstellung für jede Verbindung, es sei denn in einer konkreten Verbindungseinstellungen ist etwas anderes angegeben.&lt;br /&gt;
&lt;br /&gt;
===Ausführungsverzögerung für Chrome===&lt;br /&gt;
In manchen Fällen kann es bei Verwendung des Chrome-Browsers vorkommen, dass Bausteine mit Element-Aktionen, beispielsweise ein Klick, im Test erfolgreich durchlaufen, die eigentliche Aktion aber gar nicht ausgeführt wurde. Dies ist ein bekannter Fehler [https://github.com/MPDL/imeji-gui-testing/issues/37], [https://github.com/SeleniumHQ/selenium/issues/4075], der von Selenium bzw. chromedriver behoben werden muss.&lt;br /&gt;
&lt;br /&gt;
Der Fehler lässt sich verhindern, indem entweder der Klick über JavaScript aufgerufen wird&amp;amp;nbsp;(setzen Sie dazu im Klick-Baustein &#039;&#039;invokeDirectly&#039;&#039; auf &#039;&#039;true&#039;&#039;&amp;amp;nbsp;) oder vor der Aktion kurz gewartet wird. Die Ausführung über JavaScript hat den Nachteil, dass sie weniger nah am Klick eines echten Benutzers ist; beispielsweise funktionieren Klicks auf Elemente auch dann, wenn sie von anderen Elementen verdeckt werden (was bei einem &amp;quot;normalen&amp;quot;Klick nicht geht). &lt;br /&gt;
&lt;br /&gt;
Generell warten die Bausteine mit Element-Aktionen automatisch, bis das entsprechende Element verfügbar ist (existiert). In den hier beschriebenen Fällen reicht das aber nicht aus. Deshalb finden Sie in den Plugin-Einstellungen für Chrome die Einstellung &amp;quot;&#039;&#039;Ausführungsverzögerung&#039;&#039;&amp;quot;. Bei der Ausführung wird dann zwischen den Aktionen entsprechend lange gewartet. Falls bei Ihnen der beschriebene Fehler eintritt, können Sie diesen Wert erhöhen. Ein größerer Wert hat natürlich Auswirkung auf die Gesamtlaufzeit.&lt;br /&gt;
&lt;br /&gt;
=Recorder=&lt;br /&gt;
&lt;br /&gt;
Die folgende Beschreibung des Recorders gilt prinzipiell für alle von expecco unterstützten GUI Technologien. Verhalten und Bedienung sind bis auf kleine technologiebedingte Unterschiede für alle gleich.&lt;br /&gt;
&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung mit einem Browserfenster, kann der integrierte Recorder verwendet werden, um einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Für jeden Klick im Fenster wird eine Aktion aufgezeichnet. Weitere Aktionen stehen über das Menü zur Verfügung. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
Allgemeine Aktionen finden Sie entweder direkt in der Menüleiste oder dort im Browser-Werkzeuge-Menü (s.u.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Element-Werkzeugs in der Menüleiste (s.u.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion. Auf diese Weise ist es ebenfalls möglich, die Eingaben &#039;&#039;Backspace&#039;&#039;, &#039;&#039;Return&#039;&#039; und &#039;&#039;Tab&#039;&#039; aufzuzeichnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverRecorder.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Komponenten des Recorderfensters&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme Pausieren&#039;&#039;&#039;: Wenn die Kontrollleuchte rot ist, nimmt der Recorder auf. Durch Klicken können Sie die Aufnahme anhalten. Die Kontrolleuchte leuchtet dann grau. In diesem Zustand können Sie weiter Aktionen über das Recorder-Fenster ausführen, sie werden aber nicht aufgezeichnet. Klicken Sie erneut, um die Aufnahme weiterzuführen.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Browser. Dies wird nötig, wenn die Anzeige des Recorders nicht mit dem tatsächlichen Browserinhalt übereinstimmt. &lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Element-Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Es stehen alle Aktionen zur Verfügung, die auf ein bestimmtes Element ausgeführt werden. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst und das Element aus der Position bestimmt. Die nicht ausgewählten Aktionen sind jederzeit über einen Rechtsklick erreichbar. &lt;br /&gt;
#&#039;&#039;&#039;Browser-Werkzeuge&#039;&#039;&#039;: Aktionen die sich nicht auf bestimmte Elemente beziehen, wie Scrollen oder Aktionen auf die aktuelle URL oder den Titel, können hier ausgelöst werden.&lt;br /&gt;
#&#039;&#039;&#039;Seitennavigation&#039;&#039;&#039;: Aktionen zur Seitennavigation: &#039;&#039;eine Seite zurück&#039;&#039;, &#039;&#039;eine Seite vor&#039;&#039; und &#039;&#039;aktuelle Seite neu laden&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Alert-Behandlung&#039;&#039;&#039;: Wenn der Browser einen Alert anzeigt, klicken Sie auf diesen Button, um die Aktionen zur Alert-Behandlung auswählen zu können.&lt;br /&gt;
#&#039;&#039;&#039;Online Dokumentation&#039;&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Browsers. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot. Scrollen wird den Browser weitergeleitet, aber nicht aufgenommen.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots. Diese kann auch über Scrollen in der Anzeige bei gedrückt gehaltener Strg-Taste angepasst werden.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Hier werden Meldungen angezeigt, bspw. wenn eine Aktion nicht aufgenommen werden konnte. Die letzte Meldung wird solange angezeigt, bis sie über den Button rechts daneben geschlossen wird.&amp;lt;br&amp;gt;&#039;&#039;&#039;Fenster-Tabs&#039;&#039;&#039;: Ab expecco 23.1 werden oberhalb der Anzeige Tabs für jedes offene Fenster angezeigt, sobald eine Verbindung mehr als ein Browserfenster besitzt. Ob der Browser dieses als Tab oder in einem eigenen Fenster anzeigt, ist dabei egal. Über die Tabs im Recorder können Sie das aktuelle Fenster wechseln und diesen Wechsel auch aufzeichnen.&amp;lt;br&amp;gt;&#039;&#039;&#039;Frame-Kontext&#039;&#039;&#039;: Ab expecco 23.1 sehen Sie unterhalb der Anzeige, in welchem Frame-Kontext Sie sich gerade befinden (siehe dazu den Abschnitt [[#Eingebettete_Inhalte|Eingebettete Inhalte]]). Sie können auf die Einträge klicken, um in einen höheren Kontext zu wechseln und diesen Wechsel aufzuzeichnen. Falls Sie zusammengesetzte Pfade eingestellt haben, wird die Anzeige aktualisiert, wenn Sie ein eingebettetes Element ausgewählt haben.&lt;br /&gt;
&lt;br /&gt;
=Eingebettete Inhalte=&lt;br /&gt;
In HTML ist es möglich, auf einer Seite Inhalte einer anderen einzubinden. Das gängigste Elemente dafür ist ein Iframe (Inlineframe). Auf den Inhalt eines Iframes kann ebenfalls mit Selenium zugegriffen werden, allerdings muss dazu zuerst in diesen Kontext gewechselt werden. In der SeleniumWebDriverLibrary gibt es entsprechenden Bausteine, um in den Kontext eines Iframes zu wechseln, um in den Elternkontext zu wechseln und um zurück zum Standardinhalt, also dem obersten Kontext zu wechseln. Alle Element-Bausteine lösen die angelegten Pfade immer innerhalb des aktuellen Kontexts auf. Im GUI-Browser sehen Sie für eingebettete Inhalte ein zusätzliches Element, welches sie aufklappen können um dessen Elemente zu sehen.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Seit expecco 23.1 gibt es die Möglichkeit, auch zusammengesetzte Pfade an den Bausteinen zu verwenden, um direkt vom Standardinhalt auf den Inhalt eines Iframes zugreifen zu können. Dazu werden einfach der Pfad zum Iframe und der Pfad innerhalb des Iframe-Inhalts zu einem zusammengesetzt. Wichtig ist hierbei, dass beim Übergang keine Elemente ausgelassen werden dürfen, d.h. der vordere Teil muss mit dem Iframe-Element enden und der hintere Teil mit &#039;&#039;/body&#039;&#039; beginnen. Dazwischen dürfen die Pfade gekürzt werden und es ist natürlich auch möglich auf diese Art beliebig tief geschachtelte Elemente zu erreichen. An den Bausteinen können beide Techniken nach belieben verwendet werden, wichtig ist nur, dass die Pfade immer in dem Kontext aufgelöst werden, in dem sich Selenium gerade befindet.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie die kombinierten Pfade aufzeichnen, bzw. im GUI-Browser verwenden wollen, setzen Sie im Menü &#039;&#039;GUI Browser&#039;&#039; unter &#039;&#039;Aufzeichnung&#039;&#039; den Haken bei &#039;&#039;Zusammengesetzte Pfade aufzeichnen&#039;&#039;. Damit wird für eingebettete Elemente ein zusammengesetzter Pfad relativ zum aktuellen Kontext erzeugt und angezeigt, anstatt wie bisher nur innerhalb seines eigenen Kontexts. Außerdem können Sie diese Elemente auch direkt im Recorder ansprechen oder über Follow-Mouse finden.&lt;br /&gt;
&lt;br /&gt;
=Shadow-Elemente=&lt;br /&gt;
Shadow-DOMs sind eine Möglichkeit, um Teile einer Seite vom übrigen Dokument abzukapseln. Dabei werden an ein Element versteckte Shadow-Elemente angehängt. Eine ausführlichere Erklärung finden Sie zum Beispiel hier: [https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM Using shadow DOM - Web APIs | MDN].&lt;br /&gt;
&lt;br /&gt;
In der SeleniumWebDirverLibrary gibt es den Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039;, der die obersten Elemente liefert, die dann wie andere WebElemente verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
Da die Elemente versteckt sind, werden sie vom GUI-Browser nicht direkt angezeigt. Ab expecco 23.1 kann man allerdings im Kontextmenü der Elemente im GUI-Browser einen Haken setzen, dass Shadow-Elemente gesucht werden sollen. Beim Aktualisieren der Kinder eines Elements werden sie dann angezeigt, falls vorhanden, allerdings nicht, wenn der gesamte Baum aktualisiert wird. Wenn der Haken gesetzt ist, sind die Elemente auch im Recorder verfügbar.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Ähnlich wie die Elemente innerhalb eines Frames kann auch auf die Shadow-Elemente direkt über zusammengesetzte Pfade zugegriffen werden. Diese Pfade können dann direkt an den Bausteinen verwendet werden, sodass der Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039; nicht benötigt wird. Die Pfade haben die Form&lt;br /&gt;
 &amp;lt;host path&amp;gt;/shadowRoot/&amp;lt;shadow path&amp;gt;&lt;br /&gt;
wobei &#039;&#039;&amp;lt;host path&amp;gt;&#039;&#039; den Pfad zum Element angibt, an das der Shadow-DOM angehängt wurde, und &#039;&#039;&amp;lt;shadow path&amp;gt;&#039;&#039; der Pfad innerhalb des Shadow-DOMs zum gewünschten Element ist. &#039;/shadowRoot&#039; dient als Marker, dass an dieser Stelle der Wechsel in den Shadow-DOM erfolgt.&lt;br /&gt;
&lt;br /&gt;
=Authentifizierungs-Alerts=&lt;br /&gt;
Falls eine Webseite HTTP-Authentifizierung mit Basic Authentication verwendet, öffnet sich beim Laden der Seite ein Alert-Fenster zur Eingabe von Benutzernamen und Passwort. Dieses Fenster ist nicht direkt mit Selenium bedienbar. Im GUI-Browser wird es wie ein Alert angezeigt. Eine Ausnahme hierzu bildet Chrome, bei dem der Driver auf keine Anfrage antwortet solange der Dialog geöffnet ist. Das Plugin kann zu diesem Zeitpunkt insbesondere nicht feststellen, ob ein Authentifizierungs-Dialog geöffnet ist oder ob der Driver aus anderen Gründen nicht antwortet.&lt;br /&gt;
&lt;br /&gt;
Bei lokalen Verbindungen unter Windows kann eine Authentifizierung mittels Windows Access ausgeführt werden. Es gibt in der SeleniumWebDriverLibrary für einzelne Browsertypen spezifische Authentifizierungs-Bausteine sowie den Baustein &#039;&#039;Authenticate at Alert&#039;&#039;, der je nach Verbindung den entsprechenden Baustein ausführt. Für die verschiedenen Browser-Typen gibt es dabei unterschiedliche Einschränkungen:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Chrome:&#039;&#039;&#039; Die Anmeldedaten werden an ein Chromefenster geschickt, daher funktioniert es nur, wenn nicht mehrere geöffnet sind. Der Einzelbaustein hat für diesen Fall die Option, den Titel des Fensters anzugeben.&lt;br /&gt;
:&#039;&#039;&#039;Edge&#039;&#039;&#039;: Mit Microsoft Edge wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
:&#039;&#039;&#039;Firefox&#039;&#039;&#039;: Schickt die Anmeldedaten an ein Firefox-Dialogfenster und funktioniert daher nur, wenn es nicht mehrere gibt.&lt;br /&gt;
:&#039;&#039;&#039;Internet Explorer&#039;&#039;&#039;: Mit dem Internet Explorer wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
Als zusätzliche Option steht Ihnen auch eine Anmeldung über die URL zur Verfügung. Rufen Sie anstatt der Seite &amp;lt;nowiki&amp;gt;https://www.example.com&amp;lt;/nowiki&amp;gt; die URL &amp;lt;nowiki&amp;gt;https://user:password@www.example.com&amp;lt;/nowiki&amp;gt; auf. Wichtig ist hierbei, dass &#039;&#039;:&#039;&#039; und &#039;&#039;@&#039;&#039; nicht im Benutzernamen oder im Passwort auftauchen. Möglicherweise wird diese Methode nicht von jedem Browser unterstützt.&lt;br /&gt;
&lt;br /&gt;
Mithilfe des [[WindowsAutomation_Reference_2.0|WindowsAutomation2]]-Plugins ist es ebenfalls möglich, solch eine Anmeldung mit allen Browsertypen auszuführen.&lt;br /&gt;
&lt;br /&gt;
=Portierung alter Selenium-Tests=&lt;br /&gt;
Dieses Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Dieses basierte auf [https://www.seleniumhq.org/projects/remote-control/ Selenium RC], welches in Zukunft von den Browsern nicht mehr unterstützt wird. Der Nachfolger von Selenium RC ist [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver], auch &#039;&#039;Selenium 2&#039;&#039; genannt. Ebenso ist auch das Aufzeichnen von Tests mit [https://www.seleniumhq.org/projects/ide/ Selenim IDE] veraltet, da das Plugin von neueren Browsern nicht mehr unterstützt wird. Das Selenium WebDriver Plugin verwendet stattdessen einen eigenen [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
Tests, die mit dem alten Selenium Web Test Plugin erstellt wurden und die alte SeleniumLibrary verwenden, können über Selenium WebDriver ausgeführt werden. Setzen Sie dazu in den Plugin-Einstellungen von &amp;quot;&#039;&#039;Webtest Legacy (Selenium)&#039;&#039;&amp;quot; den Haken bei &amp;quot;&#039;&#039;WebDriver für die Ausführung verwenden&#039;&#039;&amp;quot;. Für die wichtigsten Funktionen wurde Wrapper bzw. umsetzende Funktionen erstellt, um die Migration möglichst problemlos zu gestalten.&lt;br /&gt;
Testen Sie dann, ob die Tests wie bisher ablaufen. Für den überwiegenden Teil der Bausteine sollte es dabei keine Probleme geben. Einige wenige Aktionen werden in der WebDriver Version nicht mehr unterstützt oder verhalten sich unterschiedlich. Es ist auch nicht garantiert, daß die Emulation der alten Schnittstelle auf Dauer von Selenium unterstützt werden. Wenn möglich sollten Sie daher über kurz oder lang die Testfälle umschreiben.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*&#039;&#039;&#039;Scrollbalken lassen sich im Recorder nicht bedienen&#039;&#039;&#039;&lt;br /&gt;
:Der Scrollbalken des Browsers, der automatisch angezeigt wird, wenn eine Seite größer als das Browserfenster ist, ist kein bedienbares Webelement. Scrollen um einen bestimmten Betrag ist in einem Test selten sinnvoll, wenn die Größe des Browserfensters nicht festgelegt ist. Verwenden Sie stattdessen den Baustein &amp;lt;code&amp;gt;[Web] Scroll Element into View&amp;lt;/code&amp;gt;, um ein entsprechendes Element in den sichtbaren Bereich zu scrollen. Der Klick-Baustein, den der Recorder standardmäßig verwendet, führt diese Aktion bereits automatisch mit aus (&amp;lt;code&amp;gt;[WebElement] Click (Scroll Element into View)&amp;lt;/code&amp;gt;). Wenn Sie im Recorder-Fenster scrollen, wird dies automatisch auf den Browser übertragen, aber nicht aufgezeichnet. Falls Sie tatsächlich um einen bestimmten Betrag scrollen möchten, gibt es bei den Browser-Aktionen einen Eintrag dafür und weitere Bausteine in der SeleniumWebDriverLibrary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein schlägt fehl, wenn Element zu spät sichtbar wird&#039;&#039;&#039;&lt;br /&gt;
:Alle Bausteine, die einen Elementpfad verwenden, haben automatisch eingebaut, dass sie warten, bis ein entsprechendens Element auftaucht. Es gibt aber Fälle, in denen ein Element zwar bereits da, aber noch nicht sichtbar ist. Bei einem Klick auf das Element bekommen Sie dann einen Fehler. Mögliche Fehler in diesem Zusammenhang sind &amp;lt;code&amp;gt;org.openqa.selenium.ElementNotInteractableException: element not interactable&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;. Verwenden Sie dann vor einer Interaktion mit dem Element den Baustein &amp;lt;code&amp;gt;[Web] Wait for Visibility of Element&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[Web] Wait for Element to Be Clickable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt; kann mit dem Chrome-Browser auftreten. In diesem Fall ist das verwendete Element nicht sichtbar. Lesen Sie dazu den Punkt oben. Der Fehler ist auch im Zusammenhang mit Elementen in einer Dropdown-Liste bekannt, d.h. bei einem Klick oder dem Bewegen der Maus auf ein &amp;lt;nowiki&amp;gt;&amp;lt;option&amp;gt;&amp;lt;/nowiki&amp;gt;-Element innerhalb eines &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Elements. Diese Elemente sind prinzipiell nicht klickbar. Verwenden Sie stattdessen einen passenden &amp;lt;code&amp;gt;[Web] Select&amp;lt;/code&amp;gt;-Baustein mit dem &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Stale Element Reference Exception&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein WebElement verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator, um das Element neu zu holen. Eventuell liegt es auch daran, dass sich der Test momentan in einem anderen Frame-Kontext befindet als das Element. Wenn Sie [[#Zusammengesetzte_Pfade|zusammengesetzte Pfade]] verwenden, sollte das Element selbst in den richtigen Kontext wechseln, bevor Aktionen darauf ausgeführt werden.&lt;br /&gt;
:In seltenen Fällen kann der Fehler auch in expecco selbst auftreten, wenn an irgendeiner Stelle im GUI-Browser oder Recorder ein entsprechendes WebElement verwendet wird. Sie sollten dann abbrechen können und es nochmal versuchen. Sollte der Fehler bestehen bleiben, wechseln Sie in den Default Content und laden Sie den Baum im GUI-Browser neu.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein läuft erfolgreich, aber ohne Auswirkungen&#039;&#039;&#039;&lt;br /&gt;
:Dieser Fall kann mit Chrome auftreten. Das Element ist verfügbar, die Aktion wirft keinen Fehler, aber es wird nichts ausgeführt. In der Regel hilft es, vor der Ausführung kurz zu warten, siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ausführungen mit Chrome sind langsamer&#039;&#039;&#039;&lt;br /&gt;
:Um ein Problem bei der Ausführung mit Chrome zu beheben, ist in den Plugin-Einstellungen für Chrome eine Verzögerung definiert. Überprüfen Sie, ob dieser Wert eventuell zu hoch eingestellt ist; siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldungen wie: &amp;quot;org.openqa.selenium.InvalidArgumentException: Expected &amp;quot;handle&amp;quot; to be a string...&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
:Dies passiert wenn der Driver nicht (mehr) zum Browser passt. Lesen Sie dazu obiges Kapitel &amp;quot;[[#WebDriver aktualisieren|WebDriver aktualisieren]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Key Chords mit Shortcuts funktionieren nicht&#039;&#039;&#039;&lt;br /&gt;
:Das Drücken mehrerer Tasten gleichzeitig lässt sich als Key Chord simulieren. Dadurch können auch Shortcuts eingegeben werden. Allerdings funktionieren hier nicht alle Eingaben, da diese nur an den Seiteninhalt und nicht an den Browser selbst gehen. Kombinationen wie &#039;&#039;Strg + t&#039;&#039; um einen neuen Browsertab zu öffnen, funktionieren daher vermutlich nicht, &#039;&#039;Strg + a&#039;&#039; oder &#039;&#039;Strg + c&#039;&#039; sollten hingegen möglich sein.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Zusätzliche Window Handles mit Opera&#039;&#039;&#039;&lt;br /&gt;
:Der Opera-Browser liefert mehr Window Handles als Tabs bzw. Fenster geöffnet sind. Diese kommen von Opera-internen Funktionen wie dem Schnellstart (&#039;&#039;Speed Dial&#039;&#039;) oder der &#039;&#039;Better Address Bar Experience&#039;&#039; (BABE), die zwar im Browserfenster eingebunden, aber nicht als Tab angezeigt werden. Zu diesen Tabs kann zwar mit den entsprechenden Bausteinen gewechselt werden, es sind dann aber nicht alle Aktionen möglich, die für die normalen Tabs zur Verfügung stehen. Sie können zum Beispiel nicht geschlossen werden und man bekommt von ihnen kein Bild. Am besten wechselt man daher gar nicht erst in diese Kontexte. Seien Sie also vorsichtig, wenn Sie anhand des Index zu einem Tab wechseln wollen, da sich die Opera-Tabs zwischen den anderen befinden und der Index ein anderer als für die anderen Browser sein kann.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Chrome: Wähle deine Suchmaschine&#039;&#039;&#039;&lt;br /&gt;
:Neuere Chromeversionen zeigen nach dem Starten ein [https://www.google.com/chrome/choicescreen/ Overlay], bei dem man die verwendete Suchmaschine auswählen soll. Die Entscheidung wird normalerweise im Benutzerprofil gespeichert. Wenn für die Verbindung aber nicht explizit ein Chrome-Profil angegeben wird, hat man bei jedem Verbindungsaufbau ein leeres Profil und es wird immer nachgefragt.&lt;br /&gt;
&lt;br /&gt;
:In vielen Fällen kann der Test auch trotz des Overlays im Hintergrund ablaufen. Das Overlay gilt aber wie ein Tab bzw. Fenster; so liefert beispielsweise vom Baustein &#039;&#039;[Web] Get Window Handles&#039;&#039; einen Handle dafür und es kann auch dorthin gewechselt werden. Es gibt aber auch Möglichkeiten es loszuwerden:&lt;br /&gt;
:* &#039;&#039;--disable-search-engine-choice-screen&#039;&#039;: In den [[#Erweiterte_Einstellungen|erweiterten Einstellungen]] kann man bei den Optionen &amp;lt;code&amp;gt;--disable-search-engine-choice-screen&amp;lt;/code&amp;gt; angeben, dann kommt das Overlay nicht.&lt;br /&gt;
:* &#039;&#039;Auswählen&#039;&#039;: Sie können Ihren Test auch so erweitern, dass zu Beginn eine Suchmaschine ausgewählt und damit das Overlay geschlossen wird. Dabei müssen Sie zwei Dinge beachten. Zum einen müssen Sie zuerst mit einem &#039;&#039;Switch to Window&#039;&#039;-Baustein dorthin wechseln (z.B. mit Index &#039;&#039;2&#039;&#039; oder leerem Titel) und am Ende auch wieder zurück zu Ihrem ursprünglichen Tab. Zum anderen sind interessanten Elemente des Overlays [[#Shadow-Elemente|Shadow-Elemente]] und werden daher im GUI-Browser nicht direkt angezeigt.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Firefox: &amp;lt;code&amp;gt;Process unexpectedly closed with status 0&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Fehlerbild: Die Verbindung zum Firefox-Browser kommt nicht zustande mit der Fehlermeldung &amp;lt;code&amp;gt;org.openqa.selenium.WebDriverException: Process unexpectedly closed with status 0&amp;lt;/code&amp;gt;. Der Browser öffnet sich dann aber doch ohne dass es eine Verbindung in expecco gibt.&lt;br /&gt;
:Eine bekannte Ursache dafür ist, dass der Browser dabei zum ersten Mal nach einem Update gestartet wird, womit der Browser im automatisierten Zustand nicht zurecht kommt. Beim zweiten Versuch sollte der Fehler dann nicht mehr auftreten. Um den Fehler zu verhindern, achten Sie darauf, den Browser nach einem Update immer zuerst normal zu starten.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29681</id>
		<title>Selenium WebDriver Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29681"/>
		<updated>2024-08-05T13:34:15Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* FAQ */ Chrome: Wähle deine Suchmaschine&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Selenium_WebDriver_Plugin/en|English Version]]&lt;br /&gt;
=Achtung=&lt;br /&gt;
Das Webtest Selenium WebDriver Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Zur Automatisierung wird [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver] verwendet (Driver für gängige Browser werden von uns mitgeliefert), der das bisher verwendete Selenium RC ersetzt. Dies wurde einerseits notwendig, da die SeleniumRC Schnittstelle von neuen Browsern nicht mehr unterstützt wird, andererseits, sinnvoll, da auch andere UI Technologien mit diesem Protokoll angesprochen werden können. &lt;br /&gt;
&lt;br /&gt;
Sie können dieses Protokoll nur noch mit älteren Browsern verwenden, und wir empfehlen dringend, auf die neue Version umzusteigen. &amp;lt;br&amp;gt;Hinweise zur Migration älterer Testsuiten finden Sie [[#Portierung_alter_Selenium-Tests | unten]].&lt;br /&gt;
&lt;br /&gt;
=Einleitung=&lt;br /&gt;
Mit dem Selenium WebDriver Plugin können Sie Tests von Webapplikationen erstellen oder auch diese automatisieren (*). Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests oder automatisierten Browseraktionen unterstützt. Zudem ist damit das Aufzeichnen von Abläufen möglich.&lt;br /&gt;
&lt;br /&gt;
(*) tatsächlich gibt es auch WebDriver-Schnittstellen um z.B. Windows-Apps oder OPS-Fenster zu manipulieren. Insofern gibt es für dieses Plugin weitere Einsatzbereiche.&lt;br /&gt;
&lt;br /&gt;
=Einstellungen=&lt;br /&gt;
Das Plugin verwendet die Java-Bridge und benötigt daher eine Java-Installation. Sie können diese in den Einstellungen unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Java Bridge&#039;&#039; angeben. Wichtig ist hier das Feld &#039;&#039;Pfad zur Java-Installation&#039;&#039;, wo Sie ein JDK oder JRE angeben können. Ist nichts angegeben, versucht expecco java im PATH zu finden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Für das Selenium WebDriver Plugin selbst gibt es ebenfalls Einstellungsmöglichkeiten, die Sie unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Webtest (Selenium WebDriver)&#039;&#039; finden. Hier können Sie zum Beispiel die Adresse zu einem remote laufenden Selenium-Server angeben oder eine andere Jar-Datei für Selenium angeben. Einstellungen zu den verschiedenen Browser-Typen teilen sich auf die Unterseiten &#039;&#039;Beliebte Browser&#039;&#039; und &#039;&#039;Andere Browser&#039;&#039; auf. Dort können Sie den Pfad zur Browser-Ausführungsdatei oder zum Webdriver angeben, der verwendet werden soll. Diese Felder können Sie alle leer lassen, expecco wird dann automatisch danach suchen.&lt;br /&gt;
&lt;br /&gt;
=Browser-Unterstützung=&lt;br /&gt;
Das Plugin unterstützt die Browser Chrome/Chromium, Edge, Firefox, Internet Explorer und Opera. &lt;br /&gt;
&amp;lt;br&amp;gt;Safari unter OSX muss zumindest in der Version 10 vorliegen und OSX muss mindestens die El Capitan Version sein.&lt;br /&gt;
Zur Kommunikation wird die WebDriver Schnittstelle verwendet; somit kann der getestete Browser sowohl lokal als auch auf einem entfernten Rechner laufen.&lt;br /&gt;
&lt;br /&gt;
Da inzwischen eine Vielzahl von weiteren Browsen, Geräten und graphischen Oberflächen eine WebDriver Schnittstelle anbieten, können auch diese - z.T. mit eingeschränktem Funktionsumfang - über diese automatisiert werden. So gibt es z.B. auch Schnittstellen für Windows Mobilgeräte oder Desktopanwendungen.&lt;br /&gt;
&lt;br /&gt;
== WebDriver aktualisieren==&lt;br /&gt;
Für jeden Browsertyp gibt es einen Driver, über den das Starten und Ansteuern der Browserfenster funktioniert. Für die wichtigsten Browser finden sich im Lieferumfang aktuelle Driverversionen. Da die Browser fortlaufend aktualisiert werden, teilweise sogar automatisch, müssen Sie früher oder später neue Driverversionen herunterladen. Legen Sie diese dann in Ihrem expecco-Installationsverzeichnis bei den anderen Versionen ab, und zwar unter:&lt;br /&gt;
 &amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib/XXX&amp;lt;/code&amp;gt;&lt;br /&gt;
(unter Microsoft Windows Betriebssystemen mit &amp;quot;\” anstatt &amp;quot;/&amp;quot;), wobei &amp;quot;XXX&amp;quot; für das Betriebssystem steht (Windows, Linux, OSX etc.).&lt;br /&gt;
&lt;br /&gt;
Im Verbindungsdialog warnt expecco, wenn eine Driverversion nicht zur Browserversion passt. In manchen Fällen kann das aber auch nur daran liegen, dass  diese Version zum Zeitpunkt der Auslieferung noch nicht bekannt war. Manche Kombinationen können trotz der Warnung funktioniert, aber das können wir im Einzelfall nicht garantieren.&lt;br /&gt;
&lt;br /&gt;
Daher können Sie bei einer solchen Warnung immer die Option &amp;quot;&#039;&#039;Diese Warnung nicht mehr anzeigen&#039;&#039;&amp;quot; anwählen, damit diese Driver-Browser-Versionskombination in ihren Settings als &amp;quot;kompatibel&amp;quot; vermerkt wird, und in Zukunft nicht mehr gemeldet wird. Dies sollten Sie aber nur machen, wenn Sie sicher sind, dass Ihre Tests nach wie vor korrekt ausgeführt werden. Da wir hier selbst bisweilen auf Kompatibilitätsprobleme stoßen, und nicht immer gleich klar ist, woran es liegt, empfehlen wir aber den Driver zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
Für Chrome und Microsoft Edge, bei denen es für jede neue Browserversion auch eine neue Driverversion gibt, finden Sie im Verbindungsdialog einen Button, um mit expecco die passende Version herunterzuladen.&lt;br /&gt;
&lt;br /&gt;
Neuere Versionen der Driver bekommen Sie an folgenden Adressen:&lt;br /&gt;
{|&lt;br /&gt;
|Chrome/Chromium&lt;br /&gt;
|[https://sites.google.com/chromium.org/driver/ ChromeDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Edge&lt;br /&gt;
|[https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ Microsoft WebDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|[https://github.com/mozilla/geckodriver/releases GeckoDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|[https://selenium-release.storage.googleapis.com/index.html IEDriverServer]&lt;br /&gt;
|-&lt;br /&gt;
|Opera&lt;br /&gt;
|[https://github.com/operasoftware/operachromiumdriver/releases OperaDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|[https://webkit.org/blog/6900/webdriver-support-in-safari-10 Safari Support]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Laden Sie sich eine passende Version herunter und legen Sie sie im oben genannten Verzeichnis an der entsprechenden Stelle ab. Expecco wird sie dann finden und verwenden. &amp;lt;!-- Sie können den Namen der Datei erweitern, um mehrere Versionen nebeneinander verwenden zu können. --&amp;gt; Alternativ können Sie auch in expecco den Pfad zu einem Driver angeben, entweder im [[#Erweiterte_Einstellungen | Verbindungseditor]] oder in den [[#Plugin-Einstellungen | Plugin-Einstellungen]].&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Bitte verifizieren Sie, daß die Version des Drivers kompatibel ist mit der des Browsers. Im Zweifel suchen Sie nach der Versionshistorie (z.B. für Chrome: https://chromedriver.storage.googleapis.com/2.25/notes.txt).&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Für den Internet Explorer ist zu beachten, dass der geschützte Modus für alle Zonen gleich eingestellt sein muss, damit eine Verbindung möglich ist. (im Internet Explorer: &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Internetoptionen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Sicherheit&#039;&#039;&amp;quot; öffnen, und bei allen 4 Zonen &amp;quot;geschützter&amp;quot; Bereich gleich einstellen; ansonsten kommen beim Verbindungsaufbau Fehler- und Warndialoge). Siehe außerdem die [https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration erforderliche Konfiguration] zur Verwendung des InternetExplorerDrivers.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Das Plugin verwendet für einige Funktionen JavaScript. Stellen Sie daher sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist, insbesondere wenn Sie den GUI-Browser oder den Recorder verwenden wollen. Das Ausführen von Tests ist auch ohne JavaScript möglich, solange keine Aktionen verwendet werden, welche JavaScript benötigen oder explizit ausführen.&amp;lt;br&amp;gt;Sollten Sie einen Fehler der Art &amp;quot;&amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: Error executing JavaScript&amp;lt;/code&amp;gt;&amp;quot; bekommen, stellen Sie sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist und Browser- und zugehörige WebDriver-Version kompatibel sind.&lt;br /&gt;
&lt;br /&gt;
= Headless Browser =&lt;br /&gt;
Mit &amp;quot;&#039;&#039;Headless&#039;&#039;&amp;quot; bezeichnet man eine Anwendung, welche ohne Bedienoberfläche abläuft. Einige der Browser unterstützen einen &amp;quot;headless&amp;quot; Modus,  bei dem kein Browserfenster angezeigt wird. Der Browser operiert dabei in einem &amp;quot;unsichtbaren Fenster&amp;quot; führt aber alle Operationen aus, und liefert auch die selbe Elementhierarchie.&lt;br /&gt;
Bei einigen Browsern sind allerdings die Screenshot (Bild vom Fenster bzw. von Elementen) eingeschränkt bzw. gar nicht verfügbar.&amp;lt;br&amp;gt;Den &amp;quot;headless&amp;quot; Modus können Sie beim Verbindungsaufbau in den &amp;quot;&#039;&#039;Advanced Settings&#039;&#039;&amp;quot; angeben.&lt;br /&gt;
&lt;br /&gt;
= HTML Unit Browser =&lt;br /&gt;
Bei diesem &amp;quot;&#039;&#039;Pseudobrowser&#039;&#039;&amp;quot; handelt es sich um eine weitere &amp;quot;&#039;&#039;headless&#039;&#039;&amp;quot; Variante, welche ganz ohne Renderengine operiert, und lediglich die Elementhierarchie sowie Javascript unterstützt. Sein Verhalten kann stark von dem &amp;quot;echter&amp;quot; Browser abweichen.&lt;br /&gt;
&lt;br /&gt;
Diesen Browsertyp können Sie verwenden, wenn ihr Test das Verhalten des Webservices (also der Servierseite) betrifft, und nicht das Verhalten der Anwendung im Browser (End-User-Experience) im Fokus hat. Zum Beispiel kann der &amp;quot;HTML Unit Browser&amp;quot; zum Generieren von Last oder gleichzeitigen Aktionen gegenüber dem Server dienen.&lt;br /&gt;
Da sich dieser Browser im Verhalten z.T. stark von dem echter Browser unterscheidet sollte er nur (wenn überhaupt) in besonderen Fällen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
= Schneller Einstieg =&lt;br /&gt;
== Browser öffnen / verbinden ==&lt;br /&gt;
* Starten Sie expecco&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Neue Testsuite&#039;&#039;&amp;quot;&lt;br /&gt;
* Klicken Sie auf das GUI-Browser Symbol ([[Datei:GUIBrowser.png|24px]])&lt;br /&gt;
* Es erscheint der GUI-Browser in einem neuen Reiter&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; und wählen Sie &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot; aus. Dann erscheint der [[#Verbindungseditor | Verbindungsdialog]] (Details siehe unten)&lt;br /&gt;
* Im Verbindungsdialog geben Sie die zu testende Webseite ein (z.B. &amp;quot;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.myHost.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;) und wählen den Browsertyp (z.B. &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;firefox&amp;lt;/code&amp;gt;&amp;quot;) aus&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot;&lt;br /&gt;
* Ein Browser wird nun automatisch gestartet, und die Seite angezeigt.&lt;br /&gt;
* Sobald die Verbindung steht, wird im GUIBrowser die Seitenstruktur als Baum angezeigt, und im rechten Diagramm-Fenster erscheint ein passender Verbindungsbaustein. Dieser wird nicht automatisch aufgezeichnet, da man diesen normalerweise nicht in jeder aufgezeichneten Sequenz haben will (mehr dazu unten).&lt;br /&gt;
&lt;br /&gt;
== Recording aufnehmen ==&lt;br /&gt;
* Klicken Sie auf das Recording Symbol im GUI-Browser.&lt;br /&gt;
[[Datei:Recording_Start.png | 200px]]&lt;br /&gt;
* Ein Recorderfenster erscheint (eine Beschreibung der Bedienelemente finden Sie unten)&lt;br /&gt;
* Sie zeichnen nun direkt im Rekorder auf.&amp;lt;br&amp;gt;&lt;br /&gt;
* Klicks werden je nach Einstellung als Klick, Mausbewegung, Drag&amp;amp;Drop etc. aufgezeichnet.&amp;lt;br&amp;gt;Während der Aufzeichnung können Sie zwischen diesen Werkzeugen wechseln:&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Recorder_Werkzeuge.png | 300px]]&lt;br /&gt;
* die aufgezeichneten Aktionen werden im Tab &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; dargestellt. Sie können dort noch bearbeitet werden.&lt;br /&gt;
* Zum Beenden der Aufzeichnung klicken Sie entweder auf den &amp;quot;&#039;&#039;Stop Recording&#039;&#039;&amp;quot; Knopf im GUI Browser, oder schließen das Rekorderzenster. Es ist auch möglich, das Aufzeichnen temporär zu Pausieren, indem sie im Rekorder auf den &amp;quot;&#039;&#039;Aufnahme&#039;&#039;&amp;quot;-Knopf oben links drücken.&lt;br /&gt;
* Nach dem Aufzeichnen können sie die Sequenz un ihre Testsuite als Testfall oder Teilsequenz übernehmen.&lt;br /&gt;
&lt;br /&gt;
== Aufgezeichnete Aktion wiedergeben ==&lt;br /&gt;
&lt;br /&gt;
* Im Reiter &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; kann die aktuelle Aufzeichnung sofort wiedergegeben werden (&amp;quot;&#039;&#039;Play&#039;&#039;&amp;quot;-Knopf drücken)&amp;lt;br&amp;gt;Beachten Sie, daß ihre Webseite üblicherweise im gleichen Zustand sein sollte - gegebenenfalls sollten Sie also den &amp;quot;&#039;&#039;Back&#039;&#039;&amp;quot;-Knopf oder eine andere Navigation anwenden, um dies sicher zu stellen.&lt;br /&gt;
* Die Sequenz kann bearbeitet werden. Dazu können entweder weitere Aktionen aufgenommen werden, oder zusätzliche Aktionen entweder via Drag&amp;amp;Drop oder über das Kontextmenü (bzw. &amp;lt;kbd&amp;gt;&amp;lt;CTRL-N&amp;lt;/kbd&amp;gt;) angelegt werden. Häufig werden zusätzliche Delay- oder Verifikations-Bausteine benötigt, die sie hiermit an geeigneter Stelle einfügen können.&lt;br /&gt;
&lt;br /&gt;
=Verbindungsaufbau=&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Verbindungsdialog&amp;quot;&amp;gt;Verbindungseditor==&lt;br /&gt;
Mit dem Verbindungseditor werden Verbindungen definiert, geändert und aufgebaut. Sie erreichen ihn, indem Sie den GUI-Browser öffnen und dort auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; klicken und dann &amp;quot;&#039;&#039;Selenium Testing (WebDriver)&#039;&#039;&amp;quot; auswählen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverConnectDialog.png]]&lt;br /&gt;
&lt;br /&gt;
#&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;: Öffnet einen Anhang im expecco Projekt mit Verbindungseinstellunge. Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen aus Datei&#039;&#039;: Öffnet eine gespeicherte Einstellungsdatei (*.csf). Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in JSON-Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen im JSON-Format als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in Datei speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern.&lt;br /&gt;
#&#039;&#039;Versionsinfo&#039;&#039;: Zeigt ein Fenster mit den verwendeten Versionen des Selenium-Servers, des ausgewählten Browser und dessen Driver an.&lt;br /&gt;
#&#039;&#039;Online-Dokumentation&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;Verbindungsname&#039;&#039;: Tragen Sie hier den Namen ein, unter dem die Verbindung im GUI-Browser angezeigt werden soll. (Optional)&lt;br /&gt;
#&#039;&#039;Browsertyp&#039;&#039;: Wählen Sie hier aus, welchen Browser Sie verwenden möchten. Stellen Sie sicher, dass dieser installiert ist und die Version des verwendeten Drivers zur Browserversion passt.&lt;br /&gt;
#&#039;&#039;URL&#039;&#039;: Tragen Sie hier die URL ein, die zu Beginn aufgerufen werden soll. Sie können das Feld auch frei lassen, dann wird ein leeres Browser-Fenster geöffnet. Um eine lokale Datei zu öffnen, verwenden Sie das Schema &amp;quot;&amp;lt;code&amp;gt;file://&amp;lt;/code&amp;gt;&amp;quot;, z.B. &amp;quot;&amp;lt;code&amp;gt;file:///C:/Users/admin/Desktop/index.html&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
#&#039;&#039;Erweiterte Ansicht&#039;&#039;: Wechselt zur Ansicht für die Eingabe von [[#Erweiterte Einstellungen|erweiterten Einstellungen]].&lt;br /&gt;
#&#039;&#039;Informationen zum gewählten Browser&#039;&#039;: Hier wird der ausgewählte Browsertyp kurz vorgestellt.&lt;br /&gt;
#&#039;&#039;Informationen zu den Einstellungen&#039;&#039;: Hier wird angezeigt, welche Selenium-, Browser- und Driver-Version mit den aktuellen Einstellungen verwendet wird. Falls Sie [[#Erweiterte Einstellungen|erweiterten Einstellungen]] gesetzt haben, werden diese hier ebenfalls aufgelistet.&lt;br /&gt;
&lt;br /&gt;
===Warnung &amp;amp;uuml;ber m&amp;amp;ouml;gliche Inkompatibilit&amp;amp;auml;t ===&lt;br /&gt;
Manche Browser benötigen einen versionsspezifischen Webdriver, da die verwendeten Kommunikationsprotokolle unterschiedlich sein können. &lt;br /&gt;
&lt;br /&gt;
Da regelmässig neue Browserversionen erscheinen, und damit einhergehend auch neue Versionen des zug. Webdrivers benötigt werden, kann. es sein, dass die mit expecco mitgelieferten Webdriver nicht mehr zur aktuellen Browserversion passen. Dies trat in der Vergangenheit insbes. beim Chromebrowser mehrfach auf.&lt;br /&gt;
 &lt;br /&gt;
Um auf eventuelle Probleme hinzuweisen hält expecco intern eine Liste von Paaren der von exept bereits getesteten Browser- zu Webdriverversion. Falls ihr Browser aktueller ist, und nicht in der Liste enthalten ist, erscheint eine Warnung im Infobereich.&lt;br /&gt;
&lt;br /&gt;
Diese erscheint nur zu Ihrer Information - in den meisten Fällen funktioniert die Interaktion mit dem Browser auch dann. Allerdings ist es in jedem Fall sinnvoll, den Driver zu aktualisieren, um solche Probleme auszuschliessen.&lt;br /&gt;
Wenn die Kombination ohne Probleme läuft, ist es möglich, die aktuelle Kombination in die Liste einzutragen (drücken Sie dazu auf &amp;quot;Diese Kombination ist in Ordnung&amp;quot;). Dann erschient der Warndialog nicht mehr.&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Einstellungen===&lt;br /&gt;
Neben dem zu verwendenden Browser und der Start-URL kann man noch weitere Einstellungen für eine Verbindung vornehmen. Wechseln Sie dazu im Verbindungsmenü die Ansicht über den entsprechenden Menü-Eintrag. Je nachdem, welchen Browsertypen Sie ausgewählt haben, bekommen Sie andere Eingabefelder.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Remote Server&#039;&#039;: Falls der Browser auf einem entfernten Rechner gestartet werden soll, starten Sie dort einen Selenium-Server und geben Sie dessen Adresse in diesem Feld an. Natürlich können Sie auch eine lokale Adresse angeben, wenn nicht automatisch ein Selenium-Server gestartet werden soll. Lesen Sie hierzu auch den nächsten Abschnitt [[#Remote-Verbindungen|Remote-Verbindungen]].&lt;br /&gt;
*&#039;&#039;Binary&#039;&#039;: Geben Sie den Pfad zum Binary des ausgewählten Browsers an, wenn dieser nicht automatisch von Selenium gefunden wird oder Sie eine weitere Version installiert haben.&lt;br /&gt;
*&#039;&#039;Driver&#039;&#039;: Zu jedem Browser wird ein spezieller Driver zur Automatisierung benötigt. Für neue Versionen des Browsers braucht man häufig auch eine neue Version des entsprechenden Drivers. Wenn Sie nicht den von expecco installierten Driver verwenden wollen, geben Sie hier einen entsprechenden Pfad an.&lt;br /&gt;
*&#039;&#039;Firefox Profile&#039;&#039;: Für Firefox gibt es zusätzlich die Möglichkeit, ein Profil bzw. Template anzugeben, das spezifische Einstellungen enthält. Wenn keines angegeben wird, wird für jede Verbindung ein neues, leeres Profil angelegt.&lt;br /&gt;
*&#039;&#039;Capabilities&#039;&#039;: Für Selenium-Verbindungen sind einige Capabilities definiert, mit denen sich Verbindungs-Eigenschaften oder auch das Browserverhalten festlegen lassen. &lt;br /&gt;
Solche Capabilities können Sie sie in diesem Feld angeben. Schreiben Sie dazu &#039;&#039;&amp;lt;capability name&amp;gt;: &amp;lt;value&amp;gt;&#039;&#039; oder &#039;&#039;&amp;lt;capability name&amp;gt; = &amp;lt;value&amp;gt;&#039;&#039;; jeweils ein Eintrag pro Zeile. Außerdem können Sie hier auch Eigenschaften für den Firefox-Browser setzen. Die Eingabe hierfür erfolgt wie für die Capabilities, nur dass sie dem Namen der Eigenschaft ein &#039;&#039;$&#039;&#039; voranstellen müssen.&lt;br /&gt;
&lt;br /&gt;
:Angegebene Capabilities werden durch die Methode &#039;&#039;setCapability()&#039;&#039; gesetzt. Insbesondere bei der Verwendung von Chrome gibt es einige Einstellungsoptionen, die sich nicht mit dieser Methode setzen lassen, sondern beispielsweise über &#039;&#039;setExperimentalOption()&#039;&#039; angegeben werden müssen. Zu diesem Zweck haben Sie außerdem die Möglichkeit, in diesem Feld einen Methodenaufruf mit Werten anzugeben. Diese Methode wird dann auf das entsprechende Options- bzw. Capabilities-Objekt angewandt. Um die Struktur der Eingabe von normalen Capabilities beizubehalten, müssen Sie am Ende noch &#039;&#039;:&#039;&#039; oder &#039;&#039;=&#039;&#039; setzen, aber keinen Wert danach. Beispiel: &#039;&#039;setExperimentalOption(“useAutomationExtension”, false)=&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Lokale-Verbindungen==&lt;br /&gt;
Um einen Browser auf ihrer lokalen Maschine zu starten, werden lediglich die Felder &amp;quot;&#039;&#039;URL&#039;&#039;&amp;quot; sowie &amp;quot;&#039;&#039;Browsertyp&#039;&#039;&amp;quot; benötigt. Als Voreinstellung für den Browser wird &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; erscheinen.&lt;br /&gt;
&lt;br /&gt;
==Remote-Verbindungen==&lt;br /&gt;
Um einen Browser auf einem entfernten Rechner zu starten, müssen Sie zunächst den Selenium-Server und die benötigten Driver auf diesen Rechner kopieren. Auf dem Zielrechner muss Java installiert sein. Sie finden die Dateien in Ihrer expecco-Installation unter &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib&amp;lt;/code&amp;gt;&amp;quot;. Sie können sich auch von [https://www.selenium.dev/downloads/ Selenium] eine aktuelle Version herunterladen.&lt;br /&gt;
&amp;lt;br&amp;gt;Starten Sie dann den Selenium-Sever (auf dem entfernten Rechner) mit:&lt;br /&gt;
 java -jar selenium-server-standalone-3.141.59.jar&lt;br /&gt;
(die Versionsnummer wird in Ihren Fall eine andere sein)&lt;br /&gt;
&lt;br /&gt;
Standardmäßig wird der Server dann auf dem Port 4444 Verbindungen annehmen. Um einen anderen Port zu verwenden, &lt;br /&gt;
geben Sie diesen auf der Kommandozeile mit &amp;quot;&amp;lt;code&amp;gt;-port &amp;amp;lt;nr&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;quot; an. &lt;br /&gt;
&amp;lt;br&amp;gt;Um von expecco eine Verbindung über diesen Server herzustellen, geben Sie beim Verbindungsaufbau als Remote-Server &lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:4444/wd/hub&lt;br /&gt;
an.&lt;br /&gt;
&lt;br /&gt;
Das Starten des Selenium-Servers bzw. die Verbindung muss eventuell von der Firewall zugelassen werden.&lt;br /&gt;
&lt;br /&gt;
Falls der Server beim Verbinden die jeweiligen Driver nicht finden, legen Sie diese ins selbe Verzeichnis, in dem Sie den Server starten, oder fügen Sie das Verzeichnis in dem der Driver liegt zum Pfad hinzu. Beachten Sie dabei, dass expecco verschiedene Versionen eines Driver-Typs mitliefert und diese durch einen Namenszusatz unterscheidet. Aufgrund dieser Zusätze erkennt der Server die Dateien aber häufig nicht.&lt;br /&gt;
&lt;br /&gt;
Für neue Versionen von &#039;&#039;&#039;Microsoft Edge&#039;&#039;&#039;, die Chromium basieren, starten Sie anstatt eines Selenium-Servers direkt den MSEdgeDriver (&amp;quot;msedgedriver.exe&amp;quot;) in der Version, die zur Edge-Version auf diesem Rechner passt.&lt;br /&gt;
  msedgedriver.exe [--port=9515]&lt;br /&gt;
Wenn Sie keine Portnummer angeben, wird der Service auf dem Port 9515 gestartet. Geben Sie dann beim Verbindungsaufbau in expecco als Remote-Server die Adresse&lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:9515&lt;br /&gt;
an. Die Erweiterung &amp;quot;/wd/hub&amp;quot; ist hier nicht erforderlich.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsbausteine==&lt;br /&gt;
Der Verbindungsaufbau, welcher im GUI Browser interaktiv erfolgt, muss natürlich bei einem automatisierten Ablauf über einen Aktionsbaustein erfolgen.&lt;br /&gt;
Dazu gibt es in der SeleniumWebDriverLibrary im Ordner &amp;quot;&#039;&#039;Connection&#039;&#039;&amp;quot; verschiedene Bausteine, welche die Verbindungsparameter von verschiedenen Quellen erhalten:&lt;br /&gt;
* Connect&amp;lt;br&amp;gt;Dieser Baustein erhält die Verbindungsparameter über Eingangspins&lt;br /&gt;
* Connect from File&amp;lt;br&amp;gt;Hier werden die Einstellungen aus einer Datei (Anhang) gelesen (typischerweise im JSON Format)&lt;br /&gt;
* Connect from Spec&amp;lt;br&amp;gt;Die Verbindungsparameter werden in einem Dictionaryobjekt geliefert&lt;br /&gt;
* Reuse or Start Connection&amp;lt;br&amp;gt;Im Gegensatz zu obigen Bausteinen, welche immer eine neue Browserverbindung aufbauen (i.e. ein neues Browserfenster öffnen), wird dieser Baustein zunächst prüfen, ob bereits eine Verbindung besteht, und diese gegebenenfalls wiederverwenden. Dieser Baustein kann daher mehrfach (i.e. zu Beginn von Teilsequenzen) platziert werden, und damit die Teilsequenzen sowohl innerhalb eines komplexeren Gesamttests als auch &amp;quot;stand-alone&amp;quot;, d.h. einzeln ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Alle &amp;quot;Connect&amp;quot; Bausteine benötigen die Angabe eines &amp;quot;&#039;&#039;Verbindungsnamens&#039;&#039;&amp;quot;.&lt;br /&gt;
Dieser hat die Aufgabe, die Verbindung im weiteren Testverlauf zu identifizieren, wenn zwischen mehreren Verbindungen gewechselt wird, und zum Abbauen der Verbindung. &lt;br /&gt;
&lt;br /&gt;
Wenn Sie im GUI Browser im Elementbaum auf eine Verbindung klicken, erscheint in der rechten &amp;quot;Test&amp;quot; Kachel ein Connect Baustein mit entsprechend vorgelegten Parametern. Diesen können Sie bei Bedarf gleich in die Rekordersequenz übertragen, oder (besser) als separate Aktion speichern (es ist sinnvoll, den Verbindungsaufbau von den aufgezeichneten Teilsequenzen zu trennen; damit haben Sie es später leichter, andere Browser zu verwenden, die Parameter der Verbindung zu ändern und auch neue Teilsequenzen aufzuzeichnen oder zu modifizieren.&lt;br /&gt;
&lt;br /&gt;
Verbindungen mit komplexen Einstellungen werden typischerweise im Verbindungsdialog angelegt, und die Einstellungen von dort über die Menüfunktion &amp;quot;&#039;&#039;Sichern in Anhang/Datei&#039;&#039;&amp;quot; in einer Datei gesichert. So können Sie verschiedene Konfigurationen in einzelnen Dateianhängen in ihrer Testsuite oder auch außerhalb aufbewahren. Zum Verbinden verwenden Sie dann den Aktionsbaustein &amp;quot;[&#039;&#039;Connect From File&#039;&#039;]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Plugin-Einstellungen=&lt;br /&gt;
Wenn Sie eine bestimmte Browser-Installationen oder Driver standardmäßig als Voreinstellung verwenden möchten, können Sie diese in den Einstellungen des Plugins eintragen. Sie finden sie über das Menü unter dem Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot;. Einstellungen für spezifische Browser finden Sie unter den Unterpunkten &amp;quot;&#039;&#039;Beliebteste Browser&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;Andere Browser&#039;&#039;&amp;quot;.&lt;br /&gt;
Die dortigen Einstellungen gelten als Voreinstellung für jede Verbindung, es sei denn in einer konkreten Verbindungseinstellungen ist etwas anderes angegeben.&lt;br /&gt;
&lt;br /&gt;
===Ausführungsverzögerung für Chrome===&lt;br /&gt;
In manchen Fällen kann es bei Verwendung des Chrome-Browsers vorkommen, dass Bausteine mit Element-Aktionen, beispielsweise ein Klick, im Test erfolgreich durchlaufen, die eigentliche Aktion aber gar nicht ausgeführt wurde. Dies ist ein bekannter Fehler [https://github.com/MPDL/imeji-gui-testing/issues/37], [https://github.com/SeleniumHQ/selenium/issues/4075], der von Selenium bzw. chromedriver behoben werden muss.&lt;br /&gt;
&lt;br /&gt;
Der Fehler lässt sich verhindern, indem entweder der Klick über JavaScript aufgerufen wird&amp;amp;nbsp;(setzen Sie dazu im Klick-Baustein &#039;&#039;invokeDirectly&#039;&#039; auf &#039;&#039;true&#039;&#039;&amp;amp;nbsp;) oder vor der Aktion kurz gewartet wird. Die Ausführung über JavaScript hat den Nachteil, dass sie weniger nah am Klick eines echten Benutzers ist; beispielsweise funktionieren Klicks auf Elemente auch dann, wenn sie von anderen Elementen verdeckt werden (was bei einem &amp;quot;normalen&amp;quot;Klick nicht geht). &lt;br /&gt;
&lt;br /&gt;
Generell warten die Bausteine mit Element-Aktionen automatisch, bis das entsprechende Element verfügbar ist (existiert). In den hier beschriebenen Fällen reicht das aber nicht aus. Deshalb finden Sie in den Plugin-Einstellungen für Chrome die Einstellung &amp;quot;&#039;&#039;Ausführungsverzögerung&#039;&#039;&amp;quot;. Bei der Ausführung wird dann zwischen den Aktionen entsprechend lange gewartet. Falls bei Ihnen der beschriebene Fehler eintritt, können Sie diesen Wert erhöhen. Ein größerer Wert hat natürlich Auswirkung auf die Gesamtlaufzeit.&lt;br /&gt;
&lt;br /&gt;
=Recorder=&lt;br /&gt;
&lt;br /&gt;
Die folgende Beschreibung des Recorders gilt prinzipiell für alle von expecco unterstützten GUI Technologien. Verhalten und Bedienung sind bis auf kleine technologiebedingte Unterschiede für alle gleich.&lt;br /&gt;
&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung mit einem Browserfenster, kann der integrierte Recorder verwendet werden, um einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Für jeden Klick im Fenster wird eine Aktion aufgezeichnet. Weitere Aktionen stehen über das Menü zur Verfügung. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
Allgemeine Aktionen finden Sie entweder direkt in der Menüleiste oder dort im Browser-Werkzeuge-Menü (s.u.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Element-Werkzeugs in der Menüleiste (s.u.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion. Auf diese Weise ist es ebenfalls möglich, die Eingaben &#039;&#039;Backspace&#039;&#039;, &#039;&#039;Return&#039;&#039; und &#039;&#039;Tab&#039;&#039; aufzuzeichnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverRecorder.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Komponenten des Recorderfensters&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme Pausieren&#039;&#039;&#039;: Wenn die Kontrollleuchte rot ist, nimmt der Recorder auf. Durch Klicken können Sie die Aufnahme anhalten. Die Kontrolleuchte leuchtet dann grau. In diesem Zustand können Sie weiter Aktionen über das Recorder-Fenster ausführen, sie werden aber nicht aufgezeichnet. Klicken Sie erneut, um die Aufnahme weiterzuführen.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Browser. Dies wird nötig, wenn die Anzeige des Recorders nicht mit dem tatsächlichen Browserinhalt übereinstimmt. &lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Element-Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Es stehen alle Aktionen zur Verfügung, die auf ein bestimmtes Element ausgeführt werden. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst und das Element aus der Position bestimmt. Die nicht ausgewählten Aktionen sind jederzeit über einen Rechtsklick erreichbar. &lt;br /&gt;
#&#039;&#039;&#039;Browser-Werkzeuge&#039;&#039;&#039;: Aktionen die sich nicht auf bestimmte Elemente beziehen, wie Scrollen oder Aktionen auf die aktuelle URL oder den Titel, können hier ausgelöst werden.&lt;br /&gt;
#&#039;&#039;&#039;Seitennavigation&#039;&#039;&#039;: Aktionen zur Seitennavigation: &#039;&#039;eine Seite zurück&#039;&#039;, &#039;&#039;eine Seite vor&#039;&#039; und &#039;&#039;aktuelle Seite neu laden&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Alert-Behandlung&#039;&#039;&#039;: Wenn der Browser einen Alert anzeigt, klicken Sie auf diesen Button, um die Aktionen zur Alert-Behandlung auswählen zu können.&lt;br /&gt;
#&#039;&#039;&#039;Online Dokumentation&#039;&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Browsers. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot. Scrollen wird den Browser weitergeleitet, aber nicht aufgenommen.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots. Diese kann auch über Scrollen in der Anzeige bei gedrückt gehaltener Strg-Taste angepasst werden.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Hier werden Meldungen angezeigt, bspw. wenn eine Aktion nicht aufgenommen werden konnte. Die letzte Meldung wird solange angezeigt, bis sie über den Button rechts daneben geschlossen wird.&amp;lt;br&amp;gt;&#039;&#039;&#039;Fenster-Tabs&#039;&#039;&#039;: Ab expecco 23.1 werden oberhalb der Anzeige Tabs für jedes offene Fenster angezeigt, sobald eine Verbindung mehr als ein Browserfenster besitzt. Ob der Browser dieses als Tab oder in einem eigenen Fenster anzeigt, ist dabei egal. Über die Tabs im Recorder können Sie das aktuelle Fenster wechseln und diesen Wechsel auch aufzeichnen.&amp;lt;br&amp;gt;&#039;&#039;&#039;Frame-Kontext&#039;&#039;&#039;: Ab expecco 23.1 sehen Sie unterhalb der Anzeige, in welchem Frame-Kontext Sie sich gerade befinden (siehe dazu den Abschnitt [[#Eingebettete_Inhalte|Eingebettete Inhalte]]). Sie können auf die Einträge klicken, um in einen höheren Kontext zu wechseln und diesen Wechsel aufzuzeichnen. Falls Sie zusammengesetzte Pfade eingestellt haben, wird die Anzeige aktualisiert, wenn Sie ein eingebettetes Element ausgewählt haben.&lt;br /&gt;
&lt;br /&gt;
=Eingebettete Inhalte=&lt;br /&gt;
In HTML ist es möglich, auf einer Seite Inhalte einer anderen einzubinden. Das gängigste Elemente dafür ist ein Iframe (Inlineframe). Auf den Inhalt eines Iframes kann ebenfalls mit Selenium zugegriffen werden, allerdings muss dazu zuerst in diesen Kontext gewechselt werden. In der SeleniumWebDriverLibrary gibt es entsprechenden Bausteine, um in den Kontext eines Iframes zu wechseln, um in den Elternkontext zu wechseln und um zurück zum Standardinhalt, also dem obersten Kontext zu wechseln. Alle Element-Bausteine lösen die angelegten Pfade immer innerhalb des aktuellen Kontexts auf. Im GUI-Browser sehen Sie für eingebettete Inhalte ein zusätzliches Element, welches sie aufklappen können um dessen Elemente zu sehen.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Seit expecco 23.1 gibt es die Möglichkeit, auch zusammengesetzte Pfade an den Bausteinen zu verwenden, um direkt vom Standardinhalt auf den Inhalt eines Iframes zugreifen zu können. Dazu werden einfach der Pfad zum Iframe und der Pfad innerhalb des Iframe-Inhalts zu einem zusammengesetzt. Wichtig ist hierbei, dass beim Übergang keine Elemente ausgelassen werden dürfen, d.h. der vordere Teil muss mit dem Iframe-Element enden und der hintere Teil mit &#039;&#039;/body&#039;&#039; beginnen. Dazwischen dürfen die Pfade gekürzt werden und es ist natürlich auch möglich auf diese Art beliebig tief geschachtelte Elemente zu erreichen. An den Bausteinen können beide Techniken nach belieben verwendet werden, wichtig ist nur, dass die Pfade immer in dem Kontext aufgelöst werden, in dem sich Selenium gerade befindet.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie die kombinierten Pfade aufzeichnen, bzw. im GUI-Browser verwenden wollen, setzen Sie im Menü &#039;&#039;GUI Browser&#039;&#039; unter &#039;&#039;Aufzeichnung&#039;&#039; den Haken bei &#039;&#039;Zusammengesetzte Pfade aufzeichnen&#039;&#039;. Damit wird für eingebettete Elemente ein zusammengesetzter Pfad relativ zum aktuellen Kontext erzeugt und angezeigt, anstatt wie bisher nur innerhalb seines eigenen Kontexts. Außerdem können Sie diese Elemente auch direkt im Recorder ansprechen oder über Follow-Mouse finden.&lt;br /&gt;
&lt;br /&gt;
=Shadow-Elemente=&lt;br /&gt;
Shadow-DOMs sind eine Möglichkeit, um Teile einer Seite vom übrigen Dokument abzukapseln. Dabei werden an ein Element versteckte Shadow-Elemente angehängt. Eine ausführlichere Erklärung finden Sie zum Beispiel hier: [https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM Using shadow DOM - Web APIs | MDN].&lt;br /&gt;
&lt;br /&gt;
In der SeleniumWebDirverLibrary gibt es den Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039;, der die obersten Elemente liefert, die dann wie andere WebElemente verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
Da die Elemente versteckt sind, werden sie vom GUI-Browser nicht direkt angezeigt. Ab expecco 23.1 kann man allerdings im Kontextmenü der Elemente im GUI-Browser einen Haken setzen, dass Shadow-Elemente gesucht werden sollen. Beim Aktualisieren der Kinder eines Elements werden sie dann angezeigt, falls vorhanden, allerdings nicht, wenn der gesamte Baum aktualisiert wird. Wenn der Haken gesetzt ist, sind die Elemente auch im Recorder verfügbar.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Ähnlich wie die Elemente innerhalb eines Frames kann auch auf die Shadow-Elemente direkt über zusammengesetzte Pfade zugegriffen werden. Diese Pfade können dann direkt an den Bausteinen verwendet werden, sodass der Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039; nicht benötigt wird. Die Pfade haben die Form&lt;br /&gt;
 &amp;lt;host path&amp;gt;/shadowRoot/&amp;lt;shadow path&amp;gt;&lt;br /&gt;
wobei &#039;&#039;&amp;lt;host path&amp;gt;&#039;&#039; den Pfad zum Element angibt, an das der Shadow-DOM angehängt wurde, und &#039;&#039;&amp;lt;shadow path&amp;gt;&#039;&#039; der Pfad innerhalb des Shadow-DOMs zum gewünschten Element ist. &#039;/shadowRoot&#039; dient als Marker, dass an dieser Stelle der Wechsel in den Shadow-DOM erfolgt.&lt;br /&gt;
&lt;br /&gt;
=Authentifizierungs-Alerts=&lt;br /&gt;
Falls eine Webseite HTTP-Authentifizierung mit Basic Authentication verwendet, öffnet sich beim Laden der Seite ein Alert-Fenster zur Eingabe von Benutzernamen und Passwort. Dieses Fenster ist nicht direkt mit Selenium bedienbar. Im GUI-Browser wird es wie ein Alert angezeigt. Eine Ausnahme hierzu bildet Chrome, bei dem der Driver auf keine Anfrage antwortet solange der Dialog geöffnet ist. Das Plugin kann zu diesem Zeitpunkt insbesondere nicht feststellen, ob ein Authentifizierungs-Dialog geöffnet ist oder ob der Driver aus anderen Gründen nicht antwortet.&lt;br /&gt;
&lt;br /&gt;
Bei lokalen Verbindungen unter Windows kann eine Authentifizierung mittels Windows Access ausgeführt werden. Es gibt in der SeleniumWebDriverLibrary für einzelne Browsertypen spezifische Authentifizierungs-Bausteine sowie den Baustein &#039;&#039;Authenticate at Alert&#039;&#039;, der je nach Verbindung den entsprechenden Baustein ausführt. Für die verschiedenen Browser-Typen gibt es dabei unterschiedliche Einschränkungen:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Chrome:&#039;&#039;&#039; Die Anmeldedaten werden an ein Chromefenster geschickt, daher funktioniert es nur, wenn nicht mehrere geöffnet sind. Der Einzelbaustein hat für diesen Fall die Option, den Titel des Fensters anzugeben.&lt;br /&gt;
:&#039;&#039;&#039;Edge&#039;&#039;&#039;: Mit Microsoft Edge wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
:&#039;&#039;&#039;Firefox&#039;&#039;&#039;: Schickt die Anmeldedaten an ein Firefox-Dialogfenster und funktioniert daher nur, wenn es nicht mehrere gibt.&lt;br /&gt;
:&#039;&#039;&#039;Internet Explorer&#039;&#039;&#039;: Mit dem Internet Explorer wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
Als zusätzliche Option steht Ihnen auch eine Anmeldung über die URL zur Verfügung. Rufen Sie anstatt der Seite &amp;lt;nowiki&amp;gt;https://www.example.com&amp;lt;/nowiki&amp;gt; die URL &amp;lt;nowiki&amp;gt;https://user:password@www.example.com&amp;lt;/nowiki&amp;gt; auf. Wichtig ist hierbei, dass &#039;&#039;:&#039;&#039; und &#039;&#039;@&#039;&#039; nicht im Benutzernamen oder im Passwort auftauchen. Möglicherweise wird diese Methode nicht von jedem Browser unterstützt.&lt;br /&gt;
&lt;br /&gt;
Mithilfe des [[WindowsAutomation_Reference_2.0|WindowsAutomation2]]-Plugins ist es ebenfalls möglich, solch eine Anmeldung mit allen Browsertypen auszuführen.&lt;br /&gt;
&lt;br /&gt;
=Portierung alter Selenium-Tests=&lt;br /&gt;
Dieses Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Dieses basierte auf [https://www.seleniumhq.org/projects/remote-control/ Selenium RC], welches in Zukunft von den Browsern nicht mehr unterstützt wird. Der Nachfolger von Selenium RC ist [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver], auch &#039;&#039;Selenium 2&#039;&#039; genannt. Ebenso ist auch das Aufzeichnen von Tests mit [https://www.seleniumhq.org/projects/ide/ Selenim IDE] veraltet, da das Plugin von neueren Browsern nicht mehr unterstützt wird. Das Selenium WebDriver Plugin verwendet stattdessen einen eigenen [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
Tests, die mit dem alten Selenium Web Test Plugin erstellt wurden und die alte SeleniumLibrary verwenden, können über Selenium WebDriver ausgeführt werden. Setzen Sie dazu in den Plugin-Einstellungen von &amp;quot;&#039;&#039;Webtest Legacy (Selenium)&#039;&#039;&amp;quot; den Haken bei &amp;quot;&#039;&#039;WebDriver für die Ausführung verwenden&#039;&#039;&amp;quot;. Für die wichtigsten Funktionen wurde Wrapper bzw. umsetzende Funktionen erstellt, um die Migration möglichst problemlos zu gestalten.&lt;br /&gt;
Testen Sie dann, ob die Tests wie bisher ablaufen. Für den überwiegenden Teil der Bausteine sollte es dabei keine Probleme geben. Einige wenige Aktionen werden in der WebDriver Version nicht mehr unterstützt oder verhalten sich unterschiedlich. Es ist auch nicht garantiert, daß die Emulation der alten Schnittstelle auf Dauer von Selenium unterstützt werden. Wenn möglich sollten Sie daher über kurz oder lang die Testfälle umschreiben.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*&#039;&#039;&#039;Scrollbalken lassen sich im Recorder nicht bedienen&#039;&#039;&#039;&lt;br /&gt;
:Der Scrollbalken des Browsers, der automatisch angezeigt wird, wenn eine Seite größer als das Browserfenster ist, ist kein bedienbares Webelement. Scrollen um einen bestimmten Betrag ist in einem Test selten sinnvoll, wenn die Größe des Browserfensters nicht festgelegt ist. Verwenden Sie stattdessen den Baustein &amp;lt;code&amp;gt;[Web] Scroll Element into View&amp;lt;/code&amp;gt;, um ein entsprechendes Element in den sichtbaren Bereich zu scrollen. Der Klick-Baustein, den der Recorder standardmäßig verwendet, führt diese Aktion bereits automatisch mit aus (&amp;lt;code&amp;gt;[WebElement] Click (Scroll Element into View)&amp;lt;/code&amp;gt;). Wenn Sie im Recorder-Fenster scrollen, wird dies automatisch auf den Browser übertragen, aber nicht aufgezeichnet. Falls Sie tatsächlich um einen bestimmten Betrag scrollen möchten, gibt es bei den Browser-Aktionen einen Eintrag dafür und weitere Bausteine in der SeleniumWebDriverLibrary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein schlägt fehl, wenn Element zu spät sichtbar wird&#039;&#039;&#039;&lt;br /&gt;
:Alle Bausteine, die einen Elementpfad verwenden, haben automatisch eingebaut, dass sie warten, bis ein entsprechendens Element auftaucht. Es gibt aber Fälle, in denen ein Element zwar bereits da, aber noch nicht sichtbar ist. Bei einem Klick auf das Element bekommen Sie dann einen Fehler. Mögliche Fehler in diesem Zusammenhang sind &amp;lt;code&amp;gt;org.openqa.selenium.ElementNotInteractableException: element not interactable&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;. Verwenden Sie dann vor einer Interaktion mit dem Element den Baustein &amp;lt;code&amp;gt;[Web] Wait for Visibility of Element&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[Web] Wait for Element to Be Clickable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt; kann mit dem Chrome-Browser auftreten. In diesem Fall ist das verwendete Element nicht sichtbar. Lesen Sie dazu den Punkt oben. Der Fehler ist auch im Zusammenhang mit Elementen in einer Dropdown-Liste bekannt, d.h. bei einem Klick oder dem Bewegen der Maus auf ein &amp;lt;nowiki&amp;gt;&amp;lt;option&amp;gt;&amp;lt;/nowiki&amp;gt;-Element innerhalb eines &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Elements. Diese Elemente sind prinzipiell nicht klickbar. Verwenden Sie stattdessen einen passenden &amp;lt;code&amp;gt;[Web] Select&amp;lt;/code&amp;gt;-Baustein mit dem &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Stale Element Reference Exception&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein WebElement verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator, um das Element neu zu holen. Eventuell liegt es auch daran, dass sich der Test momentan in einem anderen Frame-Kontext befindet als das Element. Wenn Sie [[#Zusammengesetzte_Pfade|zusammengesetzte Pfade]] verwenden, sollte das Element selbst in den richtigen Kontext wechseln, bevor Aktionen darauf ausgeführt werden.&lt;br /&gt;
:In seltenen Fällen kann der Fehler auch in expecco selbst auftreten, wenn an irgendeiner Stelle im GUI-Browser oder Recorder ein entsprechendes WebElement verwendet wird. Sie sollten dann abbrechen können und es nochmal versuchen. Sollte der Fehler bestehen bleiben, wechseln Sie in den Default Content und laden Sie den Baum im GUI-Browser neu.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein läuft erfolgreich, aber ohne Auswirkungen&#039;&#039;&#039;&lt;br /&gt;
:Dieser Fall kann mit Chrome auftreten. Das Element ist verfügbar, die Aktion wirft keinen Fehler, aber es wird nichts ausgeführt. In der Regel hilft es, vor der Ausführung kurz zu warten, siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ausführungen mit Chrome sind langsamer&#039;&#039;&#039;&lt;br /&gt;
:Um ein Problem bei der Ausführung mit Chrome zu beheben, ist in den Plugin-Einstellungen für Chrome eine Verzögerung definiert. Überprüfen Sie, ob dieser Wert eventuell zu hoch eingestellt ist; siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldungen wie: &amp;quot;org.openqa.selenium.InvalidArgumentException: Expected &amp;quot;handle&amp;quot; to be a string...&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
:Dies passiert wenn der Driver nicht (mehr) zum Browser passt. Lesen Sie dazu obiges Kapitel &amp;quot;[[#WebDriver aktualisieren|WebDriver aktualisieren]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Key Chords mit Shortcuts funktionieren nicht&#039;&#039;&#039;&lt;br /&gt;
:Das Drücken mehrerer Tasten gleichzeitig lässt sich als Key Chord simulieren. Dadurch können auch Shortcuts eingegeben werden. Allerdings funktionieren hier nicht alle Eingaben, da diese nur an den Seiteninhalt und nicht an den Browser selbst gehen. Kombinationen wie &#039;&#039;Strg + t&#039;&#039; um einen neuen Browsertab zu öffnen, funktionieren daher vermutlich nicht, &#039;&#039;Strg + a&#039;&#039; oder &#039;&#039;Strg + c&#039;&#039; sollten hingegen möglich sein.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Zusätzliche Window Handles mit Opera&#039;&#039;&#039;&lt;br /&gt;
:Der Opera-Browser liefert mehr Window Handles als Tabs bzw. Fenster geöffnet sind. Diese kommen von Opera-internen Funktionen wie dem Schnellstart (&#039;&#039;Speed Dial&#039;&#039;) oder der &#039;&#039;Better Address Bar Experience&#039;&#039; (BABE), die zwar im Browserfenster eingebunden, aber nicht als Tab angezeigt werden. Zu diesen Tabs kann zwar mit den entsprechenden Bausteinen gewechselt werden, es sind dann aber nicht alle Aktionen möglich, die für die normalen Tabs zur Verfügung stehen. Sie können zum Beispiel nicht geschlossen werden und man bekommt von ihnen kein Bild. Am besten wechselt man daher gar nicht erst in diese Kontexte. Seien Sie also vorsichtig, wenn Sie anhand des Index zu einem Tab wechseln wollen, da sich die Opera-Tabs zwischen den anderen befinden und der Index ein anderer als für die anderen Browser sein kann.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Chrome: Wähle deine Suchmaschine&#039;&#039;&#039;&lt;br /&gt;
:Neuere Chromeversionen zeigen nach dem Starten ein [https://www.google.com/chrome/choicescreen/ Overlay], bei dem man die verwendete Suchmaschine auswählen soll. Die Entscheidung wird normalerweise im Benutzerprofil gespeichert. Wenn für die Verbindung aber nicht explizit ein Chrome-Profil angegeben wird, hat man bei jedem Verbindungsaufbau ein leeres Profil und es wird immer nachgefragt.&lt;br /&gt;
&lt;br /&gt;
:In vielen Fällen kann der Test auch trotz des Overlays im Hintergrund ablaufen. Das Overlay gilt aber wie ein Tab bzw. Fenster; so liefert beispielsweise vom Baustein &#039;&#039;[Web] Get Window Handles&#039;&#039; einen Handle dafür und es kann auch dorthin gewechselt werden. Es gibt aber auch Möglichkeiten es loszuwerden:&lt;br /&gt;
:* &#039;&#039;--disable-search-engine-choice-screen&#039;&#039;: In den [[#Erweiterte_Einstellungen|erweiterten Einstellungen]] kann man bei den Optionen &amp;lt;code&amp;gt;--disable-search-engine-choice-screen&amp;lt;/code&amp;gt; angeben, dann kommt das Overlay nicht.&lt;br /&gt;
:* &#039;&#039;Auswählen&#039;&#039;: Sie können Ihren Test auch so erweitern, dass zu Beginn eine Suchmaschine ausgewählt und damit das Overlay geschlossen wird. Dabei müssen Sie zwei Dinge beachten. Zum einen müssen Sie zuerst mit einem &#039;&#039;Switch to Window&#039;&#039;-Baustein dorthin wechseln (z.B. mit Index &#039;&#039;2&#039;&#039; oder leerem Titel) und am Ende auch wieder zurück zu Ihrem ursprünglichen Tab. Zum anderen sind interessanten Elemente des Overlays [[#Shadow-Elemente|Shadow-Elemente]] und werden daher im GUI-Browser nicht direkt angezeigt.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin/en&amp;diff=29680</id>
		<title>Selenium WebDriver Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin/en&amp;diff=29680"/>
		<updated>2024-08-05T13:33:24Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* FAQ */ Chrome: Choose your search engine&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Selenium_WebDriver_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
Use the &#039;&#039;Selenium WebDriver Plugin&#039;&#039; to test or automate interactions of applications running in a web-browser (*). The plugin can be (and usually is) used with the [[Expecco_GUI_Tests_Extension_Reference|GUI Browser]], which helps in the creation of tests. Moreover, the GUI Browser can record UI sessions, which can later be customised or refactored as required.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;Selenium WebDriver Plugin&#039;&#039; replaces the previous [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]], which was based on the now outdated Selenium RC framework.&amp;lt;br&amp;gt;&lt;br /&gt;
The new web driver uses the [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver] for automation, and replaces the previous interface.&lt;br /&gt;
(see https://www.guru99.com/introduction-webdriver-comparison-selenium-rc.html  for background information and a description of the differences.)&lt;br /&gt;
Read [[#Transferring_Old_Selenium_Tests|this section]] for information how to transfer testsuites using the old plugin.&lt;br /&gt;
&lt;br /&gt;
(*) actually, there exists WebDriver interfaces to control Windows or OS X desktop applications. Thus, this plugin can be used in a number of additional scenarios.&lt;br /&gt;
&lt;br /&gt;
=Settings=&lt;br /&gt;
This plugin uses the Java bridge and therefore needs a Java installation. You can specify it in the settings under &#039;&#039;Plugins&#039;&#039; -&amp;gt; &#039;&#039;Java Bridge&#039;&#039;. The important field is &#039;&#039;Java Installation Path&#039;&#039;, where you can set a JDK or JRE. If nothing is set, expecco tries to find java in the PATH.&lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
There are settings for the Selenium WebDriver Plugin itself as well. You find them under &#039;&#039;Plugins&#039;&#039; -&amp;gt; &#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;. There you can for example set the address of a remote running Selenium server or another Jar file for Selenium. The settings for the different browser types are divided into the two subpages &#039;&#039;Most Popular Browsers&#039;&#039; and &#039;&#039;Other Browsers&#039;&#039;. There you can set the path to the browser executable or to the webdriver to use. You can leave all these fields empty and expecco will search for them automatically&lt;br /&gt;
&lt;br /&gt;
=Browser Support=&lt;br /&gt;
This plugin supports (among others) the Chrome/Chromium, Edge, Firefox, Internet Explorer  and Opera browsers. &lt;br /&gt;
&amp;lt;br&amp;gt;Safari under OSX must be at least version 10, and OSX must be at least El Capitan.&lt;br /&gt;
The plugin uses the WebDriver interface for communication; therefore, browsers running both on the local or on a remote machine can be tested and/or controlled.&lt;br /&gt;
In addition, many other browsers, UIs and devices support the WebDriver protocol, and can thus be automated/tested with expecco.&lt;br /&gt;
&lt;br /&gt;
==Update WebDriver==&lt;br /&gt;
Each browser has a driver (&amp;quot;&#039;&#039;WebDriver&#039;&#039;&amp;quot;) for opening and controlling a browser window. &lt;br /&gt;
Usually, the driver is a separate program which translates WebDriver requests into browser-specific interface calls. However, there are also browsers and programs which have the WebDriver protocol already built in (eg. Safari).&lt;br /&gt;
&lt;br /&gt;
The expecco installation package includes current driver versions for common browsers. However, as the browsers are updated continuously, sometimes even automatically, you sooner or later may have to download a new driver version. In that case put it in the folder inside your expecco installation directory where the other versions are stored as well, at:&lt;br /&gt;
 &amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib/XXX&amp;lt;/code&amp;gt;&lt;br /&gt;
(of course, with &amp;quot;\”s instead of &amp;quot;/&amp;quot;s on Microsoft Windows operating systems), where &amp;quot;XXX&amp;quot; denotes the operating system (Windows, Linux, OSX etc.).&lt;br /&gt;
&amp;lt;!--To use a different driver, check the &amp;quot;Advanced&amp;quot; toggle in the connection dialog and add the driver&#039;s path to the settings (see below).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the connection dialog, expecco may show a warning, that the driver version is incompatible with the browser version. In some cases this may only be due to the fact, that this version was not known at the time of delivery. Some combinations may work despite the warning, but we cannot guarantee that for each individual case.&lt;br /&gt;
&lt;br /&gt;
Therefore you can always check the &amp;quot;&#039;&#039;Do not show this warning again&#039;&#039;&amp;quot; toggle, if such a warning is shown, to have expecco remember that combination as &amp;quot;compatible&amp;quot; in your settings, and not warn again. You should only do that, if you are sure that your tests will still be executed correctly. As we sometimes get compatibility problems ourselves and cannot always immediately find the reason, we advice you, to update the driver.&lt;br /&gt;
&lt;br /&gt;
For Chrome and Microsoft Edge, where each new browser version comes with a new driver version, you find a button in the connection dialog, to download matching driver versions by expecco.&lt;br /&gt;
&lt;br /&gt;
You find new driver versions at the following addresses:&lt;br /&gt;
{|&lt;br /&gt;
|Chrome/Chromium&lt;br /&gt;
|[https://sites.google.com/chromium.org/driver/ ChromeDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Edge&lt;br /&gt;
|[https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ Microsoft WebDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|[https://github.com/mozilla/geckodriver/releases GeckoDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|[https://selenium-release.storage.googleapis.com/index.html IEDriverServer]&lt;br /&gt;
|-&lt;br /&gt;
|Opera&lt;br /&gt;
|[https://github.com/operasoftware/operachromiumdriver/releases Opera driver]&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|[https://webkit.org/blog/6900/webdriver-support-in-safari-10 Safari Support]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Download a suitable version and place it at an appropriate location in the above mentioned directory. expecco will then find and use it. &amp;lt;!-- You can extend the file name to have multiple versions in parallel. --&amp;gt; Alternatively, you can set the path to a driver either in the [[#Advanced_Settings | connection editor]] or in the [[#Plugin_Settings | plugin settings]].&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Please verify that the driver&#039;s version is compatible with the browser version. If in doubt, consult the version history (e.g. for Chrome: https://chromedriver.storage.googleapis.com/2.25/notes.txt).&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Notice: For Internet Explorer, &amp;quot;&amp;lt;code&amp;gt;Protected Mode&amp;lt;/code&amp;gt;&amp;quot; settings must be set to the same value for all zones, to be able to start a connection.  (in the Internet Explorer, open &amp;quot;Settings&amp;quot; - &amp;quot;Internet Options&amp;quot; - &amp;quot;Security&amp;quot;, and set the value of &amp;quot;protected mode&amp;quot; to the same in all 4 zones; otherwise, you&#039;ll get error- and warning dialogs when connecting). See also the [https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration required configuration] to use InternetExplorerDriver.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Also notice: the plugin uses JavaScript for some advanced functions, and those functions require that JavaScript is enabled in the browser. This is especially needed to use the GUI browser and the recorder. Test execution may be possible without JavaScript, as long as no actions are used which rely on JavaScript.&lt;br /&gt;
If you get an error like &amp;lt;code&amp;gt;&amp;quot;org.openqa.selenium.JavascriptException: Error executing JavaScript&amp;quot;&amp;lt;/code&amp;gt;,&lt;br /&gt;
make sure that JavaScript is enabled in the browser and that the versions of the browser and the associated driver are compatible.&lt;br /&gt;
&lt;br /&gt;
=Additional Uses=&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/appium/appium-for-mac AppiumForMac]&lt;br /&gt;
|WebDriver to control OS X apps (i.e. also non-Browsers)&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/microsoft/WinAppDriver WinAppDriver]&lt;br /&gt;
|WebDriver to control Windows Desktops&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Notice, that these interfaces usually provide a subset of the functionality provided by special plugins, such as Java-GUI or WindowsAutomation plugins. Usually, they are ok to manipulate the top level window or to confirm simple dialogs, but less usable for more complex UI tests.&lt;br /&gt;
&lt;br /&gt;
= Quick Start =&lt;br /&gt;
== Open Browser / Connecting ==&lt;br /&gt;
* Start expecco&lt;br /&gt;
* Click on &amp;quot;&#039;&#039;New Testsuite&#039;&#039;&amp;quot;&lt;br /&gt;
* Click on the GUI-Browser symbol ([[Datei:GUIBrowser.png|24px]])&lt;br /&gt;
* A new Tab appears, containing the GUI-Browser&lt;br /&gt;
* Click on &amp;quot;&#039;&#039;Connect&#039;&#039;&amp;quot; and choose &amp;quot;&#039;&#039;Selenium Testing&#039;&#039;&amp;quot;. The  [[#Connection Editor | Connection Dialog]] appears (see details below)&lt;br /&gt;
* Choose the type of browser (eg. &amp;quot;&amp;lt;code&amp;gt;firefox&amp;lt;/code&amp;gt;&amp;quot; and enter the URL of the tested web site (eg. &amp;quot;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.myHost.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;) and )&lt;br /&gt;
* Click on &amp;quot;Connect&amp;quot;&lt;br /&gt;
* A browser is started automatically, and the page is shown&lt;br /&gt;
* As soon as the connection is established,  the page&#039;s elements are shown in the GUIBrowser&#039;s left tree view&lt;br /&gt;
&lt;br /&gt;
== Start a Recording ==&lt;br /&gt;
* After a connection has been established, click on the record icon ([[Datei:Recording.png|16px]]) in the GUIBrowser.&lt;br /&gt;
&lt;br /&gt;
== Inspecting Elements ==&lt;br /&gt;
* Select an element in the browser&#039;s element-tree, or move the mouse over it in &amp;quot;follow-mouse mode&amp;quot;. If your browser does not support this &amp;quot;follow-mouse&amp;quot; mode, try opening a recorder, and move the mouse there.&lt;br /&gt;
The element&#039;s attributes are shown in the lower-center attribute/property list.&lt;br /&gt;
== Manually adding Actions and Checks ==&lt;br /&gt;
* In addition to recording, actions and checks can also be selected from the upper-centre action list. Select one there and either try it immediately or add it to the recording sequence via the add-action button at the top far right.&lt;br /&gt;
&lt;br /&gt;
=Connecting=&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Verbindungsdialog&amp;quot;&amp;gt;Connection Editor==&lt;br /&gt;
The connection editor defines, changes or starts a connection. Open the GUI browser, click on &amp;quot;&#039;&#039;Connect&#039;&#039;&amp;quot; and select &amp;quot;&#039;&#039;Selenium Testing (WebDriver)&#039;&#039;&amp;quot;. You can also create attachments or files containing connection parameters (&amp;quot;&#039;&#039;connection settings&#039;&#039;&amp;quot;) without actually connecting to/opening a new browser connection via the &amp;quot;&#039;&#039;Save Connection Settings&#039;&#039;&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
When opened, the connection editor presents a number of fields and load/save buttons in its toolbar menu:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverConnectDialog.png]]&lt;br /&gt;
&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Open an attachment containing connection settings from an open project. This settings will be added to the editor. Already entered inputs that are not conflicting will remain unchanged.&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Open a saved settings file (*.csf). Its settings will be added to the editor. Already entered inputs that are not conflicting will remain unchanged.&lt;br /&gt;
#&#039;&#039;Save settings as attachment&#039;&#039;: Save all entered settings as attachment in an open project.&lt;br /&gt;
#&#039;&#039;Save settings as JSON attachment&#039;&#039;: Save all entered settings in JSON format as attachment in an open project.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039;: Save all entered settings to a file (*.csf).&lt;br /&gt;
#&#039;&#039;Version info&#039;&#039;: Opens a window showing the used versions of the Selenium server, the selected browser and its driver.&lt;br /&gt;
#&#039;&#039;Online documentation&#039;&#039;: Open this online documentation page.&lt;br /&gt;
#&#039;&#039;Connection name&#039;&#039;: Enter the name of the connection used to show it in the GUI browser. (Optional)&lt;br /&gt;
#&#039;&#039;Browser type&#039;&#039;: Choose the type of browser to use. Ensure it is installed and the version of the used driver is compatible with the browser version.&lt;br /&gt;
#&#039;&#039;URL&#039;&#039;: Enter the URL to open at startup. To open an empty browser window, leave this field empty. To open a local file use the &amp;quot;&amp;lt;code&amp;gt;file://&amp;lt;/code&amp;gt;&amp;quot; scheme, e.g. &amp;quot;&amp;lt;code&amp;gt;file:///C:/Users/admin/Desktop/index.html&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
#&#039;&#039;Advanced view&#039;&#039;: Toggle the view to enter [[#Advanced Settings|advanced settings]].&lt;br /&gt;
#&#039;&#039;Information on the selected browser&#039;&#039;: Here, the selected browser type is shortly characterized.&lt;br /&gt;
#&#039;&#039;Information on the settings&#039;&#039;: It shows which Selenium, browser and driver version will be used regarding the current settings. If you have set [[#Advanced Settings|advanced settings]], they will also be displayed here.&lt;br /&gt;
&lt;br /&gt;
===Advanced Settings===&lt;br /&gt;
Besides the used browser and the start URL, more settings and possibly &amp;quot;&#039;&#039;capabilities&#039;&#039;&amp;quot; may be required. To see click on the &amp;quot;Advanced&amp;quot; toggle. Depending on the selected browser type you get different entry fields.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Remote Server&#039;&#039;: To open a browser on a remote host, start a Selenium server there and set this field to its address. You can also enter a local address if you do not want the Selenium server to start automatically or if it is already running. See the next section [[#Remote Connections|Remote Connections]] on how to start a Selenium server.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Headless&#039;&#039;: to open the browser in &amp;quot;headless&amp;quot; mode, i.e. without a window. Not all browsers/drivers support this mode.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Binary&#039;&#039;: Enter the path to the binary of the selected browser. Use this if the browser cannot be found automatically by Selenium, or if you have another browser version installed or to be tested against.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Driver&#039;&#039;: For each browser, a particular driver is needed for automation. New browser versions often also need a new driver version. If you don&#039;t want or cannot use the driver provided by expecco, set its path here.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Command Line Options&#039;&#039;: arguments passed to the browser-command. For example the chrome browser supports a &amp;quot;--disable-extensions&amp;quot; command line argument, firefox supports &amp;quot;--safe-mode&amp;quot; and &amp;quot;--profile&amp;quot;. These options are browser- and possibly browser-version specific. Most browsers allow for a &amp;quot;--help&amp;quot; argument, which you may try in a shell window to find out.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Firefox Profile&#039;&#039;: For Firefox, it is possible to set a &#039;&#039;Firefox Profile&#039;&#039;, containing specific settings. If no profile is set, each connection will use a new empty one.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Capabilities&#039;&#039;: Selenium connections can use several capabilities to define the connection&#039;s behavior. To add specific capabilities, set them in this field. Write &amp;quot;&#039;&#039;&amp;lt;capability name&amp;gt;: &amp;lt;value&amp;gt;&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;&amp;lt;capability name&amp;gt; = &amp;lt;value&amp;gt;&#039;&#039;&amp;quot;, one entry per line.&amp;lt;p&amp;gt;The set of capabilities needed or supported are browser- and driver specific. Please refer to the concrete driver&#039;s documentation as found via the driver links above. Common capabilities are: &amp;quot;app&amp;quot; or &amp;quot;application&amp;quot;, &amp;quot;url&amp;quot;, etc. For drivers which communicate with mobile devices, the capabilities also select which device to use and/or wether an emulator should be started.&amp;lt;/p&amp;gt;&amp;lt;p&amp;gt;You can also set properties for the Firefox browser - for this, use the same syntax as for capabilities, but add a leading &#039;&#039;$&#039;&#039; to the property name.&amp;lt;/p&amp;gt;Properties used by expecco internally (such as browser type, url or remote host) are prefixed by a &amp;quot;#&amp;quot;-character.&lt;br /&gt;
&lt;br /&gt;
==Remote Connections==&lt;br /&gt;
To start a browser on a remote computer, copy the Selenium server and the required driver to that computer. You find the files in your expecco installation at &amp;quot;&amp;lt;code&amp;gt;packages\exept\expecco\plugin\seleniumWebDriver\lib&amp;lt;/code&amp;gt;&amp;quot;. Start the Selenium server (on the remote host) with:&lt;br /&gt;
 java -jar selenium-server-standalone-3.6.0.jar&lt;br /&gt;
By default, the server will listen on port 4444. To use another port, set it with the &amp;quot;&amp;lt;code&amp;gt;-port &amp;amp;lt;nr&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;quot; command line argument. To connect to that server, set the &amp;quot;&#039;&#039;remote server&#039;&#039;&amp;quot; parameter of the connection to &amp;quot;&#039;&#039;&amp;lt;Server-Address&amp;gt;:4444/wd/hub&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Check and possibly configure your firewall to allow transmission through the port.&lt;br /&gt;
&lt;br /&gt;
== Headless Browsing ==&lt;br /&gt;
&amp;quot;&#039;&#039;Headless Browsing&#039;&#039;&amp;quot; means: &amp;quot;&#039;&#039;without a window&#039;&#039;&amp;quot;,  and is useful to test web-pages for reachability, performance and structure. You can either use the HTMLUnit browser type, which simulates a browser, or run against one of the real browsers in headless mode. Notice, that not all browsers support this headless mode - we recommend using &amp;quot;firefox&amp;quot; or &amp;quot;chrome&amp;quot; for this.&lt;br /&gt;
&lt;br /&gt;
Also notice, that in order to verify that a web page&#039;s interaction with a browser works correctly, you should test against real browsers.&lt;br /&gt;
For an introduction on what &amp;quot;headless browsing&amp;quot; means, see for example [https://www.guru99.com/selenium-with-htmlunit-driver-phantomjs.html https://www.guru99.com/selenium-with-htmlunit-driver-phantomjs.html].&lt;br /&gt;
&lt;br /&gt;
Notice: the HTMLUnit driver has been removed from the latest selenium distribution and is also no longer supplied with expecco (it was not a good test tool anyway, as it behaved differently from real browsers).&lt;br /&gt;
&amp;lt;br&amp;gt;If required, download from [https://github.com/SeleniumHQ/htmlunit-driver https://github.com/SeleniumHQ/htmlunit-driver].&lt;br /&gt;
&lt;br /&gt;
==Connection Blocks==&lt;br /&gt;
SeleniumWebDriverLibrary offers a number of blocks to start a Selenium connection within a testrun. The &#039;&#039;connection name&#039;&#039; identifies the connection during the run, if the test uses multiple connections and switches between them (eg. if multiple browser windows are open simultaneously). To start a connection with predefined settings, save them in the connection dialog (as attachment), and use the &amp;quot;[&#039;&#039;Connect From File&#039;&#039;]&amp;quot; action block.&lt;br /&gt;
&lt;br /&gt;
=Plugin Settings=&lt;br /&gt;
To use certain browser installations or drivers as default, for every connection, set them in the settings dialog of the plugin (&amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Selenium WebDriver Extension&#039;&#039;&amp;quot;). Settings for specific browsers can be found under &amp;quot;&#039;&#039;Most Popular Browsers&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Other Browsers&#039;&#039;&amp;quot;. The settings there are used as default, unless overwritten by an individual connection configuration.&lt;br /&gt;
&lt;br /&gt;
===Execution Delay for Chrome===&lt;br /&gt;
In some cases it can happen when using the Chrome browser that blocks with element actions, for example a click, run successfully in the test, but the actual action was not executed at all. This is a known bug [https://github.com/MPDL/imeji-gui-testing/issues/37], [https://github.com/SeleniumHQ/selenium/issues/4075] that needs to be fixed by Selenium or Chromedriver. The error can be prevented by either calling the click via JavaScript&amp;amp;nbsp;– to do this, set &#039;&#039;invokeDirectly&#039;&#039; to &#039;&#039;true&#039;&#039; at the click block&amp;amp;nbsp;– or wait briefly before the action. Execution via JavaScript has the disadvantage that it is less close to the click of a real user and, for example, clicks on elements work even if they are hidden by other elements. In general, blocks with element actions automatically wait until the corresponding element is available. In the cases described here, however, this is not sufficient. Therefore you will find the setting &#039;&#039;execution delay&#039;&#039; in the plugin settings for Chrome. During execution, the system waits accordingly long between each action. If you experience the described error, you can increase its value. Of course, a higher value has an effect on the test run executio times.&lt;br /&gt;
&lt;br /&gt;
=Recorder=&lt;br /&gt;
The following description applies to all GUI technologies which support remote recording in the integrated expecco recorder: the behaviour of the recorder is (apart from small differences due to technology-specific limitations) the same across different connections.&lt;br /&gt;
&lt;br /&gt;
Use of this recorder has some advantages over direct recording in the browser:&lt;br /&gt;
* it can be used with remote machines/connections/mobil devices&amp;lt;br&amp;gt;especially for mobile devices, which may be all located in a separate (server-) room&lt;br /&gt;
* it provides precise control over which event is to be recorded.&amp;lt;br&amp;gt;For example, for clicks, there are alternative ways to record: as &amp;quot;press-release&amp;quot;, as &amp;quot;click&amp;quot;, as &amp;quot;move-then-click&amp;quot;, as &amp;quot;move-then-press-delay-release&amp;quot;. Depending on the page&#039;s underlying event handling (typically done in JavaScript), either one may be required.&lt;br /&gt;
&lt;br /&gt;
Once connected to a browser, the integrated recorder can be used to record a test case. Start the recorder by selecting the appropriate connection in the GUI browser&#039;s left tree and click the &#039;&#039;record&#039;&#039; button. The recorder opens a new window. Each click in the window records an action. More actions are available in the menu. Recorded actions are added to the &#039;&#039;workspace&#039;&#039; of the GUI browser to form a sequence of interactions. This sequence can be edited, parametrized or replayed immediately. When finished, it should be saved into the suite as a new &amp;quot;Test Action&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
General actions can be found either directly in the menu bar or there in the Browser Tools menu (see below). To record actions on elements, either change the selection of the element tool in the menu bar (see below) and click on the element or select the corresponding action from the context menu by right-clicking on the element. For text input, you can also place the cursor over the element and enter the text. The input dialog for this action opens. It is also possible to record the imputs &#039;&#039;backspace&#039;&#039;, &#039;&#039;return&#039;&#039; and &#039;&#039;tab&#039;&#039; that way.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverRecorder.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Components of the recorder window&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Pause recording&#039;&#039;&#039;: If the control lamp is red, the recorder is in &amp;quot;&#039;&#039;recording&#039;&#039;&amp;quot;-mode. Pause the recording by clicking on this lamp. The lamp will turn to grey. In this state you can execute actions with the recorder, but they are not recorded. Click again to resume the recording.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Update the screenshot on the element tree. Necessary if the recorder view does not fit the browser content.&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: The element under the cursor is selected in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the cursor gets a red frame.&lt;br /&gt;
#&#039;&#039;&#039;Element Tools&#039;&#039;&#039;: Select which tool to use for recording. You can choose between all actions that use a certain element. The selected action is triggered by each click in the view and the element is determined by the click position. Not selected actions are available by right click.&lt;br /&gt;
#&#039;&#039;&#039;Browser Tools&#039;&#039;&#039;: Actions not refering to ocertain elements, like scrolling or actions on the current URL or the title, can be triggered here.&lt;br /&gt;
#&#039;&#039;&#039;Page navigation&#039;&#039;&#039;: Actions for page navigation: &#039;&#039;Back&#039;&#039;, &#039;&#039;Forward&#039;&#039; and &#039;&#039;Refresh Page&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Alert Handling&#039;&#039;&#039;: Click this button if the browser shows an alert, to be able to select the actions for alert handling.&lt;br /&gt;
#&#039;&#039;&#039;Online Documentation&#039;&#039;&#039;: Open this online documentation.&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the browsers. Actions can be triggered by mouse depending on the selected tool. If a new action can be entered, the frame of the window is green, red otherwise. Scrolling is forwarded to the browser, but not recorded.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Screen Size&#039;&#039;&#039;: Change the size of the window to show the whole screenshot.&lt;br /&gt;
#&#039;&#039;&#039;Set Screen Scale to Fit Window&#039;&#039;&#039;: Scale the screenshot to fully fit in the window&lt;br /&gt;
#&#039;&#039;&#039;Scale&#039;&#039;&#039;: Changes the scale of the screenshot. Can also be adjusted by scrolling with pressed &amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt; key.&lt;br /&gt;
#&#039;&#039;&#039;Notifications&#039;&#039;&#039;: Shows notifications, e.g. if an action cannot be recorded. The last notification is displayed until it is closed by the button on its right side.&amp;lt;br&amp;gt;&#039;&#039;&#039;Window Tabs&#039;&#039;&#039;: As of expecco 23.1, tabs are displayed above the display for each open window as soon as a connection has more than one browser window. Whether the browser displays this as a tab or in its own window does not matter. You can use the tabs in the recorder to switch the current window and also record this switch.&amp;lt;br&amp;gt;&#039;&#039;&#039;Frame context&#039;&#039;&#039;: As of expecco 23.1, you can see below the display in which frame context you are currently in (see the section [[#Embedded_Content|Embedded Content]]). You can click on the entries to switch to a higher context and record this switch. If you have compound paths enabled, the display will update when you select an embedded item.&lt;br /&gt;
&lt;br /&gt;
=Embedded Content=&lt;br /&gt;
In HTML it is possible to include content from another page within one page. The most common element to do this is an iframe (inline frame). The content of an iframe can also be accessed with Selenium, but first you have to switch to this context. In the SeleniumWebDriverLibrary there are corresponding blocks to switch to the context of an iframe, to switch to the parent context and to switch back to the default content, i.e. the top context. All element blocks always resolve the applied paths within the current context. In the GUI browser, you will see an additional element for embedded content, which you can expand to see its elements.&lt;br /&gt;
&lt;br /&gt;
==Compound Paths==&lt;br /&gt;
Since expecco 23.1 there is the possibility to also use compound paths at the blocks to access the content of an iframe directly from the standard content. For this purpose, simply the path to the iframe and the path within the iframe content are combined into one. It is important here that no elements may be omitted at the transition, i.e. the front part must end with the iframe element and the back part must begin with &#039;&#039;/body&#039;&#039;. In between the paths may be shortened and it is of course also possible to access elements nested to any depth in this way. Both techniques can be used on the blocks as desired, the only important thing is that the paths are always resolved in the context in which Selenium is currently located.&lt;br /&gt;
&lt;br /&gt;
If you want to record the combined paths or use them in the GUI Browser, check the box &#039;&#039;Record Compound Paths&#039;&#039; in the &#039;&#039;GUI Browser&#039;&#039; menu under &#039;&#039;Recording&#039;&#039;. This will create and display a compound path for embedded elements relative to the current context, instead of only within its own context as before. You can also address these elements directly in the recorder or find them via Follow-Mouse.&lt;br /&gt;
&lt;br /&gt;
=Shadow Elements=&lt;br /&gt;
Shadow DOMs allow you to encapsulate parts of a page from the remaining document. They provide a way to attach hidden shadow elements to an element. You can find a more detailed explanation for example here: [https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM Using shadow DOM - Web APIs | MDN].&lt;br /&gt;
&lt;br /&gt;
The SeleniumWebDirverLibrary has the block &#039;&#039;[Web] Get Shadow DOM&#039;&#039;, which gives you the topmost elements, which then can be used like other WebElements.&lt;br /&gt;
&lt;br /&gt;
As the elements are hidden, they are not directly displayed in the GUI browser. However, since expecco 23.1 you can check in the context menu of the elements in the GUI browser the option to find shadow elements. They then will be displayed when updating the children of an element, if there are any, but not when updating the whole tree. If the option is checked, the elements are also available in the recorder.&lt;br /&gt;
&lt;br /&gt;
==Compound Paths==&lt;br /&gt;
Similar to elements inside a frame, shadow elements can be accessed by compound paths. These paths can be used directly at the library blocks and the block &#039;&#039;[Web] Get Shadow DOM&#039;&#039; is not required. The paths are of the form&lt;br /&gt;
 &amp;lt;host path&amp;gt;/shadowRoot/&amp;lt;shadow path&amp;gt;&lt;br /&gt;
where &#039;&#039;&amp;lt;host path&amp;gt;&#039;&#039; denotes the path to the element that has the shadow DOM attached, and &#039;&#039;&amp;lt;shadow path&amp;gt;&#039;&#039; denotes the path inside the shadow DOM to the desired element. &#039;/shadowRoot&#039; serves as marker where the switch to the shadow DOM is needed.&lt;br /&gt;
&lt;br /&gt;
=Authentication Alerts=&lt;br /&gt;
If a Web page uses HTTP authentication with Basic Authentication, an alert window for entering the user name and password opens when the page is loaded. This window cannot be accessed directly with Selenium. In the GUI browser, it is displayed as an alert. An exception to this is Chrome, where the driver does not respond to any request as long as the dialog is open. At this point, the plugin cannot even determine whether an authentication dialog is open or whether the driver is not responding for other reasons.&lt;br /&gt;
&lt;br /&gt;
For local connections under Windows, authentication can be performed using Windows Access. In the SeleniumWebDriverLibrary there are specific authentication blocks for individual browser types as well as the block &#039;&#039;Authenticate at Alert&#039;&#039;, which executes the corresponding block depending on the connection. There are different restrictions for the different browser types:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Chrome:&#039;&#039;&#039; The credentials are sent to a chrome window, so it only works if not more than one are open. In this case, the single block has the option to specify the title of the window.&lt;br /&gt;
:&#039;&#039;&#039;Edge&#039;&#039;&#039;: With Microsoft Edge a login is not supported.&lt;br /&gt;
:&#039;&#039;&#039;Firefox&#039;&#039;&#039;: Sends the credentials to a Firefox dialog box and therefore only works if there are not multiple ones.&lt;br /&gt;
:&#039;&#039;&#039;Internet Explorer&#039;&#039;&#039;: With Internet Explorer a login is not supported.&lt;br /&gt;
&lt;br /&gt;
As an additional option, you can also log in using the URL. Instead of the page &amp;lt;nowiki&amp;gt;https://www.example.com&amp;lt;/nowiki&amp;gt; call the URL &amp;lt;nowiki&amp;gt;https://user:password@www.example.com&amp;lt;/nowiki&amp;gt;. It is important that &#039;&#039;:&#039;&#039; and &#039;&#039;@&#039;&#039; do not appear in the user name or password. This method may not be supported by every browser.&lt;br /&gt;
&lt;br /&gt;
With the [[WindowsAutomation_Reference_2.0/en|WindowsAutomation2]]-Plugin it is also possible to execute such a login with all browser types.&lt;br /&gt;
&lt;br /&gt;
=Transferring Old Selenium Tests=&lt;br /&gt;
This Plugin replaces the previous [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]], which is based on [https://www.seleniumhq.org/projects/remote-control/ Selenium RC]. Selenium RC is no longer supported by their authors and it will also no longer be maintained by exept. The successor is [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver], also referred to as Selenium 2. &lt;br /&gt;
&lt;br /&gt;
Recording of test actions using [https://www.seleniumhq.org/projects/ide/ Selenim IDE] is also outdated, as the plugin is not supported by newer browsers. The &#039;&#039;Selenium WebDriver Plugin&#039;&#039; uses its own [[#Recorder|Recorder]] instead.&lt;br /&gt;
&lt;br /&gt;
Tests which were created with the old &#039;&#039;Selenium WebTest Plugin&#039;&#039; using SeleniumLibrary can be executed with the new Selenium WebDriver. &lt;br /&gt;
For this, go to the plugin settings of &amp;quot;&#039;&#039;Webtest Legacy (Selenium)&#039;&#039;&amp;quot; and check &amp;quot;&#039;&#039;Use WebDriver for execution&#039;&#039;&amp;quot;. Please verify that your tests are still running after this change, as there is no 100% backward compatibility (which is outside the scope of expecco). However, most of the old test actions should run without problems.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*&#039;&#039;&#039;Scrollbars cannot be handled in the recorder&#039;&#039;&#039;&lt;br /&gt;
:The scrollbar of the browser which is diplayed if a page is larger than the browser window is no controllable web element. Mostly it is useless to scroll by a certain amount in a test where the size of the browser window is not defined. Instead, use the block &amp;lt;code&amp;gt;[Web] Scroll Element into View&amp;lt;/code&amp;gt; to scroll a relevant element to the visible region. The default click block used by the recorder already includes this action (&amp;lt;code&amp;gt;[WebElement] Click (Scroll Element into View)&amp;lt;/code&amp;gt;). If you scroll on the recorder window, the action will also be applied to the browser, but is not recorded. If you actually want to scroll by a certain amount, there is an appropriate entry in the browser actions, and more blocks in the SeleniumWebDriverLibrary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Block fails if element becomes visible too late&#039;&#039;&#039;&lt;br /&gt;
:All blocks that use an element path have built in that they wait until a corresponding element appears. However, there are cases where an element is already there, but not yet visible. If you click on the element you will get an error. Possible errors in this context are &amp;lt;code&amp;gt;org.openqa.selenium.ElementNotInteractableException: element not interactable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;. In this case, use the &amp;lt;code&amp;gt;[Web] Wait for Visibility of Element&amp;lt;/code&amp;gt; block or &amp;lt;code&amp;gt;[Web] Wait for Element to Be Clickable&amp;lt;/code&amp;gt; before interacting with the element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Error message &amp;lt;code&amp;gt;Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:The error &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt; can occur with the Chrome browser. This means that the used element is not visible. See the point above on that. The error is also known in combination with elements in a dropdown list, i.e. when clicking or moving the mouse over a &amp;lt;nowiki&amp;gt;&amp;lt;option&amp;gt;&amp;lt;/nowiki&amp;gt; element within a &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt; element. Such elements are generally not clickable. Instead, use a suitable &amp;lt;code&amp;gt;[Web] Select&amp;lt;/code&amp;gt; block with the &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt; element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Error message: &amp;lt;code&amp;gt;Stale Element Reference Exception&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:The error &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; occurs whenever a WebElement is used that is no longer there. If that happens during your test and the element should have been there, try using the locator instead to fetch the element again. Maybe the error occurs because the test is currently in a different frame context as the element. If you are using [[#Compound_Paths|compound paths]], the element should switch by itself to the correct context when it is used.&lt;br /&gt;
:In rare cases this error can also occur in expecco itself, if at somewhere in the GUI browser or the recorder such a WebElement is used. You should then be able to abort and try again. Should the error persist, switch to the default content and refresh the tree in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Block runs successfully, but without effect&#039;&#039;&#039;&lt;br /&gt;
:This case can occur with Chrome. The element is available, the action does not throw an error, but nothing is executed. Usually it helps to wait briefly before the execution, see [[#Execution_Delay_for_Chrome | Execution Delay for Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Executions using Chrome are slower&#039;&#039;&#039;&lt;br /&gt;
:To fix a problem when executing with Chrome, a delay is defined in the plugin settings for Chrome. Check if this value is possibly too high; see [[#Execution_Delay_for_Chrome | Execution Delay for Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Errors like: &amp;quot;org.openqa.selenium.InvalidArgumentException: Expected &amp;quot;handle&amp;quot; to be a string...&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
:This occurs if the driver does not match the browser (any more). Please read the above chapter &amp;quot;[[#Update WebDriver|Update WebDriver]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Key Chords with Shortcuts are not working&#039;&#039;&#039;&lt;br /&gt;
:Pressing keys simultaneously can be simulated using Key Chords. They can also be used to send shortcuts. However, not all inputs will work, as they are only sent to the page content, not to the browser itself. Combinations like &#039;&#039;Ctrl + t&#039;&#039; to open a new browser tab probably wont&#039;t work, &#039;&#039;Ctrl + a&#039;&#039; and &#039;&#039;Ctrl  c&#039;&#039; on the other hand should be effective.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Additional Window Handles for Opera&#039;&#039;&#039;&lt;br /&gt;
:The Opera browser returns more window handles as there are opened tabs or windows. They represent Opera internal features like &#039;&#039;Speed Dial&#039;&#039; or &#039;&#039;Better Address Bar Experience&#039;&#039; (BABE), which are embedded in the browser window, but not displayed like regular tabs. You can switch to these tabs using an appropriate action block, however not all actions are possible then, which can be used with the normal tabs. For example you cannot close them and they don&#039;t provide a screenshot. Therefore it is better to not even switch to their contexts. So be careful when switching to a tab by index, as the Opera tabs are among the others and the index might be a different one than for the other browser types.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Chrome: Choose your search engine&#039;&#039;&#039;&lt;br /&gt;
:Newer versions of Chrome show an [https://www.google.com/chrome/choicescreen/ overlay] at startup, where you have to choose a search engine. Usually, this choice is saved in the user profile. However, if you don&#039;t explicitly set a Chrome profile for the connection, each connect will use an empty profile and this question will always show up.&lt;br /&gt;
&lt;br /&gt;
:In most cases, the test can run in the back despite the overlay. However, the overlay counts as tap or window, meaning the block &#039;&#039;[Web] Get Window Handles&#039;&#039; for an example returns a window handle for it and you can switch to it. But you have options to get rid of it:&lt;br /&gt;
:* &#039;&#039;--disable-search-engine-choice-screen&#039;&#039;: In the [[#Advanced_Settings|advanced settings]] you can add the option &amp;lt;code&amp;gt;--disable-search-engine-choice-screen&amp;lt;/code&amp;gt; and the overlay won&#039;t show up.&lt;br /&gt;
:* &#039;&#039;Choose&#039;&#039;: You can extend your test, so it actually chooses a search engine and closes the overlay. There are two things you need to bear in mind. First, you have to switch there using a &#039;&#039;Switch to Window&#039;&#039; block (e.g. by index &#039;&#039;2&#039;&#039; or with an empty title) and back to your original tab afterwards as well. Secondly, the interesting elements in the overlay are [[#Shadow_Elemens|shadow elements]] and as such not directly displayed in the GUI-Browser.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29679</id>
		<title>Selenium WebDriver Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Selenium_WebDriver_Plugin&amp;diff=29679"/>
		<updated>2024-08-05T13:11:04Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* FAQ */ Chrome: Wähle deine Suchmaschine&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Selenium_WebDriver_Plugin/en|English Version]]&lt;br /&gt;
=Achtung=&lt;br /&gt;
Das Webtest Selenium WebDriver Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Zur Automatisierung wird [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver] verwendet (Driver für gängige Browser werden von uns mitgeliefert), der das bisher verwendete Selenium RC ersetzt. Dies wurde einerseits notwendig, da die SeleniumRC Schnittstelle von neuen Browsern nicht mehr unterstützt wird, andererseits, sinnvoll, da auch andere UI Technologien mit diesem Protokoll angesprochen werden können. &lt;br /&gt;
&lt;br /&gt;
Sie können dieses Protokoll nur noch mit älteren Browsern verwenden, und wir empfehlen dringend, auf die neue Version umzusteigen. &amp;lt;br&amp;gt;Hinweise zur Migration älterer Testsuiten finden Sie [[#Portierung_alter_Selenium-Tests | unten]].&lt;br /&gt;
&lt;br /&gt;
=Einleitung=&lt;br /&gt;
Mit dem Selenium WebDriver Plugin können Sie Tests von Webapplikationen erstellen oder auch diese automatisieren (*). Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests oder automatisierten Browseraktionen unterstützt. Zudem ist damit das Aufzeichnen von Abläufen möglich.&lt;br /&gt;
&lt;br /&gt;
(*) tatsächlich gibt es auch WebDriver-Schnittstellen um z.B. Windows-Apps oder OPS-Fenster zu manipulieren. Insofern gibt es für dieses Plugin weitere Einsatzbereiche.&lt;br /&gt;
&lt;br /&gt;
=Einstellungen=&lt;br /&gt;
Das Plugin verwendet die Java-Bridge und benötigt daher eine Java-Installation. Sie können diese in den Einstellungen unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Java Bridge&#039;&#039; angeben. Wichtig ist hier das Feld &#039;&#039;Pfad zur Java-Installation&#039;&#039;, wo Sie ein JDK oder JRE angeben können. Ist nichts angegeben, versucht expecco java im PATH zu finden.&lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|600px]]&lt;br /&gt;
&lt;br /&gt;
Für das Selenium WebDriver Plugin selbst gibt es ebenfalls Einstellungsmöglichkeiten, die Sie unter &#039;&#039;Erweiterungen&#039;&#039; -&amp;gt; &#039;&#039;Webtest (Selenium WebDriver)&#039;&#039; finden. Hier können Sie zum Beispiel die Adresse zu einem remote laufenden Selenium-Server angeben oder eine andere Jar-Datei für Selenium angeben. Einstellungen zu den verschiedenen Browser-Typen teilen sich auf die Unterseiten &#039;&#039;Beliebte Browser&#039;&#039; und &#039;&#039;Andere Browser&#039;&#039; auf. Dort können Sie den Pfad zur Browser-Ausführungsdatei oder zum Webdriver angeben, der verwendet werden soll. Diese Felder können Sie alle leer lassen, expecco wird dann automatisch danach suchen.&lt;br /&gt;
&lt;br /&gt;
=Browser-Unterstützung=&lt;br /&gt;
Das Plugin unterstützt die Browser Chrome/Chromium, Edge, Firefox, Internet Explorer und Opera. &lt;br /&gt;
&amp;lt;br&amp;gt;Safari unter OSX muss zumindest in der Version 10 vorliegen und OSX muss mindestens die El Capitan Version sein.&lt;br /&gt;
Zur Kommunikation wird die WebDriver Schnittstelle verwendet; somit kann der getestete Browser sowohl lokal als auch auf einem entfernten Rechner laufen.&lt;br /&gt;
&lt;br /&gt;
Da inzwischen eine Vielzahl von weiteren Browsen, Geräten und graphischen Oberflächen eine WebDriver Schnittstelle anbieten, können auch diese - z.T. mit eingeschränktem Funktionsumfang - über diese automatisiert werden. So gibt es z.B. auch Schnittstellen für Windows Mobilgeräte oder Desktopanwendungen.&lt;br /&gt;
&lt;br /&gt;
== WebDriver aktualisieren==&lt;br /&gt;
Für jeden Browsertyp gibt es einen Driver, über den das Starten und Ansteuern der Browserfenster funktioniert. Für die wichtigsten Browser finden sich im Lieferumfang aktuelle Driverversionen. Da die Browser fortlaufend aktualisiert werden, teilweise sogar automatisch, müssen Sie früher oder später neue Driverversionen herunterladen. Legen Sie diese dann in Ihrem expecco-Installationsverzeichnis bei den anderen Versionen ab, und zwar unter:&lt;br /&gt;
 &amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib/XXX&amp;lt;/code&amp;gt;&lt;br /&gt;
(unter Microsoft Windows Betriebssystemen mit &amp;quot;\” anstatt &amp;quot;/&amp;quot;), wobei &amp;quot;XXX&amp;quot; für das Betriebssystem steht (Windows, Linux, OSX etc.).&lt;br /&gt;
&lt;br /&gt;
Im Verbindungsdialog warnt expecco, wenn eine Driverversion nicht zur Browserversion passt. In manchen Fällen kann das aber auch nur daran liegen, dass  diese Version zum Zeitpunkt der Auslieferung noch nicht bekannt war. Manche Kombinationen können trotz der Warnung funktioniert, aber das können wir im Einzelfall nicht garantieren.&lt;br /&gt;
&lt;br /&gt;
Daher können Sie bei einer solchen Warnung immer die Option &amp;quot;&#039;&#039;Diese Warnung nicht mehr anzeigen&#039;&#039;&amp;quot; anwählen, damit diese Driver-Browser-Versionskombination in ihren Settings als &amp;quot;kompatibel&amp;quot; vermerkt wird, und in Zukunft nicht mehr gemeldet wird. Dies sollten Sie aber nur machen, wenn Sie sicher sind, dass Ihre Tests nach wie vor korrekt ausgeführt werden. Da wir hier selbst bisweilen auf Kompatibilitätsprobleme stoßen, und nicht immer gleich klar ist, woran es liegt, empfehlen wir aber den Driver zu aktualisieren.&lt;br /&gt;
&lt;br /&gt;
Für Chrome und Microsoft Edge, bei denen es für jede neue Browserversion auch eine neue Driverversion gibt, finden Sie im Verbindungsdialog einen Button, um mit expecco die passende Version herunterzuladen.&lt;br /&gt;
&lt;br /&gt;
Neuere Versionen der Driver bekommen Sie an folgenden Adressen:&lt;br /&gt;
{|&lt;br /&gt;
|Chrome/Chromium&lt;br /&gt;
|[https://sites.google.com/chromium.org/driver/ ChromeDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Edge&lt;br /&gt;
|[https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ Microsoft WebDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Firefox&lt;br /&gt;
|[https://github.com/mozilla/geckodriver/releases GeckoDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Internet Explorer&lt;br /&gt;
|[https://selenium-release.storage.googleapis.com/index.html IEDriverServer]&lt;br /&gt;
|-&lt;br /&gt;
|Opera&lt;br /&gt;
|[https://github.com/operasoftware/operachromiumdriver/releases OperaDriver]&lt;br /&gt;
|-&lt;br /&gt;
|Safari&lt;br /&gt;
|[https://webkit.org/blog/6900/webdriver-support-in-safari-10 Safari Support]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Laden Sie sich eine passende Version herunter und legen Sie sie im oben genannten Verzeichnis an der entsprechenden Stelle ab. Expecco wird sie dann finden und verwenden. &amp;lt;!-- Sie können den Namen der Datei erweitern, um mehrere Versionen nebeneinander verwenden zu können. --&amp;gt; Alternativ können Sie auch in expecco den Pfad zu einem Driver angeben, entweder im [[#Erweiterte_Einstellungen | Verbindungseditor]] oder in den [[#Plugin-Einstellungen | Plugin-Einstellungen]].&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Bitte verifizieren Sie, daß die Version des Drivers kompatibel ist mit der des Browsers. Im Zweifel suchen Sie nach der Versionshistorie (z.B. für Chrome: https://chromedriver.storage.googleapis.com/2.25/notes.txt).&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Für den Internet Explorer ist zu beachten, dass der geschützte Modus für alle Zonen gleich eingestellt sein muss, damit eine Verbindung möglich ist. (im Internet Explorer: &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Internetoptionen&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Sicherheit&#039;&#039;&amp;quot; öffnen, und bei allen 4 Zonen &amp;quot;geschützter&amp;quot; Bereich gleich einstellen; ansonsten kommen beim Verbindungsaufbau Fehler- und Warndialoge). Siehe außerdem die [https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver#required-configuration erforderliche Konfiguration] zur Verwendung des InternetExplorerDrivers.&lt;br /&gt;
&lt;br /&gt;
[[Datei:bulb.png|20px]]Das Plugin verwendet für einige Funktionen JavaScript. Stellen Sie daher sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist, insbesondere wenn Sie den GUI-Browser oder den Recorder verwenden wollen. Das Ausführen von Tests ist auch ohne JavaScript möglich, solange keine Aktionen verwendet werden, welche JavaScript benötigen oder explizit ausführen.&amp;lt;br&amp;gt;Sollten Sie einen Fehler der Art &amp;quot;&amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: Error executing JavaScript&amp;lt;/code&amp;gt;&amp;quot; bekommen, stellen Sie sicher, dass die Ausführung von JavaScript im verwendeten Browser erlaubt ist und Browser- und zugehörige WebDriver-Version kompatibel sind.&lt;br /&gt;
&lt;br /&gt;
= Headless Browser =&lt;br /&gt;
Mit &amp;quot;&#039;&#039;Headless&#039;&#039;&amp;quot; bezeichnet man eine Anwendung, welche ohne Bedienoberfläche abläuft. Einige der Browser unterstützen einen &amp;quot;headless&amp;quot; Modus,  bei dem kein Browserfenster angezeigt wird. Der Browser operiert dabei in einem &amp;quot;unsichtbaren Fenster&amp;quot; führt aber alle Operationen aus, und liefert auch die selbe Elementhierarchie.&lt;br /&gt;
Bei einigen Browsern sind allerdings die Screenshot (Bild vom Fenster bzw. von Elementen) eingeschränkt bzw. gar nicht verfügbar.&amp;lt;br&amp;gt;Den &amp;quot;headless&amp;quot; Modus können Sie beim Verbindungsaufbau in den &amp;quot;&#039;&#039;Advanced Settings&#039;&#039;&amp;quot; angeben.&lt;br /&gt;
&lt;br /&gt;
= HTML Unit Browser =&lt;br /&gt;
Bei diesem &amp;quot;&#039;&#039;Pseudobrowser&#039;&#039;&amp;quot; handelt es sich um eine weitere &amp;quot;&#039;&#039;headless&#039;&#039;&amp;quot; Variante, welche ganz ohne Renderengine operiert, und lediglich die Elementhierarchie sowie Javascript unterstützt. Sein Verhalten kann stark von dem &amp;quot;echter&amp;quot; Browser abweichen.&lt;br /&gt;
&lt;br /&gt;
Diesen Browsertyp können Sie verwenden, wenn ihr Test das Verhalten des Webservices (also der Servierseite) betrifft, und nicht das Verhalten der Anwendung im Browser (End-User-Experience) im Fokus hat. Zum Beispiel kann der &amp;quot;HTML Unit Browser&amp;quot; zum Generieren von Last oder gleichzeitigen Aktionen gegenüber dem Server dienen.&lt;br /&gt;
Da sich dieser Browser im Verhalten z.T. stark von dem echter Browser unterscheidet sollte er nur (wenn überhaupt) in besonderen Fällen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
= Schneller Einstieg =&lt;br /&gt;
== Browser öffnen / verbinden ==&lt;br /&gt;
* Starten Sie expecco&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Neue Testsuite&#039;&#039;&amp;quot;&lt;br /&gt;
* Klicken Sie auf das GUI-Browser Symbol ([[Datei:GUIBrowser.png|24px]])&lt;br /&gt;
* Es erscheint der GUI-Browser in einem neuen Reiter&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; und wählen Sie &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot; aus. Dann erscheint der [[#Verbindungseditor | Verbindungsdialog]] (Details siehe unten)&lt;br /&gt;
* Im Verbindungsdialog geben Sie die zu testende Webseite ein (z.B. &amp;quot;&amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://www.myHost.com&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&amp;quot;) und wählen den Browsertyp (z.B. &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; oder &amp;quot;&amp;lt;code&amp;gt;firefox&amp;lt;/code&amp;gt;&amp;quot;) aus&lt;br /&gt;
* Klicken Sie auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot;&lt;br /&gt;
* Ein Browser wird nun automatisch gestartet, und die Seite angezeigt.&lt;br /&gt;
* Sobald die Verbindung steht, wird im GUIBrowser die Seitenstruktur als Baum angezeigt, und im rechten Diagramm-Fenster erscheint ein passender Verbindungsbaustein. Dieser wird nicht automatisch aufgezeichnet, da man diesen normalerweise nicht in jeder aufgezeichneten Sequenz haben will (mehr dazu unten).&lt;br /&gt;
&lt;br /&gt;
== Recording aufnehmen ==&lt;br /&gt;
* Klicken Sie auf das Recording Symbol im GUI-Browser.&lt;br /&gt;
[[Datei:Recording_Start.png | 200px]]&lt;br /&gt;
* Ein Recorderfenster erscheint (eine Beschreibung der Bedienelemente finden Sie unten)&lt;br /&gt;
* Sie zeichnen nun direkt im Rekorder auf.&amp;lt;br&amp;gt;&lt;br /&gt;
* Klicks werden je nach Einstellung als Klick, Mausbewegung, Drag&amp;amp;Drop etc. aufgezeichnet.&amp;lt;br&amp;gt;Während der Aufzeichnung können Sie zwischen diesen Werkzeugen wechseln:&amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:Recorder_Werkzeuge.png | 300px]]&lt;br /&gt;
* die aufgezeichneten Aktionen werden im Tab &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; dargestellt. Sie können dort noch bearbeitet werden.&lt;br /&gt;
* Zum Beenden der Aufzeichnung klicken Sie entweder auf den &amp;quot;&#039;&#039;Stop Recording&#039;&#039;&amp;quot; Knopf im GUI Browser, oder schließen das Rekorderzenster. Es ist auch möglich, das Aufzeichnen temporär zu Pausieren, indem sie im Rekorder auf den &amp;quot;&#039;&#039;Aufnahme&#039;&#039;&amp;quot;-Knopf oben links drücken.&lt;br /&gt;
* Nach dem Aufzeichnen können sie die Sequenz un ihre Testsuite als Testfall oder Teilsequenz übernehmen.&lt;br /&gt;
&lt;br /&gt;
== Aufgezeichnete Aktion wiedergeben ==&lt;br /&gt;
&lt;br /&gt;
* Im Reiter &amp;quot;&#039;&#039;Aufgezeichnete Sequenz&#039;&#039;&amp;quot; kann die aktuelle Aufzeichnung sofort wiedergegeben werden (&amp;quot;&#039;&#039;Play&#039;&#039;&amp;quot;-Knopf drücken)&amp;lt;br&amp;gt;Beachten Sie, daß ihre Webseite üblicherweise im gleichen Zustand sein sollte - gegebenenfalls sollten Sie also den &amp;quot;&#039;&#039;Back&#039;&#039;&amp;quot;-Knopf oder eine andere Navigation anwenden, um dies sicher zu stellen.&lt;br /&gt;
* Die Sequenz kann bearbeitet werden. Dazu können entweder weitere Aktionen aufgenommen werden, oder zusätzliche Aktionen entweder via Drag&amp;amp;Drop oder über das Kontextmenü (bzw. &amp;lt;kbd&amp;gt;&amp;lt;CTRL-N&amp;lt;/kbd&amp;gt;) angelegt werden. Häufig werden zusätzliche Delay- oder Verifikations-Bausteine benötigt, die sie hiermit an geeigneter Stelle einfügen können.&lt;br /&gt;
&lt;br /&gt;
=Verbindungsaufbau=&lt;br /&gt;
==&amp;lt;span id=&amp;quot;Verbindungsdialog&amp;quot;&amp;gt;Verbindungseditor==&lt;br /&gt;
Mit dem Verbindungseditor werden Verbindungen definiert, geändert und aufgebaut. Sie erreichen ihn, indem Sie den GUI-Browser öffnen und dort auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; klicken und dann &amp;quot;&#039;&#039;Selenium Testing (WebDriver)&#039;&#039;&amp;quot; auswählen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverConnectDialog.png]]&lt;br /&gt;
&lt;br /&gt;
#&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;: Öffnet einen Anhang im expecco Projekt mit Verbindungseinstellunge. Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen aus Datei&#039;&#039;: Öffnet eine gespeicherte Einstellungsdatei (*.csf). Diese Einstellungen werden in den Editor übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in JSON-Anhang speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen im JSON-Format als Anhang im expecco-Projekt anlegen.&lt;br /&gt;
#&#039;&#039;Einstellungen in Datei speichern&#039;&#039;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern.&lt;br /&gt;
#&#039;&#039;Versionsinfo&#039;&#039;: Zeigt ein Fenster mit den verwendeten Versionen des Selenium-Servers, des ausgewählten Browser und dessen Driver an.&lt;br /&gt;
#&#039;&#039;Online-Dokumentation&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;Verbindungsname&#039;&#039;: Tragen Sie hier den Namen ein, unter dem die Verbindung im GUI-Browser angezeigt werden soll. (Optional)&lt;br /&gt;
#&#039;&#039;Browsertyp&#039;&#039;: Wählen Sie hier aus, welchen Browser Sie verwenden möchten. Stellen Sie sicher, dass dieser installiert ist und die Version des verwendeten Drivers zur Browserversion passt.&lt;br /&gt;
#&#039;&#039;URL&#039;&#039;: Tragen Sie hier die URL ein, die zu Beginn aufgerufen werden soll. Sie können das Feld auch frei lassen, dann wird ein leeres Browser-Fenster geöffnet. Um eine lokale Datei zu öffnen, verwenden Sie das Schema &amp;quot;&amp;lt;code&amp;gt;file://&amp;lt;/code&amp;gt;&amp;quot;, z.B. &amp;quot;&amp;lt;code&amp;gt;file:///C:/Users/admin/Desktop/index.html&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
#&#039;&#039;Erweiterte Ansicht&#039;&#039;: Wechselt zur Ansicht für die Eingabe von [[#Erweiterte Einstellungen|erweiterten Einstellungen]].&lt;br /&gt;
#&#039;&#039;Informationen zum gewählten Browser&#039;&#039;: Hier wird der ausgewählte Browsertyp kurz vorgestellt.&lt;br /&gt;
#&#039;&#039;Informationen zu den Einstellungen&#039;&#039;: Hier wird angezeigt, welche Selenium-, Browser- und Driver-Version mit den aktuellen Einstellungen verwendet wird. Falls Sie [[#Erweiterte Einstellungen|erweiterten Einstellungen]] gesetzt haben, werden diese hier ebenfalls aufgelistet.&lt;br /&gt;
&lt;br /&gt;
===Warnung &amp;amp;uuml;ber m&amp;amp;ouml;gliche Inkompatibilit&amp;amp;auml;t ===&lt;br /&gt;
Manche Browser benötigen einen versionsspezifischen Webdriver, da die verwendeten Kommunikationsprotokolle unterschiedlich sein können. &lt;br /&gt;
&lt;br /&gt;
Da regelmässig neue Browserversionen erscheinen, und damit einhergehend auch neue Versionen des zug. Webdrivers benötigt werden, kann. es sein, dass die mit expecco mitgelieferten Webdriver nicht mehr zur aktuellen Browserversion passen. Dies trat in der Vergangenheit insbes. beim Chromebrowser mehrfach auf.&lt;br /&gt;
 &lt;br /&gt;
Um auf eventuelle Probleme hinzuweisen hält expecco intern eine Liste von Paaren der von exept bereits getesteten Browser- zu Webdriverversion. Falls ihr Browser aktueller ist, und nicht in der Liste enthalten ist, erscheint eine Warnung im Infobereich.&lt;br /&gt;
&lt;br /&gt;
Diese erscheint nur zu Ihrer Information - in den meisten Fällen funktioniert die Interaktion mit dem Browser auch dann. Allerdings ist es in jedem Fall sinnvoll, den Driver zu aktualisieren, um solche Probleme auszuschliessen.&lt;br /&gt;
Wenn die Kombination ohne Probleme läuft, ist es möglich, die aktuelle Kombination in die Liste einzutragen (drücken Sie dazu auf &amp;quot;Diese Kombination ist in Ordnung&amp;quot;). Dann erschient der Warndialog nicht mehr.&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Einstellungen===&lt;br /&gt;
Neben dem zu verwendenden Browser und der Start-URL kann man noch weitere Einstellungen für eine Verbindung vornehmen. Wechseln Sie dazu im Verbindungsmenü die Ansicht über den entsprechenden Menü-Eintrag. Je nachdem, welchen Browsertypen Sie ausgewählt haben, bekommen Sie andere Eingabefelder.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;Remote Server&#039;&#039;: Falls der Browser auf einem entfernten Rechner gestartet werden soll, starten Sie dort einen Selenium-Server und geben Sie dessen Adresse in diesem Feld an. Natürlich können Sie auch eine lokale Adresse angeben, wenn nicht automatisch ein Selenium-Server gestartet werden soll. Lesen Sie hierzu auch den nächsten Abschnitt [[#Remote-Verbindungen|Remote-Verbindungen]].&lt;br /&gt;
*&#039;&#039;Binary&#039;&#039;: Geben Sie den Pfad zum Binary des ausgewählten Browsers an, wenn dieser nicht automatisch von Selenium gefunden wird oder Sie eine weitere Version installiert haben.&lt;br /&gt;
*&#039;&#039;Driver&#039;&#039;: Zu jedem Browser wird ein spezieller Driver zur Automatisierung benötigt. Für neue Versionen des Browsers braucht man häufig auch eine neue Version des entsprechenden Drivers. Wenn Sie nicht den von expecco installierten Driver verwenden wollen, geben Sie hier einen entsprechenden Pfad an.&lt;br /&gt;
*&#039;&#039;Firefox Profile&#039;&#039;: Für Firefox gibt es zusätzlich die Möglichkeit, ein Profil bzw. Template anzugeben, das spezifische Einstellungen enthält. Wenn keines angegeben wird, wird für jede Verbindung ein neues, leeres Profil angelegt.&lt;br /&gt;
*&#039;&#039;Capabilities&#039;&#039;: Für Selenium-Verbindungen sind einige Capabilities definiert, mit denen sich Verbindungs-Eigenschaften oder auch das Browserverhalten festlegen lassen. &lt;br /&gt;
Solche Capabilities können Sie sie in diesem Feld angeben. Schreiben Sie dazu &#039;&#039;&amp;lt;capability name&amp;gt;: &amp;lt;value&amp;gt;&#039;&#039; oder &#039;&#039;&amp;lt;capability name&amp;gt; = &amp;lt;value&amp;gt;&#039;&#039;; jeweils ein Eintrag pro Zeile. Außerdem können Sie hier auch Eigenschaften für den Firefox-Browser setzen. Die Eingabe hierfür erfolgt wie für die Capabilities, nur dass sie dem Namen der Eigenschaft ein &#039;&#039;$&#039;&#039; voranstellen müssen.&lt;br /&gt;
&lt;br /&gt;
:Angegebene Capabilities werden durch die Methode &#039;&#039;setCapability()&#039;&#039; gesetzt. Insbesondere bei der Verwendung von Chrome gibt es einige Einstellungsoptionen, die sich nicht mit dieser Methode setzen lassen, sondern beispielsweise über &#039;&#039;setExperimentalOption()&#039;&#039; angegeben werden müssen. Zu diesem Zweck haben Sie außerdem die Möglichkeit, in diesem Feld einen Methodenaufruf mit Werten anzugeben. Diese Methode wird dann auf das entsprechende Options- bzw. Capabilities-Objekt angewandt. Um die Struktur der Eingabe von normalen Capabilities beizubehalten, müssen Sie am Ende noch &#039;&#039;:&#039;&#039; oder &#039;&#039;=&#039;&#039; setzen, aber keinen Wert danach. Beispiel: &#039;&#039;setExperimentalOption(“useAutomationExtension”, false)=&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Lokale-Verbindungen==&lt;br /&gt;
Um einen Browser auf ihrer lokalen Maschine zu starten, werden lediglich die Felder &amp;quot;&#039;&#039;URL&#039;&#039;&amp;quot; sowie &amp;quot;&#039;&#039;Browsertyp&#039;&#039;&amp;quot; benötigt. Als Voreinstellung für den Browser wird &amp;quot;&amp;lt;code&amp;gt;chrome&amp;lt;/code&amp;gt;&amp;quot; erscheinen.&lt;br /&gt;
&lt;br /&gt;
==Remote-Verbindungen==&lt;br /&gt;
Um einen Browser auf einem entfernten Rechner zu starten, müssen Sie zunächst den Selenium-Server und die benötigten Driver auf diesen Rechner kopieren. Auf dem Zielrechner muss Java installiert sein. Sie finden die Dateien in Ihrer expecco-Installation unter &amp;quot;&amp;lt;code&amp;gt;packages/exept/expecco/plugin/seleniumWebDriver/lib&amp;lt;/code&amp;gt;&amp;quot;. Sie können sich auch von [https://www.selenium.dev/downloads/ Selenium] eine aktuelle Version herunterladen.&lt;br /&gt;
&amp;lt;br&amp;gt;Starten Sie dann den Selenium-Sever (auf dem entfernten Rechner) mit:&lt;br /&gt;
 java -jar selenium-server-standalone-3.141.59.jar&lt;br /&gt;
(die Versionsnummer wird in Ihren Fall eine andere sein)&lt;br /&gt;
&lt;br /&gt;
Standardmäßig wird der Server dann auf dem Port 4444 Verbindungen annehmen. Um einen anderen Port zu verwenden, &lt;br /&gt;
geben Sie diesen auf der Kommandozeile mit &amp;quot;&amp;lt;code&amp;gt;-port &amp;amp;lt;nr&amp;amp;gt;&amp;lt;/code&amp;gt;&amp;quot; an. &lt;br /&gt;
&amp;lt;br&amp;gt;Um von expecco eine Verbindung über diesen Server herzustellen, geben Sie beim Verbindungsaufbau als Remote-Server &lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:4444/wd/hub&lt;br /&gt;
an.&lt;br /&gt;
&lt;br /&gt;
Das Starten des Selenium-Servers bzw. die Verbindung muss eventuell von der Firewall zugelassen werden.&lt;br /&gt;
&lt;br /&gt;
Falls der Server beim Verbinden die jeweiligen Driver nicht finden, legen Sie diese ins selbe Verzeichnis, in dem Sie den Server starten, oder fügen Sie das Verzeichnis in dem der Driver liegt zum Pfad hinzu. Beachten Sie dabei, dass expecco verschiedene Versionen eines Driver-Typs mitliefert und diese durch einen Namenszusatz unterscheidet. Aufgrund dieser Zusätze erkennt der Server die Dateien aber häufig nicht.&lt;br /&gt;
&lt;br /&gt;
Für neue Versionen von &#039;&#039;&#039;Microsoft Edge&#039;&#039;&#039;, die Chromium basieren, starten Sie anstatt eines Selenium-Servers direkt den MSEdgeDriver (&amp;quot;msedgedriver.exe&amp;quot;) in der Version, die zur Edge-Version auf diesem Rechner passt.&lt;br /&gt;
  msedgedriver.exe [--port=9515]&lt;br /&gt;
Wenn Sie keine Portnummer angeben, wird der Service auf dem Port 9515 gestartet. Geben Sie dann beim Verbindungsaufbau in expecco als Remote-Server die Adresse&lt;br /&gt;
 &amp;lt;Server-Adresse&amp;gt;:9515&lt;br /&gt;
an. Die Erweiterung &amp;quot;/wd/hub&amp;quot; ist hier nicht erforderlich.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsbausteine==&lt;br /&gt;
Der Verbindungsaufbau, welcher im GUI Browser interaktiv erfolgt, muss natürlich bei einem automatisierten Ablauf über einen Aktionsbaustein erfolgen.&lt;br /&gt;
Dazu gibt es in der SeleniumWebDriverLibrary im Ordner &amp;quot;&#039;&#039;Connection&#039;&#039;&amp;quot; verschiedene Bausteine, welche die Verbindungsparameter von verschiedenen Quellen erhalten:&lt;br /&gt;
* Connect&amp;lt;br&amp;gt;Dieser Baustein erhält die Verbindungsparameter über Eingangspins&lt;br /&gt;
* Connect from File&amp;lt;br&amp;gt;Hier werden die Einstellungen aus einer Datei (Anhang) gelesen (typischerweise im JSON Format)&lt;br /&gt;
* Connect from Spec&amp;lt;br&amp;gt;Die Verbindungsparameter werden in einem Dictionaryobjekt geliefert&lt;br /&gt;
* Reuse or Start Connection&amp;lt;br&amp;gt;Im Gegensatz zu obigen Bausteinen, welche immer eine neue Browserverbindung aufbauen (i.e. ein neues Browserfenster öffnen), wird dieser Baustein zunächst prüfen, ob bereits eine Verbindung besteht, und diese gegebenenfalls wiederverwenden. Dieser Baustein kann daher mehrfach (i.e. zu Beginn von Teilsequenzen) platziert werden, und damit die Teilsequenzen sowohl innerhalb eines komplexeren Gesamttests als auch &amp;quot;stand-alone&amp;quot;, d.h. einzeln ausgeführt werden.&lt;br /&gt;
&lt;br /&gt;
Alle &amp;quot;Connect&amp;quot; Bausteine benötigen die Angabe eines &amp;quot;&#039;&#039;Verbindungsnamens&#039;&#039;&amp;quot;.&lt;br /&gt;
Dieser hat die Aufgabe, die Verbindung im weiteren Testverlauf zu identifizieren, wenn zwischen mehreren Verbindungen gewechselt wird, und zum Abbauen der Verbindung. &lt;br /&gt;
&lt;br /&gt;
Wenn Sie im GUI Browser im Elementbaum auf eine Verbindung klicken, erscheint in der rechten &amp;quot;Test&amp;quot; Kachel ein Connect Baustein mit entsprechend vorgelegten Parametern. Diesen können Sie bei Bedarf gleich in die Rekordersequenz übertragen, oder (besser) als separate Aktion speichern (es ist sinnvoll, den Verbindungsaufbau von den aufgezeichneten Teilsequenzen zu trennen; damit haben Sie es später leichter, andere Browser zu verwenden, die Parameter der Verbindung zu ändern und auch neue Teilsequenzen aufzuzeichnen oder zu modifizieren.&lt;br /&gt;
&lt;br /&gt;
Verbindungen mit komplexen Einstellungen werden typischerweise im Verbindungsdialog angelegt, und die Einstellungen von dort über die Menüfunktion &amp;quot;&#039;&#039;Sichern in Anhang/Datei&#039;&#039;&amp;quot; in einer Datei gesichert. So können Sie verschiedene Konfigurationen in einzelnen Dateianhängen in ihrer Testsuite oder auch außerhalb aufbewahren. Zum Verbinden verwenden Sie dann den Aktionsbaustein &amp;quot;[&#039;&#039;Connect From File&#039;&#039;]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=Plugin-Einstellungen=&lt;br /&gt;
Wenn Sie eine bestimmte Browser-Installationen oder Driver standardmäßig als Voreinstellung verwenden möchten, können Sie diese in den Einstellungen des Plugins eintragen. Sie finden sie über das Menü unter dem Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Webtest (Selenium WebDriver)&#039;&#039;&amp;quot;. Einstellungen für spezifische Browser finden Sie unter den Unterpunkten &amp;quot;&#039;&#039;Beliebteste Browser&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;Andere Browser&#039;&#039;&amp;quot;.&lt;br /&gt;
Die dortigen Einstellungen gelten als Voreinstellung für jede Verbindung, es sei denn in einer konkreten Verbindungseinstellungen ist etwas anderes angegeben.&lt;br /&gt;
&lt;br /&gt;
===Ausführungsverzögerung für Chrome===&lt;br /&gt;
In manchen Fällen kann es bei Verwendung des Chrome-Browsers vorkommen, dass Bausteine mit Element-Aktionen, beispielsweise ein Klick, im Test erfolgreich durchlaufen, die eigentliche Aktion aber gar nicht ausgeführt wurde. Dies ist ein bekannter Fehler [https://github.com/MPDL/imeji-gui-testing/issues/37], [https://github.com/SeleniumHQ/selenium/issues/4075], der von Selenium bzw. chromedriver behoben werden muss.&lt;br /&gt;
&lt;br /&gt;
Der Fehler lässt sich verhindern, indem entweder der Klick über JavaScript aufgerufen wird&amp;amp;nbsp;(setzen Sie dazu im Klick-Baustein &#039;&#039;invokeDirectly&#039;&#039; auf &#039;&#039;true&#039;&#039;&amp;amp;nbsp;) oder vor der Aktion kurz gewartet wird. Die Ausführung über JavaScript hat den Nachteil, dass sie weniger nah am Klick eines echten Benutzers ist; beispielsweise funktionieren Klicks auf Elemente auch dann, wenn sie von anderen Elementen verdeckt werden (was bei einem &amp;quot;normalen&amp;quot;Klick nicht geht). &lt;br /&gt;
&lt;br /&gt;
Generell warten die Bausteine mit Element-Aktionen automatisch, bis das entsprechende Element verfügbar ist (existiert). In den hier beschriebenen Fällen reicht das aber nicht aus. Deshalb finden Sie in den Plugin-Einstellungen für Chrome die Einstellung &amp;quot;&#039;&#039;Ausführungsverzögerung&#039;&#039;&amp;quot;. Bei der Ausführung wird dann zwischen den Aktionen entsprechend lange gewartet. Falls bei Ihnen der beschriebene Fehler eintritt, können Sie diesen Wert erhöhen. Ein größerer Wert hat natürlich Auswirkung auf die Gesamtlaufzeit.&lt;br /&gt;
&lt;br /&gt;
=Recorder=&lt;br /&gt;
&lt;br /&gt;
Die folgende Beschreibung des Recorders gilt prinzipiell für alle von expecco unterstützten GUI Technologien. Verhalten und Bedienung sind bis auf kleine technologiebedingte Unterschiede für alle gleich.&lt;br /&gt;
&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung mit einem Browserfenster, kann der integrierte Recorder verwendet werden, um einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Für jeden Klick im Fenster wird eine Aktion aufgezeichnet. Weitere Aktionen stehen über das Menü zur Verfügung. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
Allgemeine Aktionen finden Sie entweder direkt in der Menüleiste oder dort im Browser-Werkzeuge-Menü (s.u.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Element-Werkzeugs in der Menüleiste (s.u.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion. Auf diese Weise ist es ebenfalls möglich, die Eingaben &#039;&#039;Backspace&#039;&#039;, &#039;&#039;Return&#039;&#039; und &#039;&#039;Tab&#039;&#039; aufzuzeichnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:SeleniumWebDriverRecorder.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Komponenten des Recorderfensters&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme Pausieren&#039;&#039;&#039;: Wenn die Kontrollleuchte rot ist, nimmt der Recorder auf. Durch Klicken können Sie die Aufnahme anhalten. Die Kontrolleuchte leuchtet dann grau. In diesem Zustand können Sie weiter Aktionen über das Recorder-Fenster ausführen, sie werden aber nicht aufgezeichnet. Klicken Sie erneut, um die Aufnahme weiterzuführen.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Browser. Dies wird nötig, wenn die Anzeige des Recorders nicht mit dem tatsächlichen Browserinhalt übereinstimmt. &lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Element-Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Es stehen alle Aktionen zur Verfügung, die auf ein bestimmtes Element ausgeführt werden. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst und das Element aus der Position bestimmt. Die nicht ausgewählten Aktionen sind jederzeit über einen Rechtsklick erreichbar. &lt;br /&gt;
#&#039;&#039;&#039;Browser-Werkzeuge&#039;&#039;&#039;: Aktionen die sich nicht auf bestimmte Elemente beziehen, wie Scrollen oder Aktionen auf die aktuelle URL oder den Titel, können hier ausgelöst werden.&lt;br /&gt;
#&#039;&#039;&#039;Seitennavigation&#039;&#039;&#039;: Aktionen zur Seitennavigation: &#039;&#039;eine Seite zurück&#039;&#039;, &#039;&#039;eine Seite vor&#039;&#039; und &#039;&#039;aktuelle Seite neu laden&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Alert-Behandlung&#039;&#039;&#039;: Wenn der Browser einen Alert anzeigt, klicken Sie auf diesen Button, um die Aktionen zur Alert-Behandlung auswählen zu können.&lt;br /&gt;
#&#039;&#039;&#039;Online Dokumentation&#039;&#039;&#039;: Öffnet diese Online-Dokumentation.&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Browsers. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot. Scrollen wird den Browser weitergeleitet, aber nicht aufgenommen.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots. Diese kann auch über Scrollen in der Anzeige bei gedrückt gehaltener Strg-Taste angepasst werden.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Hier werden Meldungen angezeigt, bspw. wenn eine Aktion nicht aufgenommen werden konnte. Die letzte Meldung wird solange angezeigt, bis sie über den Button rechts daneben geschlossen wird.&amp;lt;br&amp;gt;&#039;&#039;&#039;Fenster-Tabs&#039;&#039;&#039;: Ab expecco 23.1 werden oberhalb der Anzeige Tabs für jedes offene Fenster angezeigt, sobald eine Verbindung mehr als ein Browserfenster besitzt. Ob der Browser dieses als Tab oder in einem eigenen Fenster anzeigt, ist dabei egal. Über die Tabs im Recorder können Sie das aktuelle Fenster wechseln und diesen Wechsel auch aufzeichnen.&amp;lt;br&amp;gt;&#039;&#039;&#039;Frame-Kontext&#039;&#039;&#039;: Ab expecco 23.1 sehen Sie unterhalb der Anzeige, in welchem Frame-Kontext Sie sich gerade befinden (siehe dazu den Abschnitt [[#Eingebettete_Inhalte|Eingebettete Inhalte]]). Sie können auf die Einträge klicken, um in einen höheren Kontext zu wechseln und diesen Wechsel aufzuzeichnen. Falls Sie zusammengesetzte Pfade eingestellt haben, wird die Anzeige aktualisiert, wenn Sie ein eingebettetes Element ausgewählt haben.&lt;br /&gt;
&lt;br /&gt;
=Eingebettete Inhalte=&lt;br /&gt;
In HTML ist es möglich, auf einer Seite Inhalte einer anderen einzubinden. Das gängigste Elemente dafür ist ein Iframe (Inlineframe). Auf den Inhalt eines Iframes kann ebenfalls mit Selenium zugegriffen werden, allerdings muss dazu zuerst in diesen Kontext gewechselt werden. In der SeleniumWebDriverLibrary gibt es entsprechenden Bausteine, um in den Kontext eines Iframes zu wechseln, um in den Elternkontext zu wechseln und um zurück zum Standardinhalt, also dem obersten Kontext zu wechseln. Alle Element-Bausteine lösen die angelegten Pfade immer innerhalb des aktuellen Kontexts auf. Im GUI-Browser sehen Sie für eingebettete Inhalte ein zusätzliches Element, welches sie aufklappen können um dessen Elemente zu sehen.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Seit expecco 23.1 gibt es die Möglichkeit, auch zusammengesetzte Pfade an den Bausteinen zu verwenden, um direkt vom Standardinhalt auf den Inhalt eines Iframes zugreifen zu können. Dazu werden einfach der Pfad zum Iframe und der Pfad innerhalb des Iframe-Inhalts zu einem zusammengesetzt. Wichtig ist hierbei, dass beim Übergang keine Elemente ausgelassen werden dürfen, d.h. der vordere Teil muss mit dem Iframe-Element enden und der hintere Teil mit &#039;&#039;/body&#039;&#039; beginnen. Dazwischen dürfen die Pfade gekürzt werden und es ist natürlich auch möglich auf diese Art beliebig tief geschachtelte Elemente zu erreichen. An den Bausteinen können beide Techniken nach belieben verwendet werden, wichtig ist nur, dass die Pfade immer in dem Kontext aufgelöst werden, in dem sich Selenium gerade befindet.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie die kombinierten Pfade aufzeichnen, bzw. im GUI-Browser verwenden wollen, setzen Sie im Menü &#039;&#039;GUI Browser&#039;&#039; unter &#039;&#039;Aufzeichnung&#039;&#039; den Haken bei &#039;&#039;Zusammengesetzte Pfade aufzeichnen&#039;&#039;. Damit wird für eingebettete Elemente ein zusammengesetzter Pfad relativ zum aktuellen Kontext erzeugt und angezeigt, anstatt wie bisher nur innerhalb seines eigenen Kontexts. Außerdem können Sie diese Elemente auch direkt im Recorder ansprechen oder über Follow-Mouse finden.&lt;br /&gt;
&lt;br /&gt;
=Shadow-Elemente=&lt;br /&gt;
Shadow-DOMs sind eine Möglichkeit, um Teile einer Seite vom übrigen Dokument abzukapseln. Dabei werden an ein Element versteckte Shadow-Elemente angehängt. Eine ausführlichere Erklärung finden Sie zum Beispiel hier: [https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM Using shadow DOM - Web APIs | MDN].&lt;br /&gt;
&lt;br /&gt;
In der SeleniumWebDirverLibrary gibt es den Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039;, der die obersten Elemente liefert, die dann wie andere WebElemente verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
Da die Elemente versteckt sind, werden sie vom GUI-Browser nicht direkt angezeigt. Ab expecco 23.1 kann man allerdings im Kontextmenü der Elemente im GUI-Browser einen Haken setzen, dass Shadow-Elemente gesucht werden sollen. Beim Aktualisieren der Kinder eines Elements werden sie dann angezeigt, falls vorhanden, allerdings nicht, wenn der gesamte Baum aktualisiert wird. Wenn der Haken gesetzt ist, sind die Elemente auch im Recorder verfügbar.&lt;br /&gt;
&lt;br /&gt;
==Zusammengesetzte Pfade==&lt;br /&gt;
Ähnlich wie die Elemente innerhalb eines Frames kann auch auf die Shadow-Elemente direkt über zusammengesetzte Pfade zugegriffen werden. Diese Pfade können dann direkt an den Bausteinen verwendet werden, sodass der Baustein &#039;&#039;[Web] Get Shadow DOM&#039;&#039; nicht benötigt wird. Die Pfade haben die Form&lt;br /&gt;
 &amp;lt;host path&amp;gt;/shadowRoot/&amp;lt;shadow path&amp;gt;&lt;br /&gt;
wobei &#039;&#039;&amp;lt;host path&amp;gt;&#039;&#039; den Pfad zum Element angibt, an das der Shadow-DOM angehängt wurde, und &#039;&#039;&amp;lt;shadow path&amp;gt;&#039;&#039; der Pfad innerhalb des Shadow-DOMs zum gewünschten Element ist. &#039;/shadowRoot&#039; dient als Marker, dass an dieser Stelle der Wechsel in den Shadow-DOM erfolgt.&lt;br /&gt;
&lt;br /&gt;
=Authentifizierungs-Alerts=&lt;br /&gt;
Falls eine Webseite HTTP-Authentifizierung mit Basic Authentication verwendet, öffnet sich beim Laden der Seite ein Alert-Fenster zur Eingabe von Benutzernamen und Passwort. Dieses Fenster ist nicht direkt mit Selenium bedienbar. Im GUI-Browser wird es wie ein Alert angezeigt. Eine Ausnahme hierzu bildet Chrome, bei dem der Driver auf keine Anfrage antwortet solange der Dialog geöffnet ist. Das Plugin kann zu diesem Zeitpunkt insbesondere nicht feststellen, ob ein Authentifizierungs-Dialog geöffnet ist oder ob der Driver aus anderen Gründen nicht antwortet.&lt;br /&gt;
&lt;br /&gt;
Bei lokalen Verbindungen unter Windows kann eine Authentifizierung mittels Windows Access ausgeführt werden. Es gibt in der SeleniumWebDriverLibrary für einzelne Browsertypen spezifische Authentifizierungs-Bausteine sowie den Baustein &#039;&#039;Authenticate at Alert&#039;&#039;, der je nach Verbindung den entsprechenden Baustein ausführt. Für die verschiedenen Browser-Typen gibt es dabei unterschiedliche Einschränkungen:&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Chrome:&#039;&#039;&#039; Die Anmeldedaten werden an ein Chromefenster geschickt, daher funktioniert es nur, wenn nicht mehrere geöffnet sind. Der Einzelbaustein hat für diesen Fall die Option, den Titel des Fensters anzugeben.&lt;br /&gt;
:&#039;&#039;&#039;Edge&#039;&#039;&#039;: Mit Microsoft Edge wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
:&#039;&#039;&#039;Firefox&#039;&#039;&#039;: Schickt die Anmeldedaten an ein Firefox-Dialogfenster und funktioniert daher nur, wenn es nicht mehrere gibt.&lt;br /&gt;
:&#039;&#039;&#039;Internet Explorer&#039;&#039;&#039;: Mit dem Internet Explorer wird eine Anmeldung nicht unterstützt.&lt;br /&gt;
&lt;br /&gt;
Als zusätzliche Option steht Ihnen auch eine Anmeldung über die URL zur Verfügung. Rufen Sie anstatt der Seite &amp;lt;nowiki&amp;gt;https://www.example.com&amp;lt;/nowiki&amp;gt; die URL &amp;lt;nowiki&amp;gt;https://user:password@www.example.com&amp;lt;/nowiki&amp;gt; auf. Wichtig ist hierbei, dass &#039;&#039;:&#039;&#039; und &#039;&#039;@&#039;&#039; nicht im Benutzernamen oder im Passwort auftauchen. Möglicherweise wird diese Methode nicht von jedem Browser unterstützt.&lt;br /&gt;
&lt;br /&gt;
Mithilfe des [[WindowsAutomation_Reference_2.0|WindowsAutomation2]]-Plugins ist es ebenfalls möglich, solch eine Anmeldung mit allen Browsertypen auszuführen.&lt;br /&gt;
&lt;br /&gt;
=Portierung alter Selenium-Tests=&lt;br /&gt;
Dieses Plugin ersetzt das bisherige [[Selenium_Web_Test_Plugin|Selenium Web Test Plugin]]. Dieses basierte auf [https://www.seleniumhq.org/projects/remote-control/ Selenium RC], welches in Zukunft von den Browsern nicht mehr unterstützt wird. Der Nachfolger von Selenium RC ist [https://www.seleniumhq.org/projects/webdriver/ Selenium WebDriver], auch &#039;&#039;Selenium 2&#039;&#039; genannt. Ebenso ist auch das Aufzeichnen von Tests mit [https://www.seleniumhq.org/projects/ide/ Selenim IDE] veraltet, da das Plugin von neueren Browsern nicht mehr unterstützt wird. Das Selenium WebDriver Plugin verwendet stattdessen einen eigenen [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
Tests, die mit dem alten Selenium Web Test Plugin erstellt wurden und die alte SeleniumLibrary verwenden, können über Selenium WebDriver ausgeführt werden. Setzen Sie dazu in den Plugin-Einstellungen von &amp;quot;&#039;&#039;Webtest Legacy (Selenium)&#039;&#039;&amp;quot; den Haken bei &amp;quot;&#039;&#039;WebDriver für die Ausführung verwenden&#039;&#039;&amp;quot;. Für die wichtigsten Funktionen wurde Wrapper bzw. umsetzende Funktionen erstellt, um die Migration möglichst problemlos zu gestalten.&lt;br /&gt;
Testen Sie dann, ob die Tests wie bisher ablaufen. Für den überwiegenden Teil der Bausteine sollte es dabei keine Probleme geben. Einige wenige Aktionen werden in der WebDriver Version nicht mehr unterstützt oder verhalten sich unterschiedlich. Es ist auch nicht garantiert, daß die Emulation der alten Schnittstelle auf Dauer von Selenium unterstützt werden. Wenn möglich sollten Sie daher über kurz oder lang die Testfälle umschreiben.&lt;br /&gt;
&lt;br /&gt;
=FAQ=&lt;br /&gt;
*&#039;&#039;&#039;Scrollbalken lassen sich im Recorder nicht bedienen&#039;&#039;&#039;&lt;br /&gt;
:Der Scrollbalken des Browsers, der automatisch angezeigt wird, wenn eine Seite größer als das Browserfenster ist, ist kein bedienbares Webelement. Scrollen um einen bestimmten Betrag ist in einem Test selten sinnvoll, wenn die Größe des Browserfensters nicht festgelegt ist. Verwenden Sie stattdessen den Baustein &amp;lt;code&amp;gt;[Web] Scroll Element into View&amp;lt;/code&amp;gt;, um ein entsprechendes Element in den sichtbaren Bereich zu scrollen. Der Klick-Baustein, den der Recorder standardmäßig verwendet, führt diese Aktion bereits automatisch mit aus (&amp;lt;code&amp;gt;[WebElement] Click (Scroll Element into View)&amp;lt;/code&amp;gt;). Wenn Sie im Recorder-Fenster scrollen, wird dies automatisch auf den Browser übertragen, aber nicht aufgezeichnet. Falls Sie tatsächlich um einen bestimmten Betrag scrollen möchten, gibt es bei den Browser-Aktionen einen Eintrag dafür und weitere Bausteine in der SeleniumWebDriverLibrary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein schlägt fehl, wenn Element zu spät sichtbar wird&#039;&#039;&#039;&lt;br /&gt;
:Alle Bausteine, die einen Elementpfad verwenden, haben automatisch eingebaut, dass sie warten, bis ein entsprechendens Element auftaucht. Es gibt aber Fälle, in denen ein Element zwar bereits da, aber noch nicht sichtbar ist. Bei einem Klick auf das Element bekommen Sie dann einen Fehler. Mögliche Fehler in diesem Zusammenhang sind &amp;lt;code&amp;gt;org.openqa.selenium.ElementNotInteractableException: element not interactable&amp;lt;/code&amp;gt; und &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;. Verwenden Sie dann vor einer Interaktion mit dem Element den Baustein &amp;lt;code&amp;gt;[Web] Wait for Visibility of Element&amp;lt;/code&amp;gt; oder &amp;lt;code&amp;gt;[Web] Wait for Element to Be Clickable&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.JavascriptException: javascript error: Cannot read property &#039;left&#039; of undefined&amp;lt;/code&amp;gt; kann mit dem Chrome-Browser auftreten. In diesem Fall ist das verwendete Element nicht sichtbar. Lesen Sie dazu den Punkt oben. Der Fehler ist auch im Zusammenhang mit Elementen in einer Dropdown-Liste bekannt, d.h. bei einem Klick oder dem Bewegen der Maus auf ein &amp;lt;nowiki&amp;gt;&amp;lt;option&amp;gt;&amp;lt;/nowiki&amp;gt;-Element innerhalb eines &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Elements. Diese Elemente sind prinzipiell nicht klickbar. Verwenden Sie stattdessen einen passenden &amp;lt;code&amp;gt;[Web] Select&amp;lt;/code&amp;gt;-Baustein mit dem &amp;lt;nowiki&amp;gt;&amp;lt;select&amp;gt;&amp;lt;/nowiki&amp;gt;-Element.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldung: &amp;lt;code&amp;gt;Stale Element Reference Exception&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
:Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein WebElement verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator, um das Element neu zu holen. Eventuell liegt es auch daran, dass sich der Test momentan in einem anderen Frame-Kontext befindet als das Element. Wenn Sie [[#Zusammengesetzte_Pfade|zusammengesetzte Pfade]] verwenden, sollte das Element selbst in den richtigen Kontext wechseln, bevor Aktionen darauf ausgeführt werden.&lt;br /&gt;
:In seltenen Fällen kann der Fehler auch in expecco selbst auftreten, wenn an irgendeiner Stelle im GUI-Browser oder Recorder ein entsprechendes WebElement verwendet wird. Sie sollten dann abbrechen können und es nochmal versuchen. Sollte der Fehler bestehen bleiben, wechseln Sie in den Default Content und laden Sie den Baum im GUI-Browser neu.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Baustein läuft erfolgreich, aber ohne Auswirkungen&#039;&#039;&#039;&lt;br /&gt;
:Dieser Fall kann mit Chrome auftreten. Das Element ist verfügbar, die Aktion wirft keinen Fehler, aber es wird nichts ausgeführt. In der Regel hilft es, vor der Ausführung kurz zu warten, siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ausführungen mit Chrome sind langsamer&#039;&#039;&#039;&lt;br /&gt;
:Um ein Problem bei der Ausführung mit Chrome zu beheben, ist in den Plugin-Einstellungen für Chrome eine Verzögerung definiert. Überprüfen Sie, ob dieser Wert eventuell zu hoch eingestellt ist; siehe [[#Ausf.C3.BChrungsverz.C3.B6gerung_f.C3.BCr_Chrome | Ausführungsverzögerung für Chrome]].&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Fehlermeldungen wie: &amp;quot;org.openqa.selenium.InvalidArgumentException: Expected &amp;quot;handle&amp;quot; to be a string...&amp;quot;&#039;&#039;&#039;&lt;br /&gt;
:Dies passiert wenn der Driver nicht (mehr) zum Browser passt. Lesen Sie dazu obiges Kapitel &amp;quot;[[#WebDriver aktualisieren|WebDriver aktualisieren]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Key Chords mit Shortcuts funktionieren nicht&#039;&#039;&#039;&lt;br /&gt;
:Das Drücken mehrerer Tasten gleichzeitig lässt sich als Key Chord simulieren. Dadurch können auch Shortcuts eingegeben werden. Allerdings funktionieren hier nicht alle Eingaben, da diese nur an den Seiteninhalt und nicht an den Browser selbst gehen. Kombinationen wie &#039;&#039;Strg + t&#039;&#039; um einen neuen Browsertab zu öffnen, funktionieren daher vermutlich nicht, &#039;&#039;Strg + a&#039;&#039; oder &#039;&#039;Strg + c&#039;&#039; sollten hingegen möglich sein.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Zusätzliche Window Handles mit Opera&#039;&#039;&#039;&lt;br /&gt;
:Der Opera-Browser liefert mehr Window Handles als Tabs bzw. Fenster geöffnet sind. Diese kommen von Opera-internen Funktionen wie dem Schnellstart (&#039;&#039;Speed Dial&#039;&#039;) oder der &#039;&#039;Better Address Bar Experience&#039;&#039; (BABE), die zwar im Browserfenster eingebunden, aber nicht als Tab angezeigt werden. Zu diesen Tabs kann zwar mit den entsprechenden Bausteinen gewechselt werden, es sind dann aber nicht alle Aktionen möglich, die für die normalen Tabs zur Verfügung stehen. Sie können zum Beispiel nicht geschlossen werden und man bekommt von ihnen kein Bild. Am besten wechselt man daher gar nicht erst in diese Kontexte. Seien Sie also vorsichtig, wenn Sie anhand des Index zu einem Tab wechseln wollen, da sich die Opera-Tabs zwischen den anderen befinden und der Index ein anderer als für die anderen Browser sein kann.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Chrome: Wähle deine Suchmaschine&#039;&#039;&#039;&lt;br /&gt;
:Neuere Chromeversionen zeigen nach dem Starten ein Overlay, bei dem man die verwendete Suchmaschine auswählen soll. Die Entscheidung wird normalerweise im Benutzerprofil gespeichert. Wenn für die Verbindung aber nicht explizit ein Chrome-Profil angegeben wird, hat man bei jedem Verbindungsaufbau ein leeres Profil und es wird immer nachgefragt.&lt;br /&gt;
&lt;br /&gt;
:In vielen Fällen kann der Test auch trotz des Overlays im Hintergrund ablaufen. Das Overlay gilt aber wie ein Tab bzw. Fenster; so liefert beispielsweise vom Baustein &#039;&#039;[Web] Get Window Handles&#039;&#039; einen Handle dafür und es kann auch dorthin gewechselt werden. Es gibt aber auch Möglichkeiten es loszuwerden:&lt;br /&gt;
:* &#039;&#039;--disable-search-engine-choice-screen&#039;&#039;: In den [[#Erweiterte_Einstellungen|erweiterten Einstellungen]] kann man bei den Optionen &amp;lt;code&amp;gt;--disable-search-engine-choice-screen&amp;lt;/code&amp;gt; angeben, dann kommt das Overlay nicht.&lt;br /&gt;
:* &#039;&#039;Auswählen&#039;&#039;: Sie können Ihren Test auch so erweitern, dass zu Beginn eine Suchmaschine ausgewählt und damit das Overlay geschlossen wird. Dabei müssen Sie zwei Dinge beachten. Zum einen müssen Sie zuerst mit einem &#039;&#039;Switch to Window&#039;&#039;-Baustein dorthin wechseln (z.B. mit Index &#039;&#039;2&#039;&#039; oder leerem Titel) und am Ende auch wieder zurück zu Ihrem ursprünglichen Tab. Zum anderen sind interessanten Elemente des Overlays [[#Shadow-Elemente|Shadow-Elemente]] und werden daher im GUI-Browser nicht direkt angezeigt.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29664</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29664"/>
		<updated>2024-07-24T14:27:38Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
The &#039;&#039;Mobile Testing Plugin&#039;&#039; adds mechanisms to test and automate Android and iOS devices. This includes both real and emulated devices - it does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; chromedriverStartTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
The error &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; occurs whenever an element is used that is no longer there. If that happens during your test and the element should have been there, try using the locator (xPath) instead to fetch the element again.&lt;br /&gt;
&lt;br /&gt;
In some cases this error can also occur even if you already use a locator at the action block. This is because the locator is always resolved first and the corresponding element is fetched and the action is then executed with this element. If the app refreshes the element exactly between the resolving and fetching part and the execution, creating a new element, this error occurs. If it happens at a specific point in your test, your best option is to catch the error and retry.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29663</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29663"/>
		<updated>2024-07-24T14:27:16Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; chromedriverStartTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein Element verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator (XPath), um das Element neu zu holen.&lt;br /&gt;
&lt;br /&gt;
In manchen Fällen kann dieser Fehler auch dann auftreten, wenn Sie am Baustein bereits Locator angegeben haben. Das liegt daran, dass immer zuerst der Locator aufgelöst und das entsprechende Element geholt wird und dann die Aktionen mit dem Element ausgeführt wird. Wenn die App das Element genau zwischen dem Zeitpunkt des Auflösens und Holens und der Ausführung der Aktion aktualisiert und dabei ein neues Element erzeugt, kommt es zu diesem Fehler. Passiert das an einer bestimmten Stelle in Ihrem Test, bleibt nichts anderes als den Fehler abzufangen und es erneut zu versuchen.&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29662</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29662"/>
		<updated>2024-07-23T09:48:46Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Problems and Solutions */ org.openqa.selenium.StaleElementReferenceException&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
The &#039;&#039;Mobile Testing Plugin&#039;&#039; adds mechanisms to test and automate Android and iOS devices. This includes both real and emulated devices - it does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; startChromedriverTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
The error &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; occurs whenever an element is used that is no longer there. If that happens during your test and the element should have been there, try using the locator (xPath) instead to fetch the element again.&lt;br /&gt;
&lt;br /&gt;
In some cases this error can also occur even if you already use a locator at the action block. This is because the locator is always resolved first and the corresponding element is fetched and the action is then executed with this element. If the app refreshes the element exactly between the resolving and fetching part and the execution, creating a new element, this error occurs. If it happens at a specific point in your test, your best option is to catch the error and retry.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29661</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29661"/>
		<updated>2024-07-23T09:48:41Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Probleme und Lösungen */ org.openqa.selenium.StaleElementReferenceException&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==&#039;&#039;org.openqa.selenium.StaleElementReferenceException&#039;&#039;==&lt;br /&gt;
Der Fehler &amp;lt;code&amp;gt;org.openqa.selenium.StaleElementReferenceException&amp;lt;/code&amp;gt; tritt immer dann auf, wenn ein Element verwendet wird, das nicht mehr da ist. Wenn das in Ihrem Test passiert und das Element eigentlich da sein sollte, verwenden Sie an der Stelle stattdessen den Locator (XPath), um das Element neu zu holen.&lt;br /&gt;
&lt;br /&gt;
In manchen Fällen kann dieser Fehler auch dann auftreten, wenn Sie am Baustein bereits Locator angegeben haben. Das liegt daran, dass immer zuerst der Locator aufgelöst und das entsprechende Element geholt wird und dann die Aktionen mit dem Element ausgeführt wird. Wenn die App das Element genau zwischen dem Zeitpunkt des Auflösens und Holens und der Ausführung der Aktion aktualisiert und dabei ein neues Element erzeugt, kommt es zu diesem Fehler. Passiert das an einer bestimmten Stelle in Ihrem Test, bleibt nichts anderes als den Fehler abzufangen und es erneut zu versuchen.&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29657</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29657"/>
		<updated>2024-07-17T12:33:01Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Editoren */ translated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Compound Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Semantik ==&lt;br /&gt;
=== Relation zu IEC1131 ===&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Petrinetzen ===&lt;br /&gt;
Ein Petri-Netz [https://de.wikipedia.org/wiki/Petri-Netz (siehe Wikipedia)] ist ein Netzwerk, das aus Knoten (&#039;&#039;Stellen&#039;&#039; oder auch &#039;&#039;Plätze&#039;&#039; genannt, mit möglicher Aktionsbehandlung) und Übergängen besteht. In klassischen Petri-Netzen bewegen sich anonyme Tokens entlang von Verbindungen. Übergänge kontrollieren das Auslösen (Triggern) der folgenden Aktionsschritte abhängig von der Ankunft von Tokens auf der Eingangsseite, und geben Tokens an die Ausgangsseite weiter.&lt;br /&gt;
&lt;br /&gt;
Expecco kombiniert die Übergangs- und Stellenfunktionalität in einem einzelnen Schrittelement um die grafische Representation dichter zu machen (und auch um eine Ähnlichkeit mit UML-2-Aktivitätsdiagrammen und anderen flussbasierten Diagrammen zu bekommen). Semantisch verhalten sie sich jedoch gleich und jedes Diagramm könnte mit separaten Elementen umgeschrieben werden (durch sammeln der Eingaben und Weitergabe eines Tupels mit Tokens an die Stelle).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
Ein expecco-Schritt mit mehreren Eingabepins entspricht einem Petri-Netz-Übergang mit mehreren Eingaben gefolgt von einer Petri-Netz-Aktion. Wie bei einem Übergang in einem Petri-Netz kann die Eingangsseite eines Schrittes so konfiguriert werden, dass entweder irgendein Eingabewert oder alle Eingabewerte vorliegen müssen. In expecco wird das als &amp;quot;&#039;&#039;Aktivierungsbedingung&#039;&#039;&amp;quot; des Schritts bezeichnet und ist genauer in der [[DiagramElements-Step|Dokumentation zum Schritt]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Höhere Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, die andere Petri-Netze als Stellen enthalten, was in expecco genau den zusammengesetzten Aktionen entspricht.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;&#039;&#039;Farbige Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, bei denen keine einfachen anonymen Tokens weitergereicht werden, sondern Datenobjekte (oder Referenzen darauf, wie in expecco).&lt;br /&gt;
&lt;br /&gt;
Deshalb sind expecco-Diagramme in Standard-Petri-Netz-Notation &amp;quot;&#039;&#039;Höhere farbige Petri-Netze&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu UML Aktivitätsdiagrammen ===&lt;br /&gt;
&lt;br /&gt;
Zusammengesetzte Aktionen in expecco sind isomorph zu UML-Aktivitätsdiagrammen mit einer bestimmten vordefinierten Sammlung an Stereotypen für Verbindungen, Pins und Aktionsschritte. Diese Stereotypen sind in expecco fest einprogrammiert und definieren die Semantik des Auslösens von Aktionen, der Ausführungsreihenfolge von Datenverbindungen und der optionalen parallelen Ausführung von Schritten. Die grafische Representation ist leicht anders; die leicht umständlichen &amp;lt;&amp;lt;Stereotyp&amp;gt;&amp;gt;-Vermerke werden durch verschiedene Pin-Darstellungen (gefüllt/leer usw.) ersetzt. Außerdem sind alle Verbindungen in expecco Objekt-Verbindungen und alle Pins erhalten und erzeugen Objekte als Werte.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Flussdiagrammen ===&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
Das Aktivitätsdiagramm, das das Verhalten eines zusammengesetzten Bausteins definiert, kann im [[CompoundBlock Editor-CompoundWorksheet Editor|&#039;&#039;Netzwerkeditor&#039;&#039;]] – auch &amp;quot;&#039;&#039;Diagrammeditor&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Netzwerkdiagrammeditor&#039;&#039;&amp;quot; genannt – bearbeitet werden. Dieser Editor zeigt die &amp;quot;Innenansicht&amp;quot; des Bausteins. Die Schnittstelle eines zusammengesetzten Bausteins (d.h. Anzahl und Art der Pins) kann hingegen als &amp;quot;Außenansicht&amp;quot; angesehen werden und wird im [[Scheme Editor|&#039;&#039;Schema Editor&#039;&#039;]] gezeigt und definiert.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Schritt]], [[DiagramElements-Connection|Verbindung]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementaraktion]], &lt;br /&gt;
&lt;br /&gt;
Zurück zur [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29656</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29656"/>
		<updated>2024-07-17T12:19:57Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Relation zu UML Aktivitätsdiagrammen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Compound Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Semantik ==&lt;br /&gt;
=== Relation zu IEC1131 ===&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Petrinetzen ===&lt;br /&gt;
Ein Petri-Netz [https://de.wikipedia.org/wiki/Petri-Netz (siehe Wikipedia)] ist ein Netzwerk, das aus Knoten (&#039;&#039;Stellen&#039;&#039; oder auch &#039;&#039;Plätze&#039;&#039; genannt, mit möglicher Aktionsbehandlung) und Übergängen besteht. In klassischen Petri-Netzen bewegen sich anonyme Tokens entlang von Verbindungen. Übergänge kontrollieren das Auslösen (Triggern) der folgenden Aktionsschritte abhängig von der Ankunft von Tokens auf der Eingangsseite, und geben Tokens an die Ausgangsseite weiter.&lt;br /&gt;
&lt;br /&gt;
Expecco kombiniert die Übergangs- und Stellenfunktionalität in einem einzelnen Schrittelement um die grafische Representation dichter zu machen (und auch um eine Ähnlichkeit mit UML-2-Aktivitätsdiagrammen und anderen flussbasierten Diagrammen zu bekommen). Semantisch verhalten sie sich jedoch gleich und jedes Diagramm könnte mit separaten Elementen umgeschrieben werden (durch sammeln der Eingaben und Weitergabe eines Tupels mit Tokens an die Stelle).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
Ein expecco-Schritt mit mehreren Eingabepins entspricht einem Petri-Netz-Übergang mit mehreren Eingaben gefolgt von einer Petri-Netz-Aktion. Wie bei einem Übergang in einem Petri-Netz kann die Eingangsseite eines Schrittes so konfiguriert werden, dass entweder irgendein Eingabewert oder alle Eingabewerte vorliegen müssen. In expecco wird das als &amp;quot;&#039;&#039;Aktivierungsbedingung&#039;&#039;&amp;quot; des Schritts bezeichnet und ist genauer in der [[DiagramElements-Step|Dokumentation zum Schritt]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Höhere Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, die andere Petri-Netze als Stellen enthalten, was in expecco genau den zusammengesetzten Aktionen entspricht.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;&#039;&#039;Farbige Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, bei denen keine einfachen anonymen Tokens weitergereicht werden, sondern Datenobjekte (oder Referenzen darauf, wie in expecco).&lt;br /&gt;
&lt;br /&gt;
Deshalb sind expecco-Diagramme in Standard-Petri-Netz-Notation &amp;quot;&#039;&#039;Höhere farbige Petri-Netze&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu UML Aktivitätsdiagrammen ===&lt;br /&gt;
&lt;br /&gt;
Zusammengesetzte Aktionen in expecco sind isomorph zu UML-Aktivitätsdiagrammen mit einer bestimmten vordefinierten Sammlung an Stereotypen für Verbindungen, Pins und Aktionsschritte. Diese Stereotypen sind in expecco fest einprogrammiert und definieren die Semantik des Auslösens von Aktionen, der Ausführungsreihenfolge von Datenverbindungen und der optionalen parallelen Ausführung von Schritten. Die grafische Representation ist leicht anders; die leicht umständlichen &amp;lt;&amp;lt;Stereotyp&amp;gt;&amp;gt;-Vermerke werden durch verschiedene Pin-Darstellungen (gefüllt/leer usw.) ersetzt. Außerdem sind alle Verbindungen in expecco Objekt-Verbindungen und alle Pins erhalten und erzeugen Objekte als Werte.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Flussdiagrammen ===&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the [[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;network editor&#039;&#039;]], also called &amp;quot;&#039;&#039;diagram editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;network diagram editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;internal view&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of an compound block (e.g. number and type of pins) can be regarded as its &amp;quot;external view&amp;quot; and is presented and defined in the [[Scheme Editor/en|&#039;&#039;schema editor&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Schritt]], [[DiagramElements-Connection|Verbindung]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementaraktion]], &lt;br /&gt;
&lt;br /&gt;
Zurück zur [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29655</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29655"/>
		<updated>2024-07-17T12:01:05Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Relation zu Petrinetzen */ translated&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Compound Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Semantik ==&lt;br /&gt;
=== Relation zu IEC1131 ===&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Petrinetzen ===&lt;br /&gt;
Ein Petri-Netz [https://de.wikipedia.org/wiki/Petri-Netz (siehe Wikipedia)] ist ein Netzwerk, das aus Knoten (&#039;&#039;Stellen&#039;&#039; oder auch &#039;&#039;Plätze&#039;&#039; genannt, mit möglicher Aktionsbehandlung) und Übergängen besteht. In klassischen Petri-Netzen bewegen sich anonyme Tokens entlang von Verbindungen. Übergänge kontrollieren das Auslösen (Triggern) der folgenden Aktionsschritte abhängig von der Ankunft von Tokens auf der Eingangsseite, und geben Tokens an die Ausgangsseite weiter.&lt;br /&gt;
&lt;br /&gt;
Expecco kombiniert die Übergangs- und Stellenfunktionalität in einem einzelnen Schrittelement um die grafische Representation dichter zu machen (und auch um eine Ähnlichkeit mit UML-2-Aktivitätsdiagrammen und anderen flussbasierten Diagrammen zu bekommen). Semantisch verhalten sie sich jedoch gleich und jedes Diagramm könnte mit separaten Elementen umgeschrieben werden (durch sammeln der Eingaben und Weitergabe eines Tupels mit Tokens an die Stelle).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
Ein expecco-Schritt mit mehreren Eingabepins entspricht einem Petri-Netz-Übergang mit mehreren Eingaben gefolgt von einer Petri-Netz-Aktion. Wie bei einem Übergang in einem Petri-Netz kann die Eingangsseite eines Schrittes so konfiguriert werden, dass entweder irgendein Eingabewert oder alle Eingabewerte vorliegen müssen. In expecco wird das als &amp;quot;&#039;&#039;Aktivierungsbedingung&#039;&#039;&amp;quot; des Schritts bezeichnet und ist genauer in der [[DiagramElements-Step|Dokumentation zum Schritt]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Höhere Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, die andere Petri-Netze als Stellen enthalten, was in expecco genau den zusammengesetzten Aktionen entspricht.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;&#039;&#039;Farbige Petri-Netze&#039;&#039;&amp;quot; sind Petri-Netze, bei denen keine einfachen anonymen Tokens weitergereicht werden, sondern Datenobjekte (oder Referenzen darauf, wie in expecco).&lt;br /&gt;
&lt;br /&gt;
Deshalb sind expecco-Diagramme in Standard-Petri-Netz-Notation &amp;quot;&#039;&#039;Höhere farbige Petri-Netze&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu UML Aktivitätsdiagrammen ===&lt;br /&gt;
 --- to be written&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Flussdiagrammen ===&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the [[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;network editor&#039;&#039;]], also called &amp;quot;&#039;&#039;diagram editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;network diagram editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;internal view&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of an compound block (e.g. number and type of pins) can be regarded as its &amp;quot;external view&amp;quot; and is presented and defined in the [[Scheme Editor/en|&#039;&#039;schema editor&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Schritt]], [[DiagramElements-Connection|Verbindung]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementaraktion]], &lt;br /&gt;
&lt;br /&gt;
Zurück zur [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29653</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29653"/>
		<updated>2024-07-17T10:28:20Z</updated>

		<summary type="html">&lt;p&gt;Matilk: restructuring&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Compound Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Semantik ==&lt;br /&gt;
=== Relation zu IEC1131 ===&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Petrinetzen ===&lt;br /&gt;
A Petri Net [http://en.wikipedia.org/wiki/Petri_net| -&amp;gt;Wikipedia] is a network consisting of places (with possible action processing) and transitions. In a classical petri net, anonymous tokens travel along connections and transitions control the firing (triggering) of following action steps depending on the arrival of tokens at their input side, and passing tokens to their output side. Expecco has combined the transition and place functionality into a single step item, in order to make the graphical representation more dense (and also for its similarity with UML-2 activity diagrams and other flow based diagrams). However, semantically, they behave the same, and any diagram could be rewritten by using separate items (collecting inputs and passing a tuple of tokens on to the place).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
An expecco step with multiple input pins corresponds to a Petri Net transition with multiple inputs followed by a Petri Net action. Similar to transitions in a Petri Net, the input side of a step can be configured to require either any input or all input values to be present. In expecco, this is called the step&#039;s &amp;quot;&#039;&#039;trigger condition&#039;&#039;&amp;quot; and described in detail in the [[DiagramElements-Step|step documentation]].&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Higher order Petri Nets&#039;&#039;&amp;quot; are Petri Nets containing other Petri Nets as places, which is exactly what a compound block is in expecco.&lt;br /&gt;
&amp;quot;&#039;&#039;Coloured Petri Nets&#039;&#039;&amp;quot; are Petri Nets where not simple anonymous tokens are passed around, but data objects (or references to them, as in expecco).&lt;br /&gt;
&lt;br /&gt;
Thus, in standard Petri Net notation, expecco&#039;s diagrams are therefore &amp;quot;&#039;&#039;higher ordered colored Petri Nets&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relation zu UML Aktivitätsdiagrammen ===&lt;br /&gt;
 --- to be written&lt;br /&gt;
&lt;br /&gt;
=== Relation zu Flussdiagrammen ===&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the [[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;network editor&#039;&#039;]], also called &amp;quot;&#039;&#039;diagram editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;network diagram editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;internal view&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of an compound block (e.g. number and type of pins) can be regarded as its &amp;quot;external view&amp;quot; and is presented and defined in the [[Scheme Editor/en|&#039;&#039;schema editor&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Schritt]], [[DiagramElements-Connection|Verbindung]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementaraktion]], &lt;br /&gt;
&lt;br /&gt;
Zurück zur [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element/en&amp;diff=29652</id>
		<title>CompoundBlock Element/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element/en&amp;diff=29652"/>
		<updated>2024-07-16T11:51:10Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Diagram Elements */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
A &amp;quot;&#039;&#039;Compound Action Block&#039;&#039;&amp;quot; describes an [[Block_Element/en|action]]&#039;s behavior with an activity diagram. The diagram is similar to [[#Relationship_to_UML_Activity_Diagrams|data flow diagrams]] as used in UML2.0 and also has many features in common with [[#Relationship_to_Petri_Nets|Petri Nets]]. The diagram consists of sub actions called [[DiagramElements-Step|&#039;&#039;steps&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
The execution is controlled via a combination of data and control flows which are passed via inter-step connections:&lt;br /&gt;
&lt;br /&gt;
* Data flows are defined as values (results, measurement values, objects, documents etc.) being passed from one step to another. These flows are defined by interconnections from a step&#039;s [[DiagramElements-Pin#Output Pin|output pin]] to another step&#039;s [[DiagramElements-Pin#Input Pin|input pin]]. &lt;br /&gt;
&lt;br /&gt;
* Control flows are defined as &amp;quot;&#039;&#039;action finished&#039;&#039;&amp;quot; information being used to trigger another step&#039;s action. These flows are defined by interconnections from a step&#039;s [[DiagramElements-Pin#Enable_Output_Pin|&#039;&#039;Trigger Output Pin&#039;&#039;]] to another step&#039;s [[DiagramElements-Pin#Enable_Input_Pin|&#039;&#039;Trigger Input Pin&#039;&#039;]].&amp;lt;br&amp;gt;(these are also occasionally called &amp;quot;&#039;&#039;Enable Output Pin&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Enable Input Pin&#039;&#039;&amp;quot; in this documentation).&lt;br /&gt;
&lt;br /&gt;
Both can trigger the execution of a subsequent step.&lt;br /&gt;
&lt;br /&gt;
== Diagram Elements ==&lt;br /&gt;
Diagram elements are the elements in an activity diagram. They define the behavior of the [[Compound Block|compound action block]] and are manipulated in the [[Compound_Network_Editor/en|network editor]].&lt;br /&gt;
&lt;br /&gt;
== Introductory Activity Diagram Example ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the major components of an activity diagram.&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|An activity diagram]]&lt;br /&gt;
&lt;br /&gt;
The diagram models a test of an e-mail transmission:&lt;br /&gt;
* First, the step &amp;quot;Create Unique ID&amp;quot; creates a so-called [[Glossary/en#UUID_.28Universal_Unique_Identifier.29 |UUID]] (Universal Unique Identifier) at its output pin, which is used later to check whether the correct e-mail has arrived.&lt;br /&gt;
* The UUID is delivered to the step &amp;quot;Send E-Mail [SMTP]&amp;quot;, which sends an e-mail via SMTP ([https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol &amp;quot;Simple Mail Transfer Protocol&amp;quot;]) using the UUID as subject.&lt;br /&gt;
* Next, the &amp;quot;Time [Delay]&amp;quot; step waits for 5 seconds.&lt;br /&gt;
* Finally, &amp;quot;Check for incoming Mail&amp;quot; checks whether an e-mail has arrived with the given UUID as subject. If there is no such e-mail the test will fail.&lt;br /&gt;
&lt;br /&gt;
Notice that the definition of activity diagrams in expecco corresponds largely with the UML notation. However, to emphasize important aspects and to make the diagram easier to read, some elements differ slightly from the standard UML notation. Especially, pin stereotypes are rendered directly as different pin style instead of adding extra &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot; labels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Step]] (7) ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;&#039;&#039;step&#039;&#039;&amp;quot; is a action block which is placed into an activity diagram. These blocks can be either [[Elementary Block|elementary blocks]] (such as &amp;quot;Create Unique ID&amp;quot;) which are defined by a piece of source code or [[Compound Block|compound blocks]] (such as &amp;quot;Check Incoming Mail&amp;quot;) which are defined by their own activity diagram. To the network where a block is placed, there is no difference in the behavior. The network which uses an action (i.e. places a step) does not need to know how the internals of the action are implemented. Actually, there is not even a visual difference in the diagram. All are triggered by the availability of input data, perform an operation, and generate results on their output(s). &lt;br /&gt;
&lt;br /&gt;
Steps are described in detail in a [[DiagramElements-Step | separate document]].&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
A step with autostart option will be triggered automatically, whenever the containing activity diagram network is executed. Without the autostart option, steps are only started when input data arrives at the step&#039;s input pin(s). Autostart is required for steps which have no input and are not triggered by a control flow connection. In the above diagram, this is the case for the leftmost &amp;quot;Create Unique ID&amp;quot; step.&lt;br /&gt;
&lt;br /&gt;
The diagram editor renders auto started blocks with a special icon at its top-left corner; if you prefer the standard UML notation, you can place a separate START block and connect its trigger pins.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] are used to exchange data and trigger information between steps. &lt;br /&gt;
These pins can be [[DiagramElements-Pin#Output Pin|output pins]] (3) to send data or [[DiagramElements-Pin#Input Pin|input pins]] (9) to receive data. &lt;br /&gt;
Other pins are used for special tasks like [[DiagramElements-Pin#Exception Output Pin|exception handling]];&lt;br /&gt;
in the above diagram, the vertical exception output of the &amp;quot;Check Incoming Mail&amp;quot; step is connected to the trigger input of the &amp;quot;FAIL&amp;quot; notifying step.&lt;br /&gt;
&lt;br /&gt;
Control-flow pins (trigger and status) are oriented vertically, whereas data-flow pins are oriented horizontally.&lt;br /&gt;
Input pins are always located at the top or left, whereas output pins are located at the right or bottom.&lt;br /&gt;
&lt;br /&gt;
Pins are rendered according to their behavior during execution;&lt;br /&gt;
especially consuming vs. non-consuming input behaviour&lt;br /&gt;
and buffered vs. non-buffered output behavior &lt;br /&gt;
is drawn (filled vs. unfilled) to highlight these important facts. &lt;br /&gt;
&lt;br /&gt;
Pins are described in detail in a [[DiagramElements-Pin | separate document]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Connection]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Connections are used to interconnect steps to pass data or control information from an output pin to one or more input pins.&lt;br /&gt;
In the UML sense, all connections are object connections.&lt;br /&gt;
&lt;br /&gt;
==== Data Flow Connection (4) ====&lt;br /&gt;
&lt;br /&gt;
These connections deliver data from a step&#039;s output pin to another step&#039;s input pin. In the example, the first step sends the generated UUID to two other steps.&lt;br /&gt;
Data flow pins are always located at the left and right of a step (horizontal pins), and the left pins are always inputs, whereas the right pins are always outputs.&lt;br /&gt;
&lt;br /&gt;
==== Control Flow Connection (8) ====&lt;br /&gt;
&lt;br /&gt;
These connections are used to control the execution order in an activity diagram. In the example the steps on the right are executed sequential.&lt;br /&gt;
Control flow pins are always located at the top and bottom of a step (vertical pins), and pins at the top are always inputs, whereas pins at the bottom are always outputs.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value]] (6) ===&lt;br /&gt;
&lt;br /&gt;
The data which is read by a pin can be &#039;&#039;frozen&#039;&#039; to a static value (constant). In the above example, the &amp;quot;message text&amp;quot;, the &amp;quot;e-mail address&amp;quot;, the &amp;quot;waiting time&amp;quot; and also the &amp;quot;failure message&amp;quot; are &#039;&#039;frozen&#039;&#039;.&lt;br /&gt;
A frozen pin should typically be configured to be non-triggering and non-consuming (so called &amp;quot;&#039;&#039;parameter pin&#039;&#039;&amp;quot;). For details on triggering and consumption of values, please read the chapter on [[DiagramElements-Pin#Input_Pin_Trigger_Attributes |&amp;quot;&#039;&#039;Input Pin Trigger Behavior&#039;&#039;&amp;quot;]] in the [[DiagramElements-Pin | &amp;quot;&#039;&#039;pin documentation&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Environment Freeze Value]] (5) ===&lt;br /&gt;
&lt;br /&gt;
The data for a pin can also read from a variable. These can be defined in the environment of the compound block or the [[Testsuite Element|testsuite]]. In the example, the user name and the server are fetched from such variables. A frozen pin should typically be configured to be non-triggering and non-consuming (so called &amp;quot;&#039;&#039;parameter pin&#039;&#039;&amp;quot;). For details on triggering and consumption of values, please read the chapter on [[DiagramElements-Pin#Input Pin| &amp;quot;&#039;&#039;Input Pin Trigger Behavior&#039;&#039;&amp;quot;]] in the [[DiagramElements-Pin | &amp;quot;&#039;&#039;pin documentation&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
In order to comment a diagram, or to place additional notes for developers and testers, annotations can be used. Annotations can be either text fields or imported graphics (GIF, JPEG or PNG images). You can highlight important parts of the diagram by using an empty text annotation with a non-white background color.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Probes]] ===&lt;br /&gt;
&lt;br /&gt;
Probes (not shown in the above diagram) allow for pin-values to be recorded and/or checked for being valid. Probes provide an easy to use and concise mechanism for value checking.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
=== Relationship to IEC1131 Function Block Diagrams ===&lt;br /&gt;
Expecco&#039;s compound action block execution model has many similarities with [https://en.wikipedia.org/wiki/IEC_61131 IEC-61131-3] (also IEC-1131-3 or EN 61131-3) [https://en.wikipedia.org/wiki/Function_block_diagram Function Block Diagrams]&lt;br /&gt;
which is a wellknown standard in programmable logic controller programming.&lt;br /&gt;
&lt;br /&gt;
Input values are read initially, the step execution is controlled by data flow, and output values are written&lt;br /&gt;
at the end of the action&#039;s execution. However, differences exist in the data types, which are more polymorphic in expecco, and additional pin attributes (such as eg. mailbox pins).&lt;br /&gt;
&lt;br /&gt;
=== Relationship to Petri Nets ===&lt;br /&gt;
A Petri Net [http://en.wikipedia.org/wiki/Petri%20net (see Wikipedia)] is a network consisting of places (with possible action processing) and transitions. In a classical petri net, anonymous tokens travel along connections and transitions control the firing (triggering) of following action steps depending on the arrival of tokens at their input side, and passing tokens to their output side.&lt;br /&gt;
&lt;br /&gt;
Expecco has combined the transition and place functionality into a single step item, in order to make the graphical representation more dense (and also for its similarity with UML-2 activity diagrams and other flow based diagrams). However, semantically, they behave the same, and any diagram could be rewritten by using separate items (collecting inputs and passing a tuple of tokens on to the place).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
An expecco step with multiple input pins corresponds to a Petri Net transition with multiple inputs followed by a Petri Net action. Similar to transitions in a Petri Net, the input side of a step can be configured to require either any input or all input values to be present. In expecco, this is called the step&#039;s &amp;quot;&#039;&#039;trigger condition&#039;&#039;&amp;quot; and described in detail in the [[DiagramElements-Step|step documentation]].&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Higher order Petri Nets&#039;&#039;&amp;quot; are Petri Nets containing other Petri Nets as places, which is exactly what a compound block is in expecco.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;&#039;&#039;Coloured Petri Nets&#039;&#039;&amp;quot; are Petri Nets where not simple anonymous tokens are passed around, but data objects (or references to them, as in expecco).&lt;br /&gt;
&lt;br /&gt;
Thus, in standard Petri Net notation, expecco&#039;s diagrams are therefore &amp;quot;&#039;&#039;Higher Order Colored Petri Nets&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relationship to UML Activity Diagrams ===&lt;br /&gt;
Compound actions in expecco are isomorph to UML activity diagrams with a particular predefined set of stereotypes for connections, pins and action steps. These stereotypes are hardcoded in expecco, and define the semantics of action triggering, queueing behaviour of data connections, and the optional parallel execution of steps. The graphical representation is slightly different, to replace the somewhat clumsy &amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt; annotations by different pin images (filled/unfilled etc.). Also, all connections in expecco are object-connections, and all pins receive and generate objects as values.&lt;br /&gt;
&lt;br /&gt;
=== Relationship to Flow Chart Diagrams ===&lt;br /&gt;
Activity diagrams can also be seen as a superset of flow chart diagrams. Flow charts can be translated into an activity diagram in which only control flow connections are used. Vice versa: an activity diagram which uses only control flow connections and uses no parallelism can be translated back into a flow chart diagram.&lt;br /&gt;
&lt;br /&gt;
The if-then-else conditional branches of a traditional flow chart diagram correspond to the 2-way if action blocks of the expecco standard library. Loops are implemented by connecting a trigger output pin to a previous step&#039;s trigger input pin.&lt;br /&gt;
&lt;br /&gt;
== Editors ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the &amp;quot;[[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;Network editor&#039;&#039;]]&amp;quot;, also called &amp;quot;&#039;&#039;Diagram Editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Network Diagram Editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;&#039;&#039;internal view&#039;&#039;&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of a compound block (e.g. number and type of pins) can be regarded as its &amp;quot;&#039;&#039;external view&#039;&#039;&amp;quot; and is presented and defined in the &amp;quot;[[Scheme Editor/en|&#039;&#039;Schema Editor&#039;&#039;]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Step]], [[DiagramElements-Connection|Connection]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementary Action]], &lt;br /&gt;
&lt;br /&gt;
Back to [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29651</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29651"/>
		<updated>2024-07-16T11:50:33Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Diagrammelemente */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Compound Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Relation zu IEC1131 ==&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
== Relation zu Petrinetzen ==&lt;br /&gt;
A Petri Net [http://en.wikipedia.org/wiki/Petri_net| -&amp;gt;Wikipedia] is a network consisting of places (with possible action processing) and transitions. In a classical petri net, anonymous tokens travel along connections and transitions control the firing (triggering) of following action steps depending on the arrival of tokens at their input side, and passing tokens to their output side. Expecco has combined the transition and place functionality into a single step item, in order to make the graphical representation more dense (and also for its similarity with UML-2 activity diagrams and other flow based diagrams). However, semantically, they behave the same, and any diagram could be rewritten by using separate items (collecting inputs and passing a tuple of tokens on to the place).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
An expecco step with multiple input pins corresponds to a Petri Net transition with multiple inputs followed by a Petri Net action. Similar to transitions in a Petri Net, the input side of a step can be configured to require either any input or all input values to be present. In expecco, this is called the step&#039;s &amp;quot;&#039;&#039;trigger condition&#039;&#039;&amp;quot; and described in detail in the [[DiagramElements-Step|step documentation]].&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Higher order Petri Nets&#039;&#039;&amp;quot; are Petri Nets containing other Petri Nets as places, which is exactly what a compound block is in expecco.&lt;br /&gt;
&amp;quot;&#039;&#039;Coloured Petri Nets&#039;&#039;&amp;quot; are Petri Nets where not simple anonymous tokens are passed around, but data objects (or references to them, as in expecco).&lt;br /&gt;
&lt;br /&gt;
Thus, in standard Petri Net notation, expecco&#039;s diagrams are therefore &amp;quot;&#039;&#039;higher ordered colored Petri Nets&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Relation zu UML Aktivitätsdiagrammen ==&lt;br /&gt;
 --- to be written&lt;br /&gt;
&lt;br /&gt;
== Relation zu Flussdiagrammen ==&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the [[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;network editor&#039;&#039;]], also called &amp;quot;&#039;&#039;diagram editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;network diagram editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;internal view&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of an compound block (e.g. number and type of pins) can be regarded as its &amp;quot;external view&amp;quot; and is presented and defined in the [[Scheme Editor/en|&#039;&#039;schema editor&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element/en&amp;diff=29650</id>
		<title>CompoundBlock Element/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element/en&amp;diff=29650"/>
		<updated>2024-07-16T10:56:23Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Introduction */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
A &amp;quot;&#039;&#039;Compound Action Block&#039;&#039;&amp;quot; describes an [[Block_Element/en|action]]&#039;s behavior with an activity diagram. The diagram is similar to [[#Relationship_to_UML_Activity_Diagrams|data flow diagrams]] as used in UML2.0 and also has many features in common with [[#Relationship_to_Petri_Nets|Petri Nets]]. The diagram consists of sub actions called [[DiagramElements-Step|&#039;&#039;steps&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
The execution is controlled via a combination of data and control flows which are passed via inter-step connections:&lt;br /&gt;
&lt;br /&gt;
* Data flows are defined as values (results, measurement values, objects, documents etc.) being passed from one step to another. These flows are defined by interconnections from a step&#039;s [[DiagramElements-Pin#Output Pin|output pin]] to another step&#039;s [[DiagramElements-Pin#Input Pin|input pin]]. &lt;br /&gt;
&lt;br /&gt;
* Control flows are defined as &amp;quot;&#039;&#039;action finished&#039;&#039;&amp;quot; information being used to trigger another step&#039;s action. These flows are defined by interconnections from a step&#039;s [[DiagramElements-Pin#Enable_Output_Pin|&#039;&#039;Trigger Output Pin&#039;&#039;]] to another step&#039;s [[DiagramElements-Pin#Enable_Input_Pin|&#039;&#039;Trigger Input Pin&#039;&#039;]].&amp;lt;br&amp;gt;(these are also occasionally called &amp;quot;&#039;&#039;Enable Output Pin&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Enable Input Pin&#039;&#039;&amp;quot; in this documentation).&lt;br /&gt;
&lt;br /&gt;
Both can trigger the execution of a subsequent step.&lt;br /&gt;
&lt;br /&gt;
== Diagram Elements ==&lt;br /&gt;
Diagram elements are the elements in an activity diagram. They define the behavior of the [[Compound Block|compound action block]] and are manipulated in the [[Network Editor/en|network editor]].&lt;br /&gt;
&lt;br /&gt;
== Introductory Activity Diagram Example ==&lt;br /&gt;
&lt;br /&gt;
The following example shows the major components of an activity diagram.&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|An activity diagram]]&lt;br /&gt;
&lt;br /&gt;
The diagram models a test of an e-mail transmission:&lt;br /&gt;
* First, the step &amp;quot;Create Unique ID&amp;quot; creates a so-called [[Glossary/en#UUID_.28Universal_Unique_Identifier.29 |UUID]] (Universal Unique Identifier) at its output pin, which is used later to check whether the correct e-mail has arrived.&lt;br /&gt;
* The UUID is delivered to the step &amp;quot;Send E-Mail [SMTP]&amp;quot;, which sends an e-mail via SMTP ([https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol &amp;quot;Simple Mail Transfer Protocol&amp;quot;]) using the UUID as subject.&lt;br /&gt;
* Next, the &amp;quot;Time [Delay]&amp;quot; step waits for 5 seconds.&lt;br /&gt;
* Finally, &amp;quot;Check for incoming Mail&amp;quot; checks whether an e-mail has arrived with the given UUID as subject. If there is no such e-mail the test will fail.&lt;br /&gt;
&lt;br /&gt;
Notice that the definition of activity diagrams in expecco corresponds largely with the UML notation. However, to emphasize important aspects and to make the diagram easier to read, some elements differ slightly from the standard UML notation. Especially, pin stereotypes are rendered directly as different pin style instead of adding extra &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot; labels.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Step]] (7) ===&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;&#039;&#039;step&#039;&#039;&amp;quot; is a action block which is placed into an activity diagram. These blocks can be either [[Elementary Block|elementary blocks]] (such as &amp;quot;Create Unique ID&amp;quot;) which are defined by a piece of source code or [[Compound Block|compound blocks]] (such as &amp;quot;Check Incoming Mail&amp;quot;) which are defined by their own activity diagram. To the network where a block is placed, there is no difference in the behavior. The network which uses an action (i.e. places a step) does not need to know how the internals of the action are implemented. Actually, there is not even a visual difference in the diagram. All are triggered by the availability of input data, perform an operation, and generate results on their output(s). &lt;br /&gt;
&lt;br /&gt;
Steps are described in detail in a [[DiagramElements-Step | separate document]].&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
A step with autostart option will be triggered automatically, whenever the containing activity diagram network is executed. Without the autostart option, steps are only started when input data arrives at the step&#039;s input pin(s). Autostart is required for steps which have no input and are not triggered by a control flow connection. In the above diagram, this is the case for the leftmost &amp;quot;Create Unique ID&amp;quot; step.&lt;br /&gt;
&lt;br /&gt;
The diagram editor renders auto started blocks with a special icon at its top-left corner; if you prefer the standard UML notation, you can place a separate START block and connect its trigger pins.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] are used to exchange data and trigger information between steps. &lt;br /&gt;
These pins can be [[DiagramElements-Pin#Output Pin|output pins]] (3) to send data or [[DiagramElements-Pin#Input Pin|input pins]] (9) to receive data. &lt;br /&gt;
Other pins are used for special tasks like [[DiagramElements-Pin#Exception Output Pin|exception handling]];&lt;br /&gt;
in the above diagram, the vertical exception output of the &amp;quot;Check Incoming Mail&amp;quot; step is connected to the trigger input of the &amp;quot;FAIL&amp;quot; notifying step.&lt;br /&gt;
&lt;br /&gt;
Control-flow pins (trigger and status) are oriented vertically, whereas data-flow pins are oriented horizontally.&lt;br /&gt;
Input pins are always located at the top or left, whereas output pins are located at the right or bottom.&lt;br /&gt;
&lt;br /&gt;
Pins are rendered according to their behavior during execution;&lt;br /&gt;
especially consuming vs. non-consuming input behaviour&lt;br /&gt;
and buffered vs. non-buffered output behavior &lt;br /&gt;
is drawn (filled vs. unfilled) to highlight these important facts. &lt;br /&gt;
&lt;br /&gt;
Pins are described in detail in a [[DiagramElements-Pin | separate document]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Connection]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Connections are used to interconnect steps to pass data or control information from an output pin to one or more input pins.&lt;br /&gt;
In the UML sense, all connections are object connections.&lt;br /&gt;
&lt;br /&gt;
==== Data Flow Connection (4) ====&lt;br /&gt;
&lt;br /&gt;
These connections deliver data from a step&#039;s output pin to another step&#039;s input pin. In the example, the first step sends the generated UUID to two other steps.&lt;br /&gt;
Data flow pins are always located at the left and right of a step (horizontal pins), and the left pins are always inputs, whereas the right pins are always outputs.&lt;br /&gt;
&lt;br /&gt;
==== Control Flow Connection (8) ====&lt;br /&gt;
&lt;br /&gt;
These connections are used to control the execution order in an activity diagram. In the example the steps on the right are executed sequential.&lt;br /&gt;
Control flow pins are always located at the top and bottom of a step (vertical pins), and pins at the top are always inputs, whereas pins at the bottom are always outputs.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value]] (6) ===&lt;br /&gt;
&lt;br /&gt;
The data which is read by a pin can be &#039;&#039;frozen&#039;&#039; to a static value (constant). In the above example, the &amp;quot;message text&amp;quot;, the &amp;quot;e-mail address&amp;quot;, the &amp;quot;waiting time&amp;quot; and also the &amp;quot;failure message&amp;quot; are &#039;&#039;frozen&#039;&#039;.&lt;br /&gt;
A frozen pin should typically be configured to be non-triggering and non-consuming (so called &amp;quot;&#039;&#039;parameter pin&#039;&#039;&amp;quot;). For details on triggering and consumption of values, please read the chapter on [[DiagramElements-Pin#Input_Pin_Trigger_Attributes |&amp;quot;&#039;&#039;Input Pin Trigger Behavior&#039;&#039;&amp;quot;]] in the [[DiagramElements-Pin | &amp;quot;&#039;&#039;pin documentation&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Environment Freeze Value]] (5) ===&lt;br /&gt;
&lt;br /&gt;
The data for a pin can also read from a variable. These can be defined in the environment of the compound block or the [[Testsuite Element|testsuite]]. In the example, the user name and the server are fetched from such variables. A frozen pin should typically be configured to be non-triggering and non-consuming (so called &amp;quot;&#039;&#039;parameter pin&#039;&#039;&amp;quot;). For details on triggering and consumption of values, please read the chapter on [[DiagramElements-Pin#Input Pin| &amp;quot;&#039;&#039;Input Pin Trigger Behavior&#039;&#039;&amp;quot;]] in the [[DiagramElements-Pin | &amp;quot;&#039;&#039;pin documentation&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
In order to comment a diagram, or to place additional notes for developers and testers, annotations can be used. Annotations can be either text fields or imported graphics (GIF, JPEG or PNG images). You can highlight important parts of the diagram by using an empty text annotation with a non-white background color.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Probes]] ===&lt;br /&gt;
&lt;br /&gt;
Probes (not shown in the above diagram) allow for pin-values to be recorded and/or checked for being valid. Probes provide an easy to use and concise mechanism for value checking.&lt;br /&gt;
&lt;br /&gt;
== Semantics ==&lt;br /&gt;
&lt;br /&gt;
=== Relationship to IEC1131 Function Block Diagrams ===&lt;br /&gt;
Expecco&#039;s compound action block execution model has many similarities with [https://en.wikipedia.org/wiki/IEC_61131 IEC-61131-3] (also IEC-1131-3 or EN 61131-3) [https://en.wikipedia.org/wiki/Function_block_diagram Function Block Diagrams]&lt;br /&gt;
which is a wellknown standard in programmable logic controller programming.&lt;br /&gt;
&lt;br /&gt;
Input values are read initially, the step execution is controlled by data flow, and output values are written&lt;br /&gt;
at the end of the action&#039;s execution. However, differences exist in the data types, which are more polymorphic in expecco, and additional pin attributes (such as eg. mailbox pins).&lt;br /&gt;
&lt;br /&gt;
=== Relationship to Petri Nets ===&lt;br /&gt;
A Petri Net [http://en.wikipedia.org/wiki/Petri%20net (see Wikipedia)] is a network consisting of places (with possible action processing) and transitions. In a classical petri net, anonymous tokens travel along connections and transitions control the firing (triggering) of following action steps depending on the arrival of tokens at their input side, and passing tokens to their output side.&lt;br /&gt;
&lt;br /&gt;
Expecco has combined the transition and place functionality into a single step item, in order to make the graphical representation more dense (and also for its similarity with UML-2 activity diagrams and other flow based diagrams). However, semantically, they behave the same, and any diagram could be rewritten by using separate items (collecting inputs and passing a tuple of tokens on to the place).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
An expecco step with multiple input pins corresponds to a Petri Net transition with multiple inputs followed by a Petri Net action. Similar to transitions in a Petri Net, the input side of a step can be configured to require either any input or all input values to be present. In expecco, this is called the step&#039;s &amp;quot;&#039;&#039;trigger condition&#039;&#039;&amp;quot; and described in detail in the [[DiagramElements-Step|step documentation]].&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Higher order Petri Nets&#039;&#039;&amp;quot; are Petri Nets containing other Petri Nets as places, which is exactly what a compound block is in expecco.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;quot;&#039;&#039;Coloured Petri Nets&#039;&#039;&amp;quot; are Petri Nets where not simple anonymous tokens are passed around, but data objects (or references to them, as in expecco).&lt;br /&gt;
&lt;br /&gt;
Thus, in standard Petri Net notation, expecco&#039;s diagrams are therefore &amp;quot;&#039;&#039;Higher Order Colored Petri Nets&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Relationship to UML Activity Diagrams ===&lt;br /&gt;
Compound actions in expecco are isomorph to UML activity diagrams with a particular predefined set of stereotypes for connections, pins and action steps. These stereotypes are hardcoded in expecco, and define the semantics of action triggering, queueing behaviour of data connections, and the optional parallel execution of steps. The graphical representation is slightly different, to replace the somewhat clumsy &amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt; annotations by different pin images (filled/unfilled etc.). Also, all connections in expecco are object-connections, and all pins receive and generate objects as values.&lt;br /&gt;
&lt;br /&gt;
=== Relationship to Flow Chart Diagrams ===&lt;br /&gt;
Activity diagrams can also be seen as a superset of flow chart diagrams. Flow charts can be translated into an activity diagram in which only control flow connections are used. Vice versa: an activity diagram which uses only control flow connections and uses no parallelism can be translated back into a flow chart diagram.&lt;br /&gt;
&lt;br /&gt;
The if-then-else conditional branches of a traditional flow chart diagram correspond to the 2-way if action blocks of the expecco standard library. Loops are implemented by connecting a trigger output pin to a previous step&#039;s trigger input pin.&lt;br /&gt;
&lt;br /&gt;
== Editors ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the &amp;quot;[[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;Network editor&#039;&#039;]]&amp;quot;, also called &amp;quot;&#039;&#039;Diagram Editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Network Diagram Editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;&#039;&#039;internal view&#039;&#039;&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of a compound block (e.g. number and type of pins) can be regarded as its &amp;quot;&#039;&#039;external view&#039;&#039;&amp;quot; and is presented and defined in the &amp;quot;[[Scheme Editor/en|&#039;&#039;Schema Editor&#039;&#039;]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
[[Tree Elements | Tree Elements]]&lt;br /&gt;
&lt;br /&gt;
[[Block Element]], [[DiagramElements-Step/en|Step]], [[DiagramElements-Connection|Connection]],&lt;br /&gt;
[[ElementaryBlock_Element|Elementary Action]], &lt;br /&gt;
&lt;br /&gt;
Back to [[Online Documentation#Tree Elements|Online Documentation]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29649</id>
		<title>CompoundBlock Element</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=CompoundBlock_Element&amp;diff=29649"/>
		<updated>2024-07-16T10:54:17Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Einführung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einführung ==&lt;br /&gt;
Ein zusammengesetzter Aktionsblock (englisch &amp;quot;&#039;&#039;Compound Action&#039;&#039;&amp;quot;) beschreibt das Verhalten einer [[Block_Element|Aktion]] graphisch als Aktivitätsdiagramm. Diese Diagramme sind vergleichbar mit den [[#Relation_zu_UML_Aktivit.C3.A4tsdiagrammen|Datenflussdiagrammen]] wie in UML2.0 definiert. Sie haben außerdem viele Eigenschaften gemein mit [[#Relation_zu_Petrinetzen|Petrinetzen]]. Das Diagramm besteht aus Unteraktionen, welche als [[DiagramElements-Step|&#039;&#039;Schritte&#039;&#039;]] bezeichnet werden.&lt;br /&gt;
&lt;br /&gt;
Die Ausführung wird durch eine Kombination von Daten- und Kontrollflüssen gesteuert, die durch Verbindungen zwischen den Schritten übertragen werden:&lt;br /&gt;
* Als Datenfluss wird die Übergabe von Werten (Resultate, Messwerte, Objekte, Dokumente etc.) von einem Schritt zum nächsten bezeichnet. Ein Datenfluss läuft über Verbindungen vom [[DiagramElements-Pin#Output_Pin|Ausgangspin]] (Pin = &amp;quot;Stecker/Sockel&amp;quot;) eines Schritts zum [[DiagramElements-Pin#Input_Pin|Eingangspin]] eines anderen.&lt;br /&gt;
* Kontrollflüsse sind Informationen zum Endestatus eines Schrittes, die verwendet werden können, um die Aktion eines nächsten Schritts zu starten. Sie laufen über Verbindungen vom [[DiagramElements-Pin#Enable_Output_Pin|Trigger-Ausgang]] eines Schrittes zum [[DiagramElements-Pin#Enable_Input_Pin|Trigger-Eingang]] eines anderen.&lt;br /&gt;
Beide können die Ausführung eines Folgeschritts auslösen.&lt;br /&gt;
&lt;br /&gt;
== Diagrammelemente ==&lt;br /&gt;
Als &amp;quot;&#039;&#039;Diagrammelemente&#039;&#039;&amp;quot; werden die Bestandteile eines Aktivitätsdiagramms bezeichnet. Sie definieren das Verhalten des [[Compound Block|Zusammengesetzten Aktionsblocks]] und werden im [[Network Editor|Netzwerkeditor]] bearbeitet.&lt;br /&gt;
&lt;br /&gt;
== Einführendes Beispiel eines Aktivitätsdiagramms ==&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel erläutert die Hauptkomponenten eines Aktivitätsdiagramms:&lt;br /&gt;
&lt;br /&gt;
[[Bild:diagram-elements.jpg|760px|Ein Aktivitätsdiagramm]]&lt;br /&gt;
&lt;br /&gt;
Das Diagramm beschreibt den Test einer E-Mail-Übertragung. Zuerst erzeugt der Schritt &amp;quot;Create Unique ID&amp;quot; eine sog. UUID und stellt diese an seinem Ausgangspin zur Verfügung. Diese UUID wird später gebraucht, um den korrekten Empfang der E-Mail zu verifizieren. Die UUID wird vom Schritt &amp;quot;Send E-Mail [SMTP]&amp;quot; empfangen, welcher eine E-Mail mittels dem SMTP Protokoll verschickt, und die UUID als Subject verwendet. Als nächstes sorgt der &amp;quot;Time [Delay]&amp;quot; Schritt für eine Verzögerung von 5 Sekunden (in denen die E-Mail übermittelt wird). Am Ende prüft der Schritt &amp;quot;Check for incoming Mail&amp;quot; ob eine E-Mail mit dem angegebenen Subject angekommen ist, wozu obige UUID gebraucht wird.&lt;br /&gt;
Der Test wird einen Fehler melden, falls eine solche E-Mail nicht gefunden wird.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie bitte, dass die graphische Darstellung des Diagramms im Grunde der UML-Notation entspricht. Allerdings werden um die Lesbarkeit zu erhöhen, und um wichtige Aspekte der Ausführung hervorzuheben einige Element etwas anders bzw. zusätzlich annotiert dargestellt. Insbesondere werden die Stereotypen der Pins durch unterschiedliche Pin-Darstellungen hervorgehoben, anstatt durch textuelle &amp;quot;&amp;lt;&amp;lt;stereotype&amp;gt;&amp;gt;&amp;quot;-labels, wie in UML.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Originaltext: Die Definition des Aktivitätsdiagramms entspricht weitgehend der UML-Notation. Einzelne, für die Ausführung wichtige Eigenschaften werden allerdings graphisch hervorgehoben, wodurch sich das Bild im Detail von der UML-Notation leicht unterscheidet. Zum Beispiel werden die Trigger- und Puffer Eigenschaften der Pins durch verschiedene graphische Symbole angezeigt - zu diesen gibt es in der UML-Notation kein Gegenstück, da die UML-Notation derlei semantische Details unbeachtet bzw. durch Benutzerspezifische, nicht standardisierte Stereotypdefinitionen offen lässt (Stand UML2.0).--&amp;gt;&lt;br /&gt;
=== [[DiagramElements-Step|Schritt]] (7) ===&lt;br /&gt;
&lt;br /&gt;
Als &amp;quot;&#039;&#039;Schritt&#039;&#039;&amp;quot; wird eine Aktion (Aktionsbaustein) bezeichnet, welcher in ein Diagramm platziert wurde. Diese Aktion kann ihrerseits entweder ein sog. [[Elementary Block|Elementablock]] sein (wie z.B. &amp;quot;Create Unique ID&amp;quot;), welche ihre Aktion durch eine textuellen Programmcode definiert, oder wieder ein [[Compound Block|zusammengesetzter Block]] (wie z.B. &amp;quot;Check Incoming Mail&amp;quot;), welcher durch ein eigenes Aktivitätsdiagramm definiert wurde. Für das Diagrammnetzwerk in welches der Aktionsblock platziert wurde ist kein Unterschied im Verhalten sichtbar: ein Diagramm, welches einen Aktionsblock beinhaltet (d.h. einen Schritt enthält) sieht kein unterschiedliches Verhalten in Abhängigkeit der effektiven Realisierung seiner Schritte. Tatsächlich gibt es auch keine Unterschiede in der graphischen Darstellung, so dass es auch für den Entwickler eines zusammengesetzten Blocks keinen Unterschied macht (er muss nicht wissen, wie die Interna einer Aktion aufgebaut sind). Alle Schritte werden gleichermaßen durch die Verfügbarkeit von Eingangsdaten gestartet, führen ihre Bearbeitung durch, und liefern ihre Resultate an den Ausgangspins. Details zum Verhalten von Schritten sind in einem [[DiagramElements-Step | separaten Document]] nachzulesen.&lt;br /&gt;
&lt;br /&gt;
=== Autostart (1) ===&lt;br /&gt;
&lt;br /&gt;
Ein Schritt mit der Autostart Option wird automatisch gestartet, sobald das umgebende Netzwerk ausgeführt wird. Schritte ohne Autostart-Option werden lediglich ausgeführt, sobald Daten an den Eingangspins des Schrittes erscheinen. Autostart wird insbesondere für Schritte benötigt, welche keine Eingangspins haben, oder welche nicht durch einen Kontrollfluss gestartet werden. Auch Schritte, deren Eingang lediglich konstante Parameter darstellen müssen so gestartet werden. Im obigen Diagramm trifft dies für den linken &amp;quot;Create Unique ID&amp;quot; Schritt zu.&lt;br /&gt;
&lt;br /&gt;
Im Diagrammeditor werden Schritte mit Autostart mit einem speziellen Icon am linken oberen Rand dargestellt; falls Sie die Standard-UML-Notation bevorzugen, können Sie auch einen START-Block aus der Bibliothek verwenden und dessen Trigger-Ausgangspin mit dem zuerst auszuführenden Schritt verbinden.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Pin|Pin]] (3, 6, 9) ===&lt;br /&gt;
&lt;br /&gt;
[[DiagramElements-Pin|Pins]] dienen zur Weitergabe von Daten und Triggerinformationen zwischen Schritten. Diese Pins können entweder [[DiagramElements-Pin#Output Pin|Ausgangespins]] (3) sein, um Daten zu senden, oder [[DiagramElements-Pin#Input Pin|Eingangspins]] (9), um Daten zu empfangen. Weitere Pins dienen dazu besondere Situationen wie z.B. [[DiagramElements-Pin#Exception Output Pin|Ausnahmebehandlung]] zu melden. Im obigen Diagramm, ist der Exception-Ausgang des &amp;quot;Check Incoming Mail&amp;quot; Schritts mit dem Trigger-Eingang des &amp;quot;FAIL&amp;quot; Schrittes verbunden.&lt;br /&gt;
Kontrollflusspins (Trigger und Status) sind vertikal angeordnet, wohingegen Datenflüsse als horizontal Pins dargestellt werden.&lt;br /&gt;
Eingangspins sind immer oben oder links, Ausgangspins immer unten oder rechts angeordnet.&lt;br /&gt;
Pins werden entsprechend ihrem Verhalten leicht unterschiedlich dargestellt; insbesondere auf das Puffer- und Triggerverhalten wird durch ausgefüllt vs. nicht gefüllt hingewiesen, da diese wichtig sind für die Ausführung. Pins werden in einem [[DiagramElements-Pin | separaten Dokument]] detailliert beschrieben.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Connection|Verbindung]] (4,8) ===&lt;br /&gt;
&lt;br /&gt;
Verbindungen dienen zum Weiterleiten von Daten oder Kontrollinformationen zu einem oder mehreren Eingangspins (eines oder mehrerer Folgeschritte).&lt;br /&gt;
Im Sinne von UML sind alle Verbindungen in expecco immer &amp;quot;Objektverbindungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Datenflussverbindung (4) ====&lt;br /&gt;
&lt;br /&gt;
Diese befördern Daten (-Objekte) von einem Ausgangspin zu einem Eingangspins eines Folgeschritts. Im obigen Beispiel sendet der erste Schritt die erzeugte UUID an zwei weitere Schritte.&lt;br /&gt;
Datenflusspins sind immer links und rechts angeordnet (horizontale Pins).&lt;br /&gt;
&lt;br /&gt;
==== Kontrollflussverbindung (8) ====&lt;br /&gt;
&lt;br /&gt;
Diese dienen dazu, die Ausführung unabhängig von Daten (aber abhängig von der Ausführung eines Schrittes) zu kontrollieren. Im Beispiel werden die Schritte rechts im Bild sequentiell ausgeführt, wozu der Triggerausgang eines Schrittes mit dem Triggereingang eines Folgeschrittes verbunden wurde.&lt;br /&gt;
Kontrollflusspins sind immer oben und unten angeordnet (vertikale Pins).&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Freeze Value (Vorbelegungswert)]] (6) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können mit einem statischen Wert vorbelegt werden (Konstante).&lt;br /&gt;
Im Beispiel sind der Text der E-Mail, die E-Mail-Adresse, die Wartezeit und auch die Fehlermeldung auf diese Weise &amp;quot;eingefroren&amp;quot;.&lt;br /&gt;
Ein vorbelegter Pin sollte typischerweise als nicht-triggernd und nicht-konsumierend (sogenannter &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;) konfiguriert werden, wofür es einen besonderen Menüeintrag gibt (außerdem werden beim &amp;quot;&#039;&#039;Einfrieren&#039;&#039;&amp;quot; die Pins vom Editor automatisch als solche umdefiniert). Details zum Triggerverhalten und zum Konsumieren von Eingangswerten finden sie im Dokument: [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Freeze Value|Vorbelegung aus Umgebungsvariablen]] (5) ===&lt;br /&gt;
&lt;br /&gt;
Eingangswerte eines Pins können ebenfalls aus einer Variable gelesen werden. Diese Variablen werden in einer sogenannten &amp;quot;&#039;&#039;Variablenumgebung&#039;&#039;&amp;quot; bereit gestellt, welche im umgebenden zusammengesetzten Bausteinen oder der [[TestSuite Element|Testsuite]] definiert werden. Im obigen Beispiel werden der Name des E-Mail-Kontos sowie der E-Mail-Serverhost aus solchen Variablen gelesen (und entsprechende Einträge in der Variablenumgebung der Testsuite vorausgesetzt). Wie auch reguläre Vorbelegungen sollte der Pin als nicht-triggernd und nicht-konsumierend definiert werden (i.e. &amp;quot;&#039;&#039;Parameterpin&#039;&#039;&amp;quot;). Lesen Sie dazu ebenfalls das Kapitel [[DiagramElements-Pin#Input Pin|&amp;quot;&#039;&#039;Verhalten von Eingangspins&#039;&#039;&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Annotation|Annotation]] (2) ===&lt;br /&gt;
&lt;br /&gt;
Annotationen dienen dazu, Kommentare oder Zusatzinformationen für Entwickler oder Tester im Diagramm mit abzulegen. Möglich sind sowohl textuelle Annotation, als auch importierte Grafiken (Bilder im GIF-, JPEG- oder PNG-Format). Sie können auch dazu genutzt werden, um wichtige Teile des Diagramms farblich hervorzuheben, indem Sie eine leere Textannotation mit einer Hintergrundfarbe unter Teile ihres Diagramms legen.&lt;br /&gt;
&lt;br /&gt;
=== [[DiagramElements-Probe|Messfühler]] ===&lt;br /&gt;
&lt;br /&gt;
Messfühler (im obigen Diagramm nicht gezeigt) dienen dazu Pin-Werte aufzuzeichnen und/oder zu validieren. Messfühler bieten einen komfortablen und lesbaren Mechanismus um Werte auf ihre Gültigkeit zu prüfen.&lt;br /&gt;
&lt;br /&gt;
== Relation zu IEC1131 ==&lt;br /&gt;
Expeccos Aktivitätsdiagramme ähneln stark den Funktionblöcken der IEC1131-3 FBD Sprache (siehe ua. [https://en.wikipedia.org/wiki/Function_block_diagram Wikipedia]).&lt;br /&gt;
Sowohl die grafische Darstellung als auch das Ausführungsverhalten sind vergleichbar. Ingenieure mit einem SPS Hintergrund werden keine Probleme haben, Expeccos Aktionsdefinitionen und zusammengesetzte Aktionen zu verstehen.&lt;br /&gt;
&lt;br /&gt;
== Relation zu Petrinetzen ==&lt;br /&gt;
A Petri Net [http://en.wikipedia.org/wiki/Petri_net| -&amp;gt;Wikipedia] is a network consisting of places (with possible action processing) and transitions. In a classical petri net, anonymous tokens travel along connections and transitions control the firing (triggering) of following action steps depending on the arrival of tokens at their input side, and passing tokens to their output side. Expecco has combined the transition and place functionality into a single step item, in order to make the graphical representation more dense (and also for its similarity with UML-2 activity diagrams and other flow based diagrams). However, semantically, they behave the same, and any diagram could be rewritten by using separate items (collecting inputs and passing a tuple of tokens on to the place).&lt;br /&gt;
&lt;br /&gt;
[[Datei:Beispiel.png]]&lt;br /&gt;
&lt;br /&gt;
An expecco step with multiple input pins corresponds to a Petri Net transition with multiple inputs followed by a Petri Net action. Similar to transitions in a Petri Net, the input side of a step can be configured to require either any input or all input values to be present. In expecco, this is called the step&#039;s &amp;quot;&#039;&#039;trigger condition&#039;&#039;&amp;quot; and described in detail in the [[DiagramElements-Step|step documentation]].&lt;br /&gt;
&lt;br /&gt;
&amp;quot;&#039;&#039;Higher order Petri Nets&#039;&#039;&amp;quot; are Petri Nets containing other Petri Nets as places, which is exactly what a compound block is in expecco.&lt;br /&gt;
&amp;quot;&#039;&#039;Coloured Petri Nets&#039;&#039;&amp;quot; are Petri Nets where not simple anonymous tokens are passed around, but data objects (or references to them, as in expecco).&lt;br /&gt;
&lt;br /&gt;
Thus, in standard Petri Net notation, expecco&#039;s diagrams are therefore &amp;quot;&#039;&#039;higher ordered colored Petri Nets&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Relation zu UML Aktivitätsdiagrammen ==&lt;br /&gt;
 --- to be written&lt;br /&gt;
&lt;br /&gt;
== Relation zu Flussdiagrammen ==&lt;br /&gt;
Aktivitätsdiagramme können als Obermenge von Flussdiagrammen betrachtet werden. Dazu werden die Aktionen lediglich über Kontrollflussverbindungen (Trigger-in/Trigger-out) verbunden (Daten werden hierbei über Variablen ausgetauscht).&lt;br /&gt;
&lt;br /&gt;
Die Wenn-Dann bedingte Verzeigung eines Flussdiagramms entspricht einem 2-Wege-If Aktionsblock (aus der Standardbibliothek). Schleifen werden durch Verbindungen der Trigger-out mit einem Trigger-in eines vorhergehenden Schrittes definiert.&lt;br /&gt;
&lt;br /&gt;
== Editoren ==&lt;br /&gt;
The activity diagram which defines the behavior of a compound block&lt;br /&gt;
is edited in the [[CompoundBlock Editor-CompoundWorksheet Editor/en|&#039;&#039;network editor&#039;&#039;]], also called &amp;quot;&#039;&#039;diagram editor&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;network diagram editor&#039;&#039;&amp;quot;.&lt;br /&gt;
This editor presents the &amp;quot;internal view&amp;quot; of the block.&lt;br /&gt;
In contrast, the interface of an compound block (e.g. number and type of pins) can be regarded as its &amp;quot;external view&amp;quot; and is presented and defined in the [[Scheme Editor/en|&#039;&#039;schema editor&#039;&#039;]].&lt;br /&gt;
&lt;br /&gt;
[[Category: Tree Elements]]&lt;br /&gt;
[[Category: Incomplete]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29634</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29634"/>
		<updated>2024-07-11T09:37:37Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */ new supplement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
The &#039;&#039;Mobile Testing Plugin&#039;&#039; adds mechanisms to test and automate Android and iOS devices. This includes both real and emulated devices - it does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; startChromedriverTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29633</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29633"/>
		<updated>2024-07-11T09:36:15Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */ new supplement&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 24.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-24.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.3]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.2: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29406</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29406"/>
		<updated>2024-05-29T07:42:43Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 24.1 (2Q 2024) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt; ([[Qt_Inject_Windows/en#Logging|Qt-Logging]])&lt;br /&gt;
*Feature: Qt-Testing: Qt-Connections now use the ConnectionManager like the other Gui test technologies&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: [[Testsuite_Editor-ExecutionSettings_Editor/en|Settings for execution]] (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved refactoring for compound blocks: &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: Enhanced expecco reflection library&lt;br /&gt;
*Feature: Logprocessors can be executed for embedded testplans&lt;br /&gt;
*Feature: Logging of background actions can be individually enabled and disabled for testplans and nested testplans&lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;br /&gt;
*Fix: Acitivity logs of asynchronous events in background actions are now displayed correctly in the background activity log.&lt;br /&gt;
*Fix: Qt: Drag and drop improved by revising the &amp;quot;Move mouse event&amp;quot; (Windows)&lt;br /&gt;
*Fix: Disabling logs of sub-activities (if successful, if not successful, etc.)&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29405</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29405"/>
		<updated>2024-05-28T07:12:16Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 24.1 (2Q 2024) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt; ([[Qt_Inject_Windows/en#Logging|Qt-Logging]])&lt;br /&gt;
*Feature: Qt-Testing: Qt-Connections now use the ConnectionManager like the other Gui test technologies&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: [[Testsuite_Editor-ExecutionSettings_Editor/en|Settings for execution]] (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved refactoring for compound blocks: &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: Enhanced expecco reflection library&lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;br /&gt;
*Fix: Acitivity logs of asynchronous events in background actions are now displayed correctly in the background activity log.&lt;br /&gt;
*Fix: Qt: Drag and drop improved by revising the &amp;quot;Move mouse event&amp;quot; (Windows)&lt;br /&gt;
*Fix: Disabling logs of sub-activities (if successful, if not successful, etc.)&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Test_Editor/en&amp;diff=29345</id>
		<title>Test Editor/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Test_Editor/en&amp;diff=29345"/>
		<updated>2024-05-07T15:18:56Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Timeline View */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:Test Editor.png|thumb|300px|Test Editor after a run]]&lt;br /&gt;
Notice: starting with release 1.8, this editor has been split into separate editor and execution tabs:&lt;br /&gt;
;Test/Demo&lt;br /&gt;
:Definition of the network under test. This is used to define a test or demo for the edited action. As such, it combines features of the [[CompoundBlock Editor-CompoundWorksheet Editor/en|network editor]].&lt;br /&gt;
;Run&lt;br /&gt;
:Shows information of the current or last execution of the network under test.&lt;br /&gt;
&lt;br /&gt;
The separation was made to make better use of the screen (which was too filled for small displays) and also to reuse the execution output view in the [[GUI Browser/en|GUI-Browser]]. This document describes the previous combined editor.&lt;br /&gt;
&lt;br /&gt;
=== As Part of an Action Block Definition ===&lt;br /&gt;
Every action can have an associated &amp;quot;&#039;&#039;Test Network&#039;&#039;&amp;quot; which is shown in the &amp;quot;&#039;&#039;Test/Demo&#039;&#039;&amp;quot; tab. The test network typically shows how the action is to be used and/or contains a unit test of the action.&lt;br /&gt;
We highly recommend that all of your actions provide an executable example of its use, both as a &amp;quot;unit test&amp;quot; and as additional documentation. It may also be used as a place to provide ready-to-use setups, which can be copied/pasted into other networks.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;&#039;&#039;Test/Demo&#039;&#039;&amp;quot; network should not be used for &amp;quot;official&amp;quot; test-runs. Instead, always put real tests into a testplan and only use the test/demo network for the &amp;quot;private&amp;quot; execution of a single block &lt;br /&gt;
(i.e. unit tests for the action itself) or as a place for demonstration or &amp;quot;executable documentation&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To the right, you see a test editor after the successful execution of a test-block.&lt;br /&gt;
&lt;br /&gt;
=== As Part of the GUI Browser ===&lt;br /&gt;
&lt;br /&gt;
In this context, the test run tab presents the outcome of the last&lt;br /&gt;
execution within the GUI browser. This can be either the single action or the complete sequence as recorded so far.&lt;br /&gt;
&lt;br /&gt;
=== As Part of the Testplan Editor ===&lt;br /&gt;
&lt;br /&gt;
Here the outcome of the selected test case is presented.&lt;br /&gt;
&lt;br /&gt;
= Buttons =&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Run.png]] &amp;quot;Run&amp;quot; &amp;lt;br&amp;gt; Starts or continues execution. All auto started steps will be triggered.&amp;lt;br&amp;gt;Unless enabled in the execution settings, no debugger is opened when an error occurs or a breakpoint is hit. Instead, on error or fail, the execution is terminated and the failed/error status remembered in the log (shown in red).&amp;lt;br&amp;gt;Halts or breakpoints are ignored.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Run Debug.png]] &amp;quot;Debug Run&amp;quot; &amp;lt;br&amp;gt;Start or continue the test execution in debug mode causing the debugger to open on exceptions (regardless of what is specified in the execution settings) and also when a breakpoint is hit.&amp;lt;br&amp;gt;In addition, skipInTrace and doNotLog attributes are ignored. Thus, all activities will be logged.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Run Single Step.png]] &amp;quot;Step&amp;quot;&amp;lt;br&amp;gt;Start the test execution in single step mode or continue single stepping (when at a breakpoint).&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Run SingleStepInto.png]] &amp;quot;Step Into&amp;quot;&amp;lt;br&amp;gt;Like the above, but steps into other compound actions.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Pause.png]] &amp;quot;Pause&amp;quot; &amp;lt;br&amp;gt;Pause the current test run. To proceed or single step, click on the according button.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Stop.png]] &amp;quot;Stop&amp;quot; &amp;lt;br&amp;gt;Stop the execution of the current test run. Exception handling &amp;amp; cleanup (post actions) will be performed.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon InterruptRun.png]] &amp;quot;Interrupt&amp;quot; (new in 18.1 aka &amp;quot;2.12&amp;quot;) &amp;lt;br&amp;gt;Interrupt the execution of the current test run and open a debugger. Useful to debug endless loops or to inspect the execution state in a long running elementary action. In the debugger, the execution can be proceeded, single stepped or aborted.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon PauseOnError.png]] &amp;quot;Pause on Error&amp;quot; &amp;lt;br&amp;gt;This toggle controls how the executor behaves when an error is encountered. The default is to stop the test execution and to mark the test case as &amp;quot;FAILED&amp;quot; or &amp;quot;ERROR&amp;quot;. However, especially during the test development process itself, it is often useful to be able to proceed after an error. For example, when the test consists of a web-browser&#039;s input field values being checked and validated, you may want to continue after a validation error. With this toggle set, the executor goes into the pause-state whenever an error is encountered, and execution can be continued by pressing the &amp;quot;Run&amp;quot; or &amp;quot;Single Step&amp;quot; button again (i.e. it behaves as if &amp;quot;Pause&amp;quot; was pressed).&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Hard Stop.png]] &amp;quot;Hard Stop&amp;quot; &amp;lt;br&amp;gt;Hard-Terminate the execution of the current test run, without doing any exception/cleanup handling. This is useful e.g. for recursion hang-ups, or if a block&#039;s cleanup action leads to another blocking situation.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;!-- no longer; only in testplan runner &lt;br /&gt;
*[[Bild:Icon Logging Menu.png]] Open the logging dropdown menu&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
*[[Bild:Icon Print Report.png]] &amp;quot;Report&amp;quot;&amp;lt;br&amp;gt;Generate a report from the log data&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Follow Execution.gif]] &amp;quot;Follow execution&amp;quot;&amp;lt;br&amp;gt;To enabled/disable auto-select of the currently active block in the log (animation while running).&amp;lt;br&amp;gt;This button also provides a drop-down box (right click or press-and-hold), to select the number of levels and a tag filter, to further control which actions should be followed. The button&#039;s icon image shows a &amp;quot;minus&amp;quot; when automatic follow is disabled.&amp;lt;br&amp;gt;If the tag filter is set, it gives a list of match-patterns (GLOB patterns) separated by semicolon. Automatic follow will then only show action which are both within any level-limit and which have a tag which matches any in the given tag filter pattern&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon FindNextError.png]] &amp;quot;Find Error&amp;quot; &amp;lt;br&amp;gt;In the log, select the next activity which has finished with an error.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Next Inconclusive.png]] &amp;quot;Find Inconclusive&amp;quot;&amp;lt;br&amp;gt;In the log, select the next activity which has finished with an inconclusive state.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon FindNextActive2.png]] &amp;quot;Find Active&amp;quot;&amp;lt;br&amp;gt;In the log, select the next activity which is currently executing.&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon BackToPreviouslyVisited.png]] &amp;quot;Previously Visited&amp;quot;&amp;lt;br&amp;gt;In the log, select the previously visited activity (i.e. back in visited-history).&lt;br /&gt;
&lt;br /&gt;
The remaining edit- and breakpoint-related buttons are described in the [[CompoundBlock Editor-CompoundWorksheet Editor/en#Buttons|network editor]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- only present in the testplan-run-editor !&lt;br /&gt;
&lt;br /&gt;
= Logging Menu =&lt;br /&gt;
[[Bild:Logging Menu.png|thumb|153px|Logging]]&lt;br /&gt;
&lt;br /&gt;
;Save Log...&lt;br /&gt;
:This option allows saving the current logging information into an expecco log file or a XML formatted file. Selecting it brings up a file chooser to determine the target path of the log file.&lt;br /&gt;
&lt;br /&gt;
;Load Log...&lt;br /&gt;
:This option allows loading previously saved logging information from an expecco log file or a XML formatted file. Selecting it brings up a file chooser to determine the source path of the log file.&lt;br /&gt;
&lt;br /&gt;
;Remove all Results in System&lt;br /&gt;
:This option is used to clear all generated log data in the system. No reports can be generated from any more.&lt;br /&gt;
&lt;br /&gt;
;Remove Result&lt;br /&gt;
:This option is used to clear the last generated log data. No reports can be generated from any more.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Views =&lt;br /&gt;
After a run, the recorded &#039;&#039;Activity Log&#039;&#039; is presented as a hierarchical tree of executed actions. Select individual actions the tree to see the action&#039;s details (inputs, outputs and generated logging messages).&lt;br /&gt;
&lt;br /&gt;
== Activity Tree ==&lt;br /&gt;
The activity tree displays a hierarchical view of the activities that are invoked during the test run, each with a single entry in the tree. If an activity spawns sub activities, these sub activities are enlisted in the branch of the spawning activity, and you can expand or collapse the branch with the node browsing item. Only the first level is expanded automatically when the test run is started. Activities that perform elementary actions never have sub activities, while those that perform compound actions always have at least one sub activity (else they fail due to lack of executable steps inside). Activities on the same level are sorted chronologically by invocation time.&lt;br /&gt;
&lt;br /&gt;
The symbol in front of the activity indicates the state of the activity. This can be either in progress or one of the [[Glossary/en#Verdict | test results (verdicts)]]: &amp;quot;PASSED&amp;quot;, &amp;quot;FAIL&amp;quot;, &amp;quot;INCONCLUSIVE&amp;quot; or &amp;quot;ERROR&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Context Menu Activity Tree.png|thumb|231px|Context Menu]]&lt;br /&gt;
A context menu is available in the activity tree view, relating to the Activity that is currently selected:&lt;br /&gt;
&lt;br /&gt;
;Find Next Unhandled Error&lt;br /&gt;
:This option switches the selection in the tree from the currently selected activity to the next, failed activity for which no error handling was performed (and which was not ignored). The search is in the order of the tree hierarchy (i.e. deep-first search, starting at the current selection). &lt;br /&gt;
&lt;br /&gt;
;Find Next Error&lt;br /&gt;
:Similar to the above, but this menu function will find both handled and unhandled errors and failures.&lt;br /&gt;
&lt;br /&gt;
;Find Previous Unhandled Error&lt;br /&gt;
:Similar to the above, but searches backward for the previous unhandled failure or error.&lt;br /&gt;
&lt;br /&gt;
;Find Previous Error&lt;br /&gt;
:Similar to the above, but searches for any error (both handled and unhandled)&lt;br /&gt;
&lt;br /&gt;
;Generate Report from here...&lt;br /&gt;
:This option generates a report of the selected activity and all nested activities.&lt;br /&gt;
&lt;br /&gt;
;Open page on selected Item&lt;br /&gt;
:This opens a new page on the block corresponding to the selected activity.&lt;br /&gt;
&lt;br /&gt;
== Network View ==&lt;br /&gt;
This view is shown for compound activities. It displays the activity diagram and highlights steps as they are executed. A step&#039;s color reflects its execution state, as described below in &amp;quot;State Colors&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Note that in this view, editing is not possible. You can, however, press &amp;lt;kbd&amp;gt;Enter&amp;lt;/kbd&amp;gt; after selecting a step, causing a new browser page to open up, showing the selected step&#039;s diagram.&lt;br /&gt;
&lt;br /&gt;
== Log View ==&lt;br /&gt;
This view shows the log created by the activity. The log consists of the messages (and possibly attached data or screenshots) as generated by the activity (and subactivities) via the &amp;quot;logInfo&amp;quot; / &amp;quot;logWarning&amp;quot; / &amp;quot;logError&amp;quot; and &amp;quot;logFailure&amp;quot; calls (either from elementary code or via the corresponding action steps in a compound action).&lt;br /&gt;
&lt;br /&gt;
The toolbar buttons show or hide different message types. The checkbox named &amp;quot;&#039;&#039;Sublogs&#039;&#039;&amp;quot; shows or hides the logs of subactivities.&lt;br /&gt;
&lt;br /&gt;
== [[Timeline/en|Timeline View]] ==&lt;br /&gt;
This pane is new with version 23.2. It shows a graphical presentation of the execution times.&lt;br /&gt;
&lt;br /&gt;
== Pin Data View ==&lt;br /&gt;
This view is available for all types of activities. It shows two lists, the input pin value list to the left, and the output pin value list to the right. In each of the lists, three columns arrange the information. The first field of each row displays the pin name, the second one displays the value, and the third one displays the sender, or the receiver, respectively.&lt;br /&gt;
&lt;br /&gt;
Note that input information is not changing after an activity was spawned, while output values can still be produced or changed during the execution of the activity. In each list, only one row can be selected at a time. According to the selected row, the above icon buttons can be used:&lt;br /&gt;
&lt;br /&gt;
;[[Bild:Icon Sender.png]]&lt;br /&gt;
: Jump to the sender (the source) of the value. Only available for input pins when a sender object is available. This causes the selection in the activity tree to change to the activity that sent the selected value to this activity.&lt;br /&gt;
;[[Bild:Icon Receiver.png]]&lt;br /&gt;
: Jump to the receiver (the sink) of the value. Only available for output pins when a receiver object is available. This causes the selection in the activity tree to change to the activity that received the selected value from this activity.&lt;br /&gt;
;[[Bild:Icon Inspect Value.png]]&lt;br /&gt;
: Inspect the value object. As a shortcut, double click on the pin value&#039;s row.&lt;br /&gt;
&lt;br /&gt;
The popup menu (right click) depends on the selection. If no row is selected, functions operating on all values are provided. Otherwise, functions on the selected item are offered. The selection can be toggled by pressing CTRL with the mouse click.&lt;br /&gt;
&lt;br /&gt;
= State Colors =&lt;br /&gt;
When a compound action&#039;s diagram is executed, a read-only version of the diagram editor is showing the state of the execution.&lt;br /&gt;
There, steps are colored according to their [[Glossary/en#Verdict|execution state (verdict)]]. The color setting is part of the user settings and&lt;br /&gt;
can be changed according to your personal taste (or, if you suffer from red-green color blindness, for example).&lt;br /&gt;
&amp;lt;br&amp;gt;The defaults are:&lt;br /&gt;
* grey/original color&amp;lt;br&amp;gt;the step was not yet executed&lt;br /&gt;
&lt;br /&gt;
* blue&amp;lt;br&amp;gt;the step is about to be executed. This means that it has all of its input values (and possibly any required resources) available and it is ready to run. However, its code or network is not yet being executed - either because other steps are still running and the maximum execution parallelity has been reached, or because the diagram is being single stepped and waiting for you to press the &amp;quot;&#039;&#039;Step Next&#039;&#039;&amp;quot; button.&lt;br /&gt;
&lt;br /&gt;
* bright green (lime)&amp;lt;br&amp;gt;the step is being executed&lt;br /&gt;
&lt;br /&gt;
* normal green (darker green)&amp;lt;br&amp;gt;the step has finished execution with success&lt;br /&gt;
&lt;br /&gt;
* yellow&amp;lt;br&amp;gt;the step has finished execution with success, but a warning was generated during its execution or an exception was caught or ignored. Select the step and the &amp;quot;Log&amp;quot; tab for details.&lt;br /&gt;
&lt;br /&gt;
* normal red&amp;lt;br&amp;gt;the step finished execution with an unhanded error&lt;br /&gt;
&lt;br /&gt;
* dark red&amp;lt;br&amp;gt;the step finished execution with a failure&lt;br /&gt;
&lt;br /&gt;
* dark grey&amp;lt;br&amp;gt;the step was skipped or its execution was aborted. Either due to the user initiating an explicit abort (&amp;quot;&#039;&#039;Stop&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;Hard Stop&#039;&#039;&amp;quot; button), or because another step forced the containing diagram&#039;s execution to stop.&lt;br /&gt;
&lt;br /&gt;
= Tasks =&lt;br /&gt;
==Running a Trial Test of the Block==&lt;br /&gt;
To invoke the test wrapper, click on the start button in the editor&#039;s tool bar. The network is executed as usual, by starting with steps marked as autostart. If logging is enabled, the lower monitoring panel monitors the execution status. If logging is not enabled, the monitoring panel will be cleared and remains empty. Logging is initially enabled.&lt;br /&gt;
&lt;br /&gt;
The monitoring panel is split vertically, showing the activity tree on the left, and the observation panel to the right, which displays the current state of the selected activity. Select any activity to see the details in the right area. The depth of the activity tree can be limited by setting a log depth limit. See [[Settings/en#Logging Settings|settings]].&lt;br /&gt;
&lt;br /&gt;
If the &amp;quot;follow execution&amp;quot; toggle([[Bild:Icon Follow Execution.gif]]) has been checked, the selection in the tree automatically follows the currently executing activity.&lt;br /&gt;
&lt;br /&gt;
==Debugging==&lt;br /&gt;
The &amp;quot;normal&amp;quot; reaction to errors during a testplan-run is to finish the test plan with a FAIL or ERROR status. This behavior is OK for test execution; however, during test development, it is helpful to get a symbolic debugger which gives more detail about what happened, the current state (i.e. variables) and how the program got there (called &amp;quot;&#039;&#039;backtrace&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;walkback&#039;&#039;&amp;quot; or &amp;quot;&#039;&#039;call chain&#039;&#039;&amp;quot; in the literature).&lt;br /&gt;
&lt;br /&gt;
The debugger can be enabled via the global settings dialog. These settings are also used if you press the &amp;quot;&#039;&#039;Run&#039;&#039;&amp;quot;-button in this test-block runner. However, the additional &amp;quot;&#039;&#039;Run with Debug&#039;&#039;&amp;quot; button starts executing with the debugger enabled, ignoring the global settings.&lt;br /&gt;
&lt;br /&gt;
==Modifying the Program while Executing==&lt;br /&gt;
It is possible to change the running program. This may sound a weird thing to do at first, but is very useful when test cases are created in an explorative manner, or changes have to be made to a long running test, and you do not want (or cannot) restart the test from the beginning.&lt;br /&gt;
&lt;br /&gt;
You can change the program at any time (simply edit the action in another tab or window and accept). However, any action being already executed continues execution until finished in the old action definition. Only then (when invoked for the next time) will any changed definition become effective. &lt;br /&gt;
&lt;br /&gt;
This means:&lt;br /&gt;
* if an elementary block is currently being executed, the changed program text will be effective when the elementary block is called the next time&lt;br /&gt;
* if a compound action is changed, it will use the new activity diagram, when invoked the next time.&lt;br /&gt;
&lt;br /&gt;
To make code and diagram changes an atomic action, all changes are first done to a temporary edit-copy, which is finally installed as an atomic action when the &amp;quot;&#039;&#039;Accept&#039;&#039;&amp;quot; button is pressed. If multiple actions are to be edited, any ongoing execution should be paused first, and proceeded once all changes have been done.&lt;br /&gt;
&lt;br /&gt;
==Single Stepping and Breakpoints==&lt;br /&gt;
===Steps in an Activity Diagram===&lt;br /&gt;
Either place a breakpoint on a step and proceed by pressing the &amp;quot;&#039;&#039;Single Step&#039;&#039;&amp;quot; button, or start the execution right from the start via the &amp;quot;&#039;&#039;Single Step&#039;&#039;&amp;quot; button. There is also a &amp;quot;breakpoint&amp;quot;-action, which can be placed into the network. By conditionally enabling these steps, conditional breakpoints can be added.&amp;lt;br&amp;gt;When a breakpoint is reached, you can:&lt;br /&gt;
* continue single stepping (by pressing the &amp;quot;Step&amp;quot; button),&lt;br /&gt;
* cancel execution (press the &amp;quot;Stop&amp;quot; or &amp;quot;Hard Stop&amp;quot; button), or&lt;br /&gt;
* continue with normal execution (press the &amp;quot;Run&amp;quot; button).&lt;br /&gt;
&lt;br /&gt;
Notice that there are now two different single step buttons; one is showing steps as executed in the currently visible network, the other (&amp;quot;&#039;&#039;Step In&#039;&#039;&amp;quot;) also halts before any step in any subnetwork is about to be executed.&lt;br /&gt;
&lt;br /&gt;
===Code Lines in an Elementary Action===&lt;br /&gt;
In a JavaScript action, place a line such as:&lt;br /&gt;
 this.halt();&lt;br /&gt;
or&lt;br /&gt;
 halt();&lt;br /&gt;
(in Smalltalk code, write &amp;quot;&amp;lt;CODE&amp;gt;self halt&amp;lt;/CODE&amp;gt;&amp;quot;)&lt;br /&gt;
somewhere in your elementary block&#039;s code. When executed, a debugger will be opened, highlighting the line containing the code-breakpoint.&lt;br /&gt;
&lt;br /&gt;
As an alternative, place a line breakpoint by double-clicking beside the code line in the left side-bar area (a red breakpoint sign will be shown then). Notice that line breakpoints can only be placed at expressions starting in that very line, whereas the above described &amp;lt;CODE&amp;gt;halt&amp;lt;/CODE&amp;gt; can be placed anywhere, where an expression is allowed.&lt;br /&gt;
&lt;br /&gt;
In the debugger, press one of&lt;br /&gt;
* &amp;quot;&#039;&#039;Next Line&#039;&#039;&amp;quot; to single step to the next code line &lt;br /&gt;
* &amp;quot;&#039;&#039;Step&#039;&#039;&amp;quot; to single step over the next expression&lt;br /&gt;
* &amp;quot;&#039;&#039;Send&#039;&#039;&amp;quot; to step into the next expression&lt;br /&gt;
* &amp;quot;&#039;&#039;Continue&#039;&#039;&amp;quot; to proceed.&lt;br /&gt;
* &amp;quot;&#039;&#039;Abort&#039;&#039;&amp;quot; to stop the execution&lt;br /&gt;
&lt;br /&gt;
The debugger also shows the calling chain (how did I get there) in the top pane, and the activity&#039;s local variables and temporary variables in the lower pane.&lt;br /&gt;
&lt;br /&gt;
The debugger is described in detail in http://live.exept.de/doc/online/english/tools/debugger/TOP.html.&lt;br /&gt;
&lt;br /&gt;
==Premature Stop of a Test==&lt;br /&gt;
Occasionally, it might be required to stop a test even though it has not completed. For example, if you detect an error or malfunction which is not detected by the test, or the test is caught in an endless loop due to an unexpected situation.&lt;br /&gt;
In this case, press the &amp;quot;&#039;&#039;Stop&#039;&#039;&amp;quot; button. &lt;br /&gt;
&lt;br /&gt;
The &amp;quot;&#039;&#039;Stop&#039;&#039;&amp;quot; button asks the test-executor for a controlled termination of the run. &amp;quot;&#039;&#039;Controlled&#039;&#039;&amp;quot; means, that any cleanup actions (post-execution actions) are to be executed.&lt;br /&gt;
&lt;br /&gt;
This is the preferred way to stop test execution, because those cleanup actions are meant to free any acquired resources, remove temporary files or to turn off hardware equipment which was acquired and configured by the test. I.e. to bring the state of your equipment back to a well known (initial) state.&lt;br /&gt;
&lt;br /&gt;
However, sometimes, a cleanup action might itself encounter trouble. For example, if your test requires a login procedure to a remote machine, and the cleanup tries to perform a logout, this may block if the connection was lost during the test. In this case, the cleanup action will not be able to perform its logout and may even block forever.&lt;br /&gt;
&lt;br /&gt;
To handle this situation gracefully, expecco will wait for some pre-configured time for all the cleanup actions to complete (this is a configurable settings value found in the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Execution Settings&#039;&#039;&amp;quot;-dialog). After that, a dialog window will appear, asking if the cleanup should be aborted or if you want to continue waiting for the cleanup.&lt;br /&gt;
&lt;br /&gt;
If you are certain that no cleanup action is required, or if you know in advance, that it will fail or block, use the &amp;quot;&#039;&#039;Hard Stop&#039;&#039;&amp;quot; button, which terminates the execution without even attempting to perform any cleanup actions.&lt;br /&gt;
Use this with care, as it may leave allocated resources and devices in a non-determined state. It may also lead to file streams or sockets being left open. You can repair this (i.e. manually close any streams) via the &amp;quot;&#039;&#039;Extra&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; menu, where you fild menu items to find and/or close those streams.&lt;br /&gt;
&amp;lt;BR&amp;gt;Notice that unreferenced resources are usually automatically freed after some time via the automatic memory manager&#039;s finalization mechanism. However, this would not work if eg. an open file stream is still referenced by being held in an activity log or an expecco environment variable.&lt;br /&gt;
&lt;br /&gt;
= Typical Error Messages when Execution Fails =&lt;br /&gt;
&lt;br /&gt;
=== Empty action &amp;quot;...&amp;quot; (no steps) ===&lt;br /&gt;
&lt;br /&gt;
Obviously, there is no action step at all in your diagram. This makes no sense in a production test suite, and is therefore reported as an error.&lt;br /&gt;
However, when developing tests, it may be useful to create dummy actions as placeholders for &amp;quot;to-be-implemented&amp;quot; actions. Then, got to &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Execution&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; and check the &amp;quot;&#039;&#039;Allow empty Actions&#039;&#039;&amp;quot; toggle.&lt;br /&gt;
&lt;br /&gt;
Solutions:&lt;br /&gt;
* add some dummy action to you network. A step which writes a log message such as &amp;quot;to be implemented&amp;quot; is a good idea. This can be written to either the activity log (and will therefore appear in any printed test report) or to the Transcript (console).&lt;br /&gt;
&lt;br /&gt;
* check &amp;quot;&#039;&#039;Allow empty Actions&#039;&#039;&amp;quot; in the settings.&lt;br /&gt;
&lt;br /&gt;
=== No executable step in action &amp;quot;Test/Demo&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
No inner action step could be executed inside the diagram.&lt;br /&gt;
&amp;lt;br&amp;gt;This happens if:&lt;br /&gt;
* an explicit &amp;quot;Start&amp;quot; step is missing,&lt;br /&gt;
* and/or no step has the &amp;quot;autostart&amp;quot; attribute set (which is equivalent to a start step)&lt;br /&gt;
* and no inner step got a value at one of its required triggering pins (from the compound action).&lt;br /&gt;
Solution:&lt;br /&gt;
:typically, you forgot to provide an input value to the tested compound action in the &amp;quot;Test/Demo&amp;quot; diagram.&lt;br /&gt;
&lt;br /&gt;
=== No value for input pin &amp;quot;...&amp;quot; of step &amp;quot;...&amp;quot; ===&lt;br /&gt;
An inner step was started, but got no input value at one of its required pins.&lt;br /&gt;
The inner step was started (probably due to autostart or an explicit trigger, bt not due to an input value arriving).&lt;br /&gt;
&lt;br /&gt;
Solution:&lt;br /&gt;
:make sure the inner pin is connected, and also that it will receive a value at the input pin(s). If it has an autostart or explicit trigger, check if that is really what you intended. In most cases, steps should be triggered by incoming data, and not only by control flow triggers (but to have both is perfectly ok).&lt;br /&gt;
:&lt;br /&gt;
:Be especially careful when steps are in a loop: often an input value is &amp;quot;consumed&amp;quot;in the first iteration, and then no value is present in further loop cycles. Then, make the input a &amp;quot;non-consuming&amp;quot; (parameter) pin, to preserve the value across loop cycles.&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
API for the builtin and bridged languages: &amp;quot;[[Expecco API]]&amp;quot;,&lt;br /&gt;
&amp;quot;[[Expecco_API/en#Pin Functions | Pin-API ]]&amp;quot; and &amp;quot;[[ Expecco_API/en#Current Activity | Activity-API ]]&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#JavaScript_and_Smalltalk_Elementary_Blocks|API for Smalltalk/JavaScript actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#Groovy_Elementary_Blocks|API for Java/Groovy actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#Bridged_Python_Elementary_Blocks|API for Python actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#Node.js_.28Bridged.29_Elementary_Blocks|API for NodeJS actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#Bridged_Ruby_Elementary_Blocks|API for Ruby actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[Expecco_API/en#Bridged C Elementary Blocks|API for C actions]]&lt;br /&gt;
&amp;lt;br&amp;gt;Scripted actions: &amp;quot;[[ElementaryBlock_Element/en#Script_Action_Blocks | Script Action Blocks]]&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;[[ElementaryBlock_Element/en#Bridge_Action_Blocks_vs._Script_Action_Blocks | Bridged Actions vs. Script Actions]]&amp;quot;&lt;br /&gt;
&amp;lt;br&amp;gt;[[Code_Editor/en|Code Editor]]&lt;br /&gt;
&amp;lt;br&amp;gt;[[GUI Browser/en|GUI-Browser]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Editors]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29338</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29338"/>
		<updated>2024-05-07T14:50:59Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 24.1 (2Q 2024) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt;&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Show Log and [[Timeline/en|Timeline view]] for testplans&lt;br /&gt;
*Feature: Search and Goto Line menu functions in the activity log view&lt;br /&gt;
*Feature: [[Embedded Systems C Bridge API|C-Bridge]] now supports SSL connections (encryption and authentication using certificates)&lt;br /&gt;
*Feature: Settings for execution (thread pool and log activities/pins/info) can now be saved in the test suite settings&lt;br /&gt;
*Feature: CSV test report, values for start time, end time and duration added&lt;br /&gt;
*Feature: Improved Refactoring &amp;quot;Extract (&amp;amp; Replace) New Compound Action&amp;quot;&lt;br /&gt;
*Feature: More information in CSV test reports&lt;br /&gt;
*Fix: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Fix: WindowsAutomation: Fix blocking of applications after &amp;lt;Mouse Button Down&amp;gt;&lt;br /&gt;
*Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Fix: Bridges: Detect (and ignore) invalid requests from forked background bridge threads&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29310</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29310"/>
		<updated>2024-05-06T13:32:19Z</updated>

		<summary type="html">&lt;p&gt;Matilk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Bug Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt;&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Feature: Log and timeline view also for the root testplan&lt;br /&gt;
*Enhancement: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Bug Fix: WindowsAutomation: Fix blocking after &amp;lt;Mouse Button Down&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29269</id>
		<title>Release Notes 24.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_24.x&amp;diff=29269"/>
		<updated>2024-04-22T09:31:37Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 24.1 (2Q 2024) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 23.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 24.1 (2Q 2024) ==&lt;br /&gt;
*Feature: [[Expecco_API/en#Global_and_Static_Variables|Static Variables for Python]]&lt;br /&gt;
*Bug Fix: asynchronous write to an output pin with no wait() in bridged actions are now detected and reported as error (see Example3 in the [[Expecco_API/en#Asynchronous_and_Callback_Functions|NodeJS API Documentation]])&lt;br /&gt;
*Feature: Qt-Testing: Logging with log levels &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;WARN&amp;lt;/code&amp;gt;&lt;br /&gt;
*Feature: WindowsAutomation: Native Touch, Tap, Drag &amp;amp; Drop support now in the base WindowsAutomation Library&lt;br /&gt;
*Enhancement: Current temporary testplan settings (like selected testcases, do-not-execute of pre/post action, etc.) don&#039;t get lost anymore when reimporting a library&lt;br /&gt;
*Bug Fix: WindowsAutomation: Fix blocking after &amp;lt;Mouse Button Down&amp;gt;&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Testplan_Editor/en&amp;diff=29268</id>
		<title>Testplan Editor/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Testplan_Editor/en&amp;diff=29268"/>
		<updated>2024-04-17T12:07:07Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Log Processor Action */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:Testplan Editor 1.png|thumb|300px|Testplan Editor showing the plan&#039;s attributes]]&lt;br /&gt;
[[Bild:Testplan Editor 2.png|thumb|300px|Testplan Editor showing a test-case item&#039;s attributes]]&lt;br /&gt;
&lt;br /&gt;
The test plan editor is used to create, modify and execute test plans. It is shown in the &amp;quot;&#039;&#039;Testplan&#039;&#039;&amp;quot; tab when a [[Testplan Element/en|testplan element]] is selected in the navigation tree.&lt;br /&gt;
&lt;br /&gt;
Testplans are constructed as a sequence of test cases. Notice that in literature and other test frameworks, these are often called &amp;quot;&#039;&#039;test steps&#039;&#039;&amp;quot;. Expecco uses the term &amp;quot;&#039;&#039;test case&#039;&#039;&amp;quot; for items in a test plan and &amp;quot;&#039;&#039;test step&#039;&#039;&amp;quot; for individual action steps within a test case. The reason is that in expecco, a &amp;quot;&#039;&#039;test step&#039;&#039;&amp;quot; (which defines what is done) can be put into multiple test plans as test case (which defines when and under which conditions it is execute). &lt;br /&gt;
&lt;br /&gt;
To add test cases to a test plan, drag actions (from the left tree) into the test case list. &lt;br /&gt;
If you want to define your test plan in a top-down fashion (i.e. create the list of test cases first, before any actions are defined), you can also create the test plan&#039;s list items with the &amp;quot;&#039;&#039;Add Test Case&#039;&#039;&amp;quot; button or menu function, and later specify the concrete action by dragging actions into the &amp;quot;&#039;&#039;Action&#039;&#039;&amp;quot; field at the bottom or by selecting the test action vie the &amp;quot;...&amp;quot; button at the right. Finally, you can copy (CTRL-C) tree items and paste them elow the selected testcase with CTRL-V.&lt;br /&gt;
&lt;br /&gt;
Later, when the test plan is executed, these test cases will be executed in sequence one after the other.&lt;br /&gt;
&lt;br /&gt;
The test plan editor consists of two major areas: the top list presents the list of test cases, the bottom presents attributes of the selected item in the list.&lt;br /&gt;
Attributes specify the behavior of the test plan and of individual test cases.&lt;br /&gt;
&lt;br /&gt;
To execute the test plan, click on the green &amp;quot;&#039;&#039;run&#039;&#039;&amp;quot; button in the toolbar.&lt;br /&gt;
&lt;br /&gt;
When a test plan has been executed, the state of its last execution outcome is shown in the top list. Not executed or inconclusive items are shown with a grey color, successful items in green, and failed items in red.&lt;br /&gt;
&lt;br /&gt;
To the right you can see two examples for an opened testplan editor. In the first, the test plan itself is selected; in the second, a test case is selected and shown. Both show a situation after a test run which was only partially successful.&lt;br /&gt;
&lt;br /&gt;
= Testplan Hierarchies and Slices =&lt;br /&gt;
&lt;br /&gt;
Items in a test plan (called &amp;quot;&#039;&#039;Test Cases&#039;&#039;&amp;quot; in the previous paragraph) are typically implemented as &lt;br /&gt;
actions from the tree. I.e. usually, you will define a test action and bring it into a test plan&#039;s list. &lt;br /&gt;
&lt;br /&gt;
Any action can be used as test case and thus placed into a test plan&#039;s list. However, it is recommended that test actions be  tagged as &amp;quot;TEST-CASE&amp;quot; (tree menu &amp;amp;#8594; &amp;quot;&#039;&#039;More&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Mark as TEST_CASE&#039;&#039;&amp;quot;), so they will be presented with a different icon in the tree (that us just to make things easier to find; it has no semantic meaning).&lt;br /&gt;
&lt;br /&gt;
In addition to actions, it is also possible to place other test plans as items into a test plan.&lt;br /&gt;
This allows for tests to be grouped (for example: by component or variant of the [[Glossary/en#SUT_.28System_Under_Test.29 | SUT]]) and placed as group into another test plan. Thus, the group can be executed individually (for component tests) or under another test plan (for final acceptance tests).&lt;br /&gt;
&lt;br /&gt;
Because of this, it may be better to call these &amp;quot;&#039;&#039;Testplan Items&#039;&#039;&amp;quot; instead of &amp;quot;&#039;&#039;Test Cases&#039;&#039;&amp;quot; (but your milage may vary and users tend to use different naming for these entities).&lt;br /&gt;
&lt;br /&gt;
= Buttons =&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Run.png]] Start the test execution (stop execution on error).&lt;br /&gt;
*[[Bild:Icon Run Debug.png]] Start the test execution with debug (open a debugger on error).&lt;br /&gt;
*[[Bild:Icon Run Failed.png]] Runs all previously failed and inconclusive test cases again (i.e. all cases which ended with success will be skipped)&lt;br /&gt;
*[[Bild:Icon Run Inconclusive.png]] Runs all previously inconclusive test cases.&lt;br /&gt;
:This includes both cases which have not yet been executed and cases which have ended in the inconclusive state.&lt;br /&gt;
*[[Bild:Icon Run Single Step.png]] Start execution in single step mode or continue single stepping.&lt;br /&gt;
*[[Bild:Icon Run Single Step2.png]] Start execution in single step mode or continue single stepping. Steps into called actions.&lt;br /&gt;
*[[Bild:Icon Pause.png]] Pause the current test run. To proceed, click on the run button. To proceed single stepping, click on one of the single-step buttons.&lt;br /&gt;
*[[Bild:Icon StopAndSkip.png]] Stop the execution of the current test-case, marking it as aborted (inconclusive). Proceed by starting the next test-case.&lt;br /&gt;
*[[Bild:Icon Stop.png]] Stop the execution of the current test run. Exception handling and cleanup actions will be performed.&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Hard Stop.png]] Hard-Terminate the testrun, without exception handling or cleanup actions.&lt;br /&gt;
: This is useful e.g. for hang-ups or communication failures (i.e. if a cleanup action itself hangs). Be aware, that this may lead to leftover open web-browser windows (in case of web-testing) or leftover open communication channels (sockets, serial line connections). These may have to be closed manually via the &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Close Connections&#039;&#039;&amp;quot; menu, if required.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Logging Menu.png]] Logging drop down menu to load/save a result log&lt;br /&gt;
*[[Bild:Icon Print Report.png]] Generate a [[Report Generation/en|report]] from the log data&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Add Testcase.png]] Adds an empty test-case to testplan. The item&#039;s action can then be specified in the lower details area. However, a more convenient way to add test-cases is to simply drag&amp;amp;drop an action into the list.&lt;br /&gt;
*[[Bild:Icon Remove Testcase.png]] Remove the selected test-case(s) from test plan&lt;br /&gt;
*[[Bild:Icon Up.png]]/[[Bild:Icon Down.png]] Change the execution order of the test-cases, by moving the selected test-case(s) up or down in the list&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*[[Bild:Icon Follow Execution.png]] Follow execution: autoselect the currently active block in the log (while running).&amp;lt;br&amp;gt;In recent expecco versions, this button got replaced by a drop-down box, to selecte the number of levels, which should be followed. The button&#039;s icon image is slightly different.&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
*[[Bild:Icon Previous Error.png]] Find the previous failed or erroneous test case&lt;br /&gt;
*[[Bild:Icon Next Error.png]] Find the next failed or erroneous test case&lt;br /&gt;
*[[Bild:Icon Next Inconclusive.png]] Find the next inconclusive test case&lt;br /&gt;
*[[Bild:Icon Next Active.png]] Find the next active (currently running) test case&lt;br /&gt;
&lt;br /&gt;
= Tasks =&lt;br /&gt;
== Adding and Arranging Test Cases ==&lt;br /&gt;
There are multiple ways to create new test case entries in the test plan:&lt;br /&gt;
# Create empty items with the toolbar button shown above, then specify the action block in the lower editor&#039;s &amp;quot;&#039;&#039;Action&#039;&#039;&amp;quot; field.&lt;br /&gt;
# Directly drag &amp;amp; drop an action block or another test plan from the navigation tree into the testplan area. For this, it is useful to open a secondary popup or split tree.&lt;br /&gt;
# Copy-Paste items from the left tree; using either menu- or keyboard shortcut functions.&lt;br /&gt;
# Use a programatic testplan generator from the reflection library&lt;br /&gt;
&lt;br /&gt;
Please note that not any block can serve as test case item in this list.&lt;br /&gt;
Allowed are:&lt;br /&gt;
* actions without input pins (or where all pins have default values)&lt;br /&gt;
* actions where input pins have only simple types (strings, numbers, filenames). See [[#Action Parameters | &amp;quot;&#039;&#039;Action Parameters&#039;&#039;&amp;quot; below]].&lt;br /&gt;
* other test plans (this creates a hierarchical test plan, with sub-test sequences).&lt;br /&gt;
&lt;br /&gt;
When creating an entry with the toolbar button or by pasting, new entries will be inserted below the currently selected entry. If nothing is selected or when an item is dropped onto the test plan itself, the new entry is added at the very bottom of the list.&lt;br /&gt;
&lt;br /&gt;
The items&#039; order (which is also the execution order) can be changed via the &amp;quot;&#039;&#039;Move Item Up&#039;&#039;&amp;quot; / &amp;quot;&#039;&#039;Move Item Down&#039;&#039;&amp;quot; items found on the the popup menu of a selected item. There are also [[Common_Keyboard_Shortcuts/en#Tree.2FList_Organisation|keyboard shortcuts]] (&amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2191;&amp;lt;/kbd&amp;gt; / &amp;lt;kbd&amp;gt;Ctrl-&amp;amp;#x2193;&amp;lt;/kbd&amp;gt;) and toolbar buttons to move selected item(s).&lt;br /&gt;
&lt;br /&gt;
== Executing a Test ==&lt;br /&gt;
&lt;br /&gt;
Start the execution by clicking on the &amp;quot;&#039;&#039;Start&#039;&#039;&amp;quot; (or &amp;quot;&#039;&#039;Run&#039;&#039;&amp;quot;) button ([[Bild:Icon Run.png]]). By default, execution starts with the first item and proceeds downward in the list.&lt;br /&gt;
You&#039;ll find multiple such run buttons: regular run, to run with debugger opening on error, to rerun failed cases only (as described above) or to rerun only inconclusive test cases. There are also two single step options in the toolbar.&lt;br /&gt;
&lt;br /&gt;
Test cases can be individually skipped or activated by toggling the &amp;quot;&#039;&#039;Enable&#039;&#039;&amp;quot; checkbox in the list. There are also popup-menu entries to enable/disable multiple items in one operation (i.e. select multiple items, then use the menu function &amp;quot;&#039;&#039;Skip Selected Items&#039;&#039;&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
The list keeps the information of the previous run, even if you switch to another editor and come back later. However, only the last execution&#039;s result of a test plan is remembered (unless you save the result in a file). Before any run, all test-cases&#039; states are reset to the &amp;quot;Untested&amp;quot; state (which counts as &amp;quot;INCONLUSIVE&amp;quot;), no matter if they are activated for execution or not.&lt;br /&gt;
&lt;br /&gt;
All checked test-cases are executed sequentially. While running, the currently executing test-case is marked with a little clock symbol. The symbols of all other test cases indicate their result state, which is one of the [[Glossary/en#Verdict|verdicts]] or the already mentioned &amp;quot;Untested&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
After the test run, the list-elements can be expanded (the little [+]/[-] icons) to browse the test-cases&#039; activity logs. You can also follow the execution while running, to keep track on the current execution state. Either click on those activity items, or check the &amp;quot;&#039;&#039;Follow Activity&#039;&#039;&amp;quot; toggle, to have expecco automatically follow the currently active action.&lt;br /&gt;
&lt;br /&gt;
Create a report from this test-run by clicking on the &amp;quot;&#039;&#039;Report&#039;&#039;&amp;quot; button. Initially, a standard report template (with probably way too much detail) is printed. This can be customized in various ways to suit your needs. For more information see: [[Report Generation/en|Report Generation]].&lt;br /&gt;
&lt;br /&gt;
== Stopping / Pausing / Resuming ==&lt;br /&gt;
&lt;br /&gt;
* The &amp;quot;&#039;&#039;Pause&#039;&#039;&amp;quot; button ([[Bild:Icon Pause.png]]) will pause the execution.&amp;lt;br&amp;gt;Useful to look into the trace or message log. You may later continue with or without the debug option (without the debug option, errors will lead to non-success of the corresponding test case, without user intervention. With debug, a debugger will pop up allowing for inspection of data and the state of any pending elementary action).&lt;br /&gt;
&lt;br /&gt;
* The &amp;quot;&#039;&#039;Stop&#039;&#039;&amp;quot; button ([[Bild:Icon Stop.png]]) will end the execution.&amp;lt;br&amp;gt;All currently active actions will be marked as &amp;quot;aborted&amp;quot;, which is treated like &amp;quot;inconclusive&amp;quot; when interpreted as [[Glossary/en#Verdict | test verdict]].&lt;br /&gt;
&lt;br /&gt;
* If you press either the &amp;quot;&#039;&#039;Run&#039;&#039;&amp;quot; ([[Bild:Icon Run.png]]) or the &amp;quot;&#039;&#039;Run-with-debug&#039;&#039;&amp;quot; ([[Bild:Icon Run_Debug.png]])button,&amp;lt;br&amp;gt;execution will start from the very first test case (unless you change the check-toggles which control the individual test case executions). If the suite was paused, it will be resumed.&lt;br /&gt;
&lt;br /&gt;
* If you press the &amp;quot;&#039;&#039;Run Failed&#039;&#039;&amp;quot; button ([[Bild:Icon Run_Failed.png]]),&amp;lt;br&amp;gt;test cases which already finished with success will NOT be reexecuted. Thus their outcome and trace data is preserved. This is useful after a fix of the system under test and a rerun of affected cases.&lt;br /&gt;
&lt;br /&gt;
* If you press the &amp;quot;&#039;&#039;Run Inconclusive&#039;&#039;&amp;quot; button ([[Bild:Icon Run_Inconclusive.png]]),&amp;lt;br&amp;gt;only tests which where aborted previously or which have not yet been executed will be executed. Both successful and failed tests will NOT be reexecuted. This is useful to resume a test after a longer session interruption. Notice, that this &amp;quot;Run not Executed&amp;quot; function even works if you saved the previous test result and restarted expecco in the mean time. This works even if you proceed testing on another machine (testers will appreciate this, when their laptop battery is about to die...).&lt;br /&gt;
&lt;br /&gt;
== Selective Execution ==&lt;br /&gt;
You can execute individual test-cases or a subset of all the test plan.&lt;br /&gt;
&lt;br /&gt;
Of course, selective execution requires that test cases are independent from previous cases. That means that either each case leaves the SUT in a defined initial state, or every case makes sure to bring it into a defined state before doing its thing.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Individual Selection:&#039;&#039;&#039;&amp;lt;br&amp;gt;Individual testcases are excluded/included by toggling their execution toggle in the list. Notice that this is a session setting. When the suite is reloaded in a new session, all execution toggles will be reset to their default state (which can be specified for each individual item in the lower attribute area).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Rerun of Failed Tests:&#039;&#039;&#039;&amp;lt;br&amp;gt;The &amp;quot;&#039;&#039;Execute Failed&#039;&#039;&amp;quot; button executes those tests which failed in the previous run. This is useful if the whole suite would take a long time and individual tests are to be executed again after a fix of the system under test. Or after a change of a test-case&#039;s definition. Although this might save time, it is good practice (i.e. highly obligatory) to rerun the test plan completely eventually.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Selection by Risk:&#039;&#039;&#039;&amp;lt;br&amp;gt;You can define individual risk levels to each test-case of the plan. Now toggle the &amp;quot;&#039;&#039;Risk&#039;&#039;&amp;quot; check-box at the top of the test plan and set a risk limit. Then, when executing, only those test-cases will be executed which have a greater or equal risk level. &lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Selection by Group:&#039;&#039;&#039;&amp;lt;br&amp;gt;By attaching individual group-tags to each test-case, you can also group related test cases into test groups. Then, toggle the &amp;quot;&#039;&#039;Testgroup&#039;&#039;&amp;quot; check-box at the top of the test plan and enter some identifier(s) to specify, which group(s) to execute. The next test-run will only execute test-cases with a matching group tag.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Dynamic Selection by Pre-Execution Checks&#039;&#039;&#039;&amp;lt;br&amp;gt;If present, the pre-execution action is run before the actual test case. If it generates a non-successful result, the corresponding test case is skipped (a corresponding post-execution action is also skipped, if present).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Dynamic Selection by Condition Variables&#039;&#039;&#039;&amp;lt;br&amp;gt;You can attach a &#039;&#039;condition variable&#039;&#039; or a set of condition variables to a testcase. If a name or list of names is specified in the &amp;quot;&#039;&#039;Check Condition Variable&#039;&#039;&amp;quot; field, all of them must contain a boolean &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt; value, otherwise, the test case is skipped with an inconclusive outcome. The variables must be defined in the testplan&#039;s environment (or the project&#039;s top environment) as boolean variables.&amp;lt;p&amp;gt;In addition, it is possible to update a condition variable (or a set of condition variables) depending on the outcome of a test case. All variables listed in the &amp;quot;&#039;&#039;set condition variable&#039;&#039;&amp;quot; field will be set to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, if the test case passed, &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; otherwise.&amp;lt;br&amp;gt;These two allow for a simple conditional execution of individual test cases. Of course, these variables are also visible in the network as regular environment variables. Therefore, more complex checks can be performed using arbitrarily complex logic there.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Sub-Testplans&#039;&#039;&#039;&amp;lt;br&amp;gt;Finally, by dropping another test-plan into the test-case area, all of its test-cases are embedded and are treated as a single test-case in the outer test-plan. Thus, hierarchies of testplans can be created, which can of course still be executed individually.&lt;br /&gt;
&lt;br /&gt;
== Repeated Execution (Loop Modes) ==&lt;br /&gt;
&lt;br /&gt;
It is often useful to run the same test scenario multiple times. For example if an error only occurs sporadically, you may want to repeat the test run until an error occurs. Or if your goal is to detect memory leaks or performance degration of the system under test, you may want to run it multiple times to put stress on it.&lt;br /&gt;
For this, various loop modes can be configured (see &amp;quot;&#039;&#039;Execution Modes&#039;&#039;&amp;quot; below):&lt;br /&gt;
* repeat the test for a particular number of runs&lt;br /&gt;
* repeat the test for a given time duration&lt;br /&gt;
* repeat the test until an error occurs&lt;br /&gt;
* repeat the test until no error occurs&lt;br /&gt;
&lt;br /&gt;
Of course, all of the above can be easily implemented by creating a compound block and placing the test scenario&#039;s action block into it with either an iteration count or by adding appropriate looping blocks around. This is also the preferred mechanism, if different input values or configuration data has to be used for each run.&lt;br /&gt;
However, in most cases, only a simple repetition of the same test is desired, and this can be done without programming, by setting up a loop mode in the execution configuration.&lt;br /&gt;
&lt;br /&gt;
=== Individual versus Full Report ===&lt;br /&gt;
&lt;br /&gt;
When executing a test in loop mode, a big amount of trace and report data may accumulate, which may be cumbersome to examine and may also reach the available memory limits (in this case, expecco prunes the execution log, by removing older trace information).&lt;br /&gt;
&lt;br /&gt;
For this, it is possible to specify that individual reports are generated and written to a file after each run - either unconditionally or only when an individual run is successful or failed. You can specify a filename pattern for this, so that each file gets a distinguished name (with optional run-number and/or time stamp in the file name). The files will be created relative to the project&#039;s attachment folder, unless an absolute pathname is specified.&lt;br /&gt;
&lt;br /&gt;
=== Alternative Postprocessing Options ===&lt;br /&gt;
&lt;br /&gt;
To postprocess the accumulated trace/log information, define a log-processor action and add it to individual testcases as &amp;quot;&#039;&#039;Log Processor Action&#039;&#039;&amp;quot;. The log processor action gets the collected activity-log as input. This allows for arbitrary filtering and/or processing of the log information, but requires some knowledge about the structure of the log items and the operation of the log-processing action blocks in the [[ Standard Library ]] and/or the [[ Expecco Reflection Library | Reflection Library ]].&lt;br /&gt;
&amp;lt;br&amp;gt;(You can of course create an dummy log processor first, place a breakpoint on it and inspect the received object to see its structure).&lt;br /&gt;
&lt;br /&gt;
== Data Driver / Generator (Feeding Loop) ==&lt;br /&gt;
&lt;br /&gt;
You can execute the same suite with multiple data value tuples,&lt;br /&gt;
by defining a data generator action (drag&amp;amp;drop it into the &amp;quot;&#039;&#039;Data Generator&#039;&#039;&amp;quot; input field). &lt;br /&gt;
This action will be executed and each output value tuple will be&lt;br /&gt;
used to set variables in the testplan&#039;s environment, and execute the testplan&lt;br /&gt;
once for for each generated tuple.&lt;br /&gt;
The variables are named according to the generator action&#039;s output pin names.&lt;br /&gt;
(i.e. if you define environment variables &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot;, the generator should (must) have two output pins named &amp;quot;a&amp;quot; and &amp;quot;b&amp;quot;, and generate the driving values there.)&lt;br /&gt;
&lt;br /&gt;
== Configuring the Testplan ==&lt;br /&gt;
=== Adding Pre and Post Execution Actions===&lt;br /&gt;
Testplans can have pre- and post-execution blocks. The pre-execution block is executed before the plan is executed; the post-execution block is executed after it has finished.&lt;br /&gt;
If the pre-execution block does not finish with success, the testplan is not executed. This can be useful e.g. to allocate and/or release resources. To add a pre- or post-execution action, drag &amp;amp; drop an action block from the navigation tree into the corresponding field. Please note that these blocks cannot receive values via an input pin. See also below for pre- and post actions of individual test cases.&lt;br /&gt;
&lt;br /&gt;
=== Adding a Background Execution Action ===&lt;br /&gt;
Testplans can have a background-execution block. The background-execution block is executed in parallel to the execution of the testplan and will be terminated after the execution of the testplan has finished. Typically, this will be a block which opens a socket, pipe or other communication channel or to start an external (shell-) process to feed or monitor the system under test. See also below for individual testcase background actions.&lt;br /&gt;
&lt;br /&gt;
=== Adding an Inventory ===&lt;br /&gt;
If a test case requires a resource (device, lock or operator), an inventory can be specified, which defines the set of available resources and from which the resource will be allocated. Without an inventory, the test will not be able to perform.&lt;br /&gt;
&amp;lt;br&amp;gt;An inventory can be defined locally in a test plan, or globally in the top-level testSuite&#039;s &#039;&#039;misc&#039;&#039; tab (the later is used, if the test plan does not specify its own inventory preferences).&lt;br /&gt;
&lt;br /&gt;
If tests are executed from AIDYMO via remote-execution, the inventory is provided by AIDYMO instead.&lt;br /&gt;
This ensures that measurement devices are correctly acquired and locked&lt;br /&gt;
for the duration of a test&#039;s execution - even among multiple tests running at the same time on different test machines.&lt;br /&gt;
To add an inventory, drag &amp;amp; drop an existing inventory definition element from the navigation tree.&lt;br /&gt;
&lt;br /&gt;
=== Execution Settings ===&lt;br /&gt;
*&#039;&#039;&#039;Run Time Limit&#039;&#039;&#039;&amp;lt;br&amp;gt;This field is used to set a time limit for the execution of the test plan. The execution will stop after the specified duration. The entered number can be followed by a time unit, e.g. &amp;quot;ms&amp;quot; / &amp;quot;s&amp;quot; / &amp;quot;m&amp;quot; / &amp;quot;h&amp;quot; / &amp;quot;d&amp;quot;. Without unit, &amp;quot;seconds&amp;quot; are assumed. To remove a previously set time limit simply leave the field blank.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Finish Suite even if Time Limit Reached&#039;&#039;&#039;&amp;lt;br&amp;gt;This check box determines if either the execution of a test plan is stopped immediately after reaching the time limit or let the execution finish, e.g. to execute the remaining items and any post actions.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Loop (Stop on Error or Failure / Success)&#039;&#039;&#039;&amp;lt;br&amp;gt;This check box toggles looping on or off. If on, the execution of the test plan will be repeated until an error or failure (success) is encountered or otherwise the time limit for the execution is reached. The stop on condition feature is useful to catch sporadic error-behavior of a system under test. For example, to run a test unattended over night, but stop when a certain condition arises.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Loop (Skip successful tests when looping)&#039;&#039;&#039;&amp;lt;br&amp;gt;This check box toggles, if only failed or inconclusive tests should be run when looping. This is useful, when you want to retry failed tests until all testcases in the testplan are successful.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Loop Count&#039;&#039;&#039;&amp;lt;br&amp;gt;This field is used to set a maximum loop count for the test plan execution. To loop endless just leave the field blank.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Period&#039;&#039;&#039;&amp;lt;br&amp;gt;Forces cycles to be executed with this periodic time. For example, if you specify 30m, the testplan will be repeated every 30 minutes. If an individual run takes longer than the period, the next loop iteration will be performed immediately - otherwise, the system waits (idle) for the time difference between period and previous execution time. Use this, if the system under test needs some cleanup or &amp;quot;healing&amp;quot; time after each test run - especially when doing stress tests on a system which needs database or memory management cleanup after each run (e.g. systems which need some pause to perform garbage collection to prevent ever growing memory usage). Another&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Save Result after each Run&#039;&#039;&#039;&amp;lt;br&amp;gt;If checked, a report file is written as specified in the filename pattern field after each run - either unconditionally, or for every successful or for every failed run. This is useful if a test only fails/succeeds sporadically, and you need a trace/log for those runs. If you do not specify this option, a single huge report may be generated, which is both hard to examine and which may become larger than the systems memory capacity (in this case, expecco would prune the report and throw away older items, which is usually not the user&#039;s intention).&amp;lt;br&amp;gt;The filename pattern specifies the names of those individual report files, and should contain meta patterns such as:&amp;lt;br&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%1&amp;quot; for the current run-number (1..)&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%2&amp;quot; for the individual run&#039;s start timestamp (as YYYYMMDDHHMMSS)&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%3&amp;quot; for the name of the test plan&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%4&amp;quot; for the name of the test suite.&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%5&amp;quot; for the individual run&#039;s start timestamp (as YYYYMMDD-HHMMSS)  (V23.2 only)&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;li&amp;gt;&amp;quot;%6&amp;quot; for the individual run&#039;s start timestamp (as YYYY-MM-DD-HHMMSS) (V23.2 only)&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;br&amp;gt;Thus, &amp;quot;&amp;lt;code&amp;gt;%4-%3-%1-%2.elf&amp;lt;/code&amp;gt;&amp;quot; will generate report files named &amp;quot;suite-plan-1-20141004140005.elf&amp;quot;, &amp;quot;suite-plan-2-20141004140007.elf&amp;quot;, etc.&amp;lt;br&amp;gt;You may specify multiple report file patterns in this field (separated by semicolon &amp;quot;;&amp;quot;), to generate reports in different formats. For example, enter &amp;quot;&amp;lt;code&amp;gt;run%1.elf , run%1.pdf&amp;lt;/code&amp;gt;&amp;quot; to generate both a full log (which can be reopened with expecco for detail information) and a summary report as pdf document. For all reports, the default report template of the suite (or the user settings) is used. &amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;lt;br&amp;gt;The individual report files are created either in the project&#039;s attachment folder or, if an absolute pathname is given as pattern, in that folder.&amp;lt;br&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;The attachment folder is a temporary folder, which is automatically removed when expecco is closed, or another suite is opened. Thus, you should archive those after execution. If expecco ALM is used as a test execution management system, these files will be uploaded and archived automatically after a run.&amp;lt;br&amp;gt;&amp;amp;nbsp;&amp;lt;br&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;If expecco is used without expecco ALM, you may want to add a post-execution action, which copies those files to an archive, a database or checks them into a versioning repository. This is also a possible solution, if expecco-tests are to be started via another system, like jenkins or a batch script.&lt;br /&gt;
&lt;br /&gt;
:New in V23.2:&lt;br /&gt;
::You may also provide shell- and environment variable replacements in the filename; $(xxx) will be expanded by either a shell/cmd or a project-variable named &amp;quot;xxx&amp;quot;.&lt;br /&gt;
::Thus, if you &amp;quot;&amp;lt;code&amp;gt;setenv ELF_DIR /tmp/myrun&amp;lt;/code&amp;gt;&amp;quot; and define the report file pattern as &amp;quot;&amp;lt;code&amp;gt;$(ELF_DIR)/run%1.elf&amp;lt;/code&amp;gt;&amp;quot;, your files will be stored as &amp;quot;/tmp/myrun/run1.elf&amp;quot;, &amp;quot;/tmp/myrun/run2.elf&amp;quot;, etc.&lt;br /&gt;
::Or if you set a project variable named &amp;quot;ELF_DIR&amp;quot; (possibly even dynamically during the run), the directory is defined by that variable&#039;s value.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;span ID=&amp;quot;SeverityIgnoreLimit&amp;quot;&amp;gt;&#039;&#039;&#039;Severity Ignore Limit&#039;&#039;&#039;&amp;lt;/span&amp;gt; (new in 21.2)&amp;lt;br&amp;gt;By default, a test plan stops executing further test cases if a &amp;quot;Mandatory (also called &amp;quot;Required&amp;quot;) test case fails, and only continues after a fail with the next test case if the failed test case was marked as &amp;quot;Optional&amp;quot;.&lt;br /&gt;
:Test cases should be marked as &amp;quot;Mandatory&amp;quot;, if it really does not make any sense to continue with a test; for example, if the device under test has no power, if a login procedure failed or if a measurement device is offline.&lt;br /&gt;
:However, it is sometimes useful to have a more fine-grain control over the severity of a failure.&lt;br /&gt;
:For this, you can pass a severity level with a FAIL (either by calling &amp;lt;code&amp;gt;fail_severity()&amp;lt;/code&amp;gt; in elementary code, or via the &amp;quot;&amp;lt;code&amp;gt;FAIL-with-SEVERITY&amp;lt;/code&amp;gt;&amp;quot; action from the standard library).&lt;br /&gt;
:In the tesplan, you can now specify which severity level is considered severe enough to stop the test plan. In other words, of a FAIL-severity is less than the limit specified in that field, then test plan will continue executing mandatory test cases.&lt;br /&gt;
:Severities are numbers from 0 to 100. For backward compatibility, a regular FAIL (i.e. without an explicit severity) are handled like a max-severe failure with a pritority of 100.&lt;br /&gt;
:These cannot be ignored by the severity limit field.&lt;br /&gt;
:Thus old suites which where developed before the 21.2 version will keep their behavior of stopping when a mandatory test case fails, whereas new test actions can use the new &amp;quot;&amp;lt;code&amp;gt;FAIL-with-SEVERITY&amp;lt;/code&amp;gt; action to pass aseverity level, which is then compared against the limit set for the run.&lt;br /&gt;
:Notice that this is a per-run setting. The severity limit will not be stored with the suite and it will not be made persistent in the user&#039;s settings. This limit is meant to be used when tests are manually started by an operator or during test development, but not for productions systems. Therefore, in a production run, all FAILS within a mandatory test case will stop the run.&lt;br /&gt;
:For now, the elementary &amp;quot;&amp;lt;code&amp;gt;fail_severity()&amp;lt;/code&amp;gt;&amp;quot; API is only available in expecco elementary actions (i.e. script actions and bridged actions cannot as-yet call this. These may be provided in future releases, if there are sufficient requests from customers (for now, you can pass a fail severity from a bridged elementary action via an output pin back to expecco, and raise the FAIL there, using the action from the std-lib).&lt;br /&gt;
&lt;br /&gt;
=== Manual Execution Settings ===&lt;br /&gt;
*&#039;&#039;&#039;Stop between individual Tests&#039;&#039;&#039;&amp;lt;br&amp;gt;This check box allows you to stop the execution between each testcase. A confirmation dialog will pop up, asking for a confirmation-click to continue. Useful if any manual handling is needed after each test-case.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Stop between loop cycles&#039;&#039;&#039;&amp;lt;br&amp;gt;Similar to the above. If checked and one of the loop modes is selected, a confirmation dialog pops up after every loop cycle, asking for a confirmation-click to continue.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Stop on Error&#039;&#039;&#039;&amp;lt;br&amp;gt;This check-box determines whether the execution of the test plan is stopped when an error occurs. There are two such check boxes, to specify if it should apply only to test-cases marked as &amp;quot;required&amp;quot; or also to &amp;quot;optional&amp;quot; test cases.&lt;br /&gt;
&lt;br /&gt;
=== expecco ALM Settings ===&lt;br /&gt;
These settings are only relevant if expecco is used as a &amp;quot;slave test execution engine&amp;quot; for AIDYMO (formerly called &amp;quot;&#039;&#039;expecco ALM&#039;&#039;&amp;quot;). They are ignored if expecco is running as a stand alone application (e.g. by the test developer) or started manually by a test engineer (see [[Command_Line_Options|&amp;quot;Command Line Options&amp;quot;]]).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Visible in AIDYMO&#039;&#039;&#039;&amp;lt;br&amp;gt;This checkbox determines whether the test plan is visible in [[Expecco_ALM_Overview/en|expecco ALM/AIDYMO]]. Such externally visible test plans can later be executed automatically by AIDYMO. Invisible test plans are useful for the test developer, to leave partial tests, setup, shutdown or cleanup sequences in the test suite, which are not meant for public use (or use by the automatic test scheduler).&lt;br /&gt;
*&#039;&#039;&#039;Operator Needed&#039;&#039;&#039;&amp;lt;br&amp;gt;This checkbox determines whether an operator is required during execution of the test. AIDYMO will then ask a human operator to supervise/perform the test.&lt;br /&gt;
*&#039;&#039;&#039;Cases Visible in AIDYMO&#039;&#039;&#039;&amp;lt;br&amp;gt;This checkbox determines whether test cases are individually selectable for execution in AIDYMO. If unchecked, only the whole test plan can be configured for an automatic run. You should only turn this check on, if the test cases are independent from each other, and do not need state from a previous test case or leave the system under test in a state needed by another test case. Otherwise, it is better to define multiple test plans, each with its individual setup/shutdown actions to leave the system under test in a defined state, and let the test manager choose among those plans, instead of individual test cases.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--* &#039;&#039;&#039;MON&#039;&#039;&#039;&amp;lt;br&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Configuring Testcases ==&lt;br /&gt;
&lt;br /&gt;
=== Testcase Description Field ===&lt;br /&gt;
Specifies the test case&#039;s descriptive name which is shown in reports, traces and log files.&lt;br /&gt;
If this field is left blank, the name of the action block which implements the test case is shown.&lt;br /&gt;
This field does not affect the execution - it only controls the names used in reports and logs.&lt;br /&gt;
&lt;br /&gt;
=== Action ===&lt;br /&gt;
The action block, which implements the test case. This can be any compound or elementary action block from the left tree. The block must be one without input pins - if required, wrap it into a new compound block and provide input values from any source, such as constant freeze values, database values, CSV values from a file or environment variable values. You can either set the action by dragging a block from the left tree into this field, or by opening a selection dialog via the &amp;quot;...&amp;quot; button at the field&#039;s right.&lt;br /&gt;
&lt;br /&gt;
=== Condition Variables ===&lt;br /&gt;
Condition variables provide an easy to use control mechanism over which testcase items are executed during a run. By specifying a list of boolean condition variables in this field, the testcase item will only be executed if all of those variables contain a &amp;quot;&amp;lt;CODE&amp;gt;true&amp;lt;/CODE&amp;gt;&amp;quot; value (non-existing variables are treated like being &amp;quot;&amp;lt;CODE&amp;gt;true&amp;lt;/CODE&amp;gt;&amp;quot;). After the execution, the success-state is written to the variables named in the &amp;quot;&#039;&#039;Set Variables&#039;&#039;&amp;quot; field.&lt;br /&gt;
These variables are managed in the testplan&#039;s environment. Therefore, you can also access these variables via regular environment blocks or via the low level code API (environmentAt: / environmentAt:put: calls). Condition variables can be used to disable individual test cases or to guide execution through different paths depending on previous actions. A typical application is to read out the system under tests configuration by a pre-action or first test case step, then setting condition variables, and execute only specific subsets of the suite, depending on the outcome.&lt;br /&gt;
&lt;br /&gt;
More complex conditional execution is possible by wrapping individual test case actions into a compound block and placing condition test actions into that.&lt;br /&gt;
&lt;br /&gt;
=== Adding Pre and Post Execution ===&lt;br /&gt;
Individual testcase items can have pre- and post-execution actions too. The pre-execution action (if specified) is executed each time the item is executed; the post execution action is executed after the item&#039;s execution has finished. This can be useful e.g. to allocate and/or release resources, to check for more complex preconditions, system state or for the test system&#039;s configuration, and to leave that information in environment variables to be accessed by later test steps, or be used as condition variables. To add a pre- or post-execution action, simply drag and drop a block from the navigation tree into the according slot. Please note that these block may not have input pins.&lt;br /&gt;
&lt;br /&gt;
The pre-execution action is also a &#039;&#039;pre condition&#039;&#039;.&lt;br /&gt;
If it ends non-successful, the corresponding test case and any post execute action are skipped.&lt;br /&gt;
&lt;br /&gt;
=== Background Action ===&lt;br /&gt;
Sometimes, a background server process, monitor or data feeder activity is required to run in parallel to the actual test scenario.&lt;br /&gt;
This field allows for an action to be defined, which is started in parallel with (actually: right before) the test plan and terminated afterwards. Any compound or elementary block can be specified. Typically, this will be a block which opens a server socket, pipe or other communication channel to feed the system under test, or to start an external program for monitoring, capturing or generating data.&lt;br /&gt;
Please note that this block may not have input pins.&lt;br /&gt;
&amp;lt;br&amp;gt;If you need a background action to run during individual actions, place them as a step into the action&#039;s diagram.&lt;br /&gt;
&lt;br /&gt;
=== Log Processor Action ===&lt;br /&gt;
Test executions generate an execution log/trace, which is later used to generate a more or less detailed report. For most customers, the report settings allow for the most common type of reports to be generated (by specifying the amount of data and detail of the report there).&lt;br /&gt;
&lt;br /&gt;
However, for very special reports, or if specific data has to be extracted and postprocessed, it may be useful to process the generated raw activity data before it is used or instead of being used as input to the report generator.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;&#039;&#039;Log Processor&#039;&#039;&amp;quot; field allows for an action block to be specified, which gets the raw log as input and may produce a cooked-up version of it as output. If the log processor has no output, the original activity log will be passed on to the report generator.&lt;br /&gt;
&lt;br /&gt;
Arbitrary processing, filtering, renaming or archival of the raw data is possible in this action. Of course, some knowledge about the structure of that raw data is required, and you should consult the class browser and/or open a data inspector on a generated raw log for this. You will find an example in the &amp;quot;d11_LOG_Processing_Example.ets&amp;quot; suite (in &amp;quot;projects/examples&amp;quot;). Also, the reflection library now contains activityLog processing actions in the &amp;quot;Analysis&amp;quot; folder, and a sample testplan.&lt;br /&gt;
&lt;br /&gt;
The log processor can also be used to extract particular information and save it into a separate database or file in any format. In this case, the log processor should not modify the given activity log, and either not having an output pin, or send it unchanged to its output.&lt;br /&gt;
&lt;br /&gt;
Notice that there are both per-testcase log processors and a an overall (per testplan) log processor.&lt;br /&gt;
The latter gets a collection (i.e. Array) of individual activity logs as input, which it should process in an enumeration loop. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
=== Adding an Inventory ===&lt;br /&gt;
If the test case, or a nested requires skills, an inventory has to be specified here, otherwise the test will not be able to perform. You can also specify inventories for certain test cases. To add an inventory simply drag and drop it from the navigation tree into the according slot.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Testgroup and Risk Setting ===&lt;br /&gt;
For the selective execution of a test plan it can be useful to set a risk level for certain test cases or to collect related test cases in test groups. The risk level can go from &amp;quot;&amp;lt;CODE&amp;gt;very low&amp;lt;/CODE&amp;gt;&amp;quot; to &amp;quot;&amp;lt;CODE&amp;gt;very high&amp;lt;/CODE&amp;gt;&amp;quot; or can be set to &amp;quot;&amp;lt;CODE&amp;gt;unknown&amp;lt;/CODE&amp;gt;&amp;quot;. To add a block to an test group, just enter identifiers for the groups into the according field. Multiple identifiers must be separated by spaces. See [[Testplan_Editor-TestplanListView_Editor/en#Selective Execution|&amp;quot;Selective Execution&amp;quot;]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Execution Settings ===&lt;br /&gt;
The check box in front of each test case determines whether it is executed or not (in the upper list). Please note that this setting is temporary and will not be saved. To set the default execution toggle setting, use the &amp;quot;&#039;&#039;Default for Execute&#039;&#039;&amp;quot; check box in the lower attribute area.&lt;br /&gt;
&lt;br /&gt;
=== Action Parameters ===&lt;br /&gt;
Actions which have input pins need additional values when executed. If such an action is placed into a test plan, an additional tab is provided in the lower attribute area where values for those pins are to be entered.&lt;br /&gt;
&lt;br /&gt;
Notice that only a limited set of data types are allowed for these. If more complex values are needed, you must place the action as a step into another compound &#039;&#039;Test Case Action&#039;&#039;, feed the step&#039;s input pins as required and place this &#039;&#039;wrapper&#039;&#039; action into the test plan. There of course, any arbitrary complex data may be generated or acquired from a file, attachment or database.&lt;br /&gt;
&lt;br /&gt;
= Context Menu of the Testcase List =&lt;br /&gt;
Some of the context menu (right-click) functions of the test-case/activity-log list operate on the selected item or set of items.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Context Menu Testplan.png|thumb|373px|Context Menu]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Add Testcase&#039;&#039;&#039;&amp;lt;br&amp;gt;Adds a new (blank) test-case to the test-plan. You should drag and drop a test action into the &amp;quot;block&amp;quot; field in the lower pane.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Delete Testcase&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes the selected test-case from the test-plan.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Enable selected Testcases&#039;&#039;&#039;&amp;lt;br&amp;gt;Enables (activates) the selected test-cases for execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Disable selected Testcases&#039;&#039;&#039;&amp;lt;br&amp;gt;Disables the selected test-cases for execution.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Make all Enable Flags the Default for Execution&#039;&#039;&#039;&amp;lt;br&amp;gt;Sets the state of the selection as the default for the test case. This will be the initial enable/disable-state of those test-cases, when the suite is loaded.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Make selected Testcase Required&#039;&#039;&#039;&amp;lt;br&amp;gt;Sets the priority of the selected test-cases to &amp;quot;Required&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Make selected Testcases Optional&#039;&#039;&#039;&amp;lt;br&amp;gt;Sets the priority of the selected test-cases to &amp;quot;Optional&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Open Page on selected Item&#039;&#039;&#039;&amp;lt;br&amp;gt;Opens a new browser page on the selected test-case&#039;s action. This function is only available if exactly one test-case is selected.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Update&#039;&#039;&#039;&amp;lt;br&amp;gt;Update all activity logs and sublogs under the selected item.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Find Next Error&#039;&#039;&#039;&amp;lt;br&amp;gt;Find and select the next failed or erroneous test-case in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Find Previous Error&#039;&#039;&#039;&amp;lt;br&amp;gt;Find and select the previous failed or erroneous test-case in the activity log.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Remove Result for selected Items&#039;&#039;&#039;&amp;lt;br&amp;gt;Removes the test results of the selected test-case.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Compress Result for selected Items&#039;&#039;&#039;&amp;lt;br&amp;gt;Compresses the log result for the selected items. Compression means that only erroneous log entries are kept; all passed and OK infos are removed.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Generate Report from here...&#039;&#039;&#039;&amp;lt;br&amp;gt;Generates a [[Report Generation/en|report]] for the selected test-case (and, if this is a sub-testplan, for all nested test-cases).&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Move Up/Down&#039;&#039;&#039;&amp;lt;br&amp;gt;To change the execution order of the test-cases.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The full online documentation can be found under: [[Online Documentation/en|Online Documentation]]&lt;br /&gt;
&lt;br /&gt;
= Plugin Extension Tabs =&lt;br /&gt;
&lt;br /&gt;
Plugins may add additional pages to this editor. Please refer to the individual plugin documentation.&lt;br /&gt;
For example, the Jira plugin adds a tab to specify the issue action to be taken in case of a failed test case execution.&lt;br /&gt;
&lt;br /&gt;
[[Category:Editors]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Java_Browser/en&amp;diff=29202</id>
		<title>Java Browser/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Java_Browser/en&amp;diff=29202"/>
		<updated>2024-02-21T16:39:53Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Using Java Browser */ new location in the menu&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Java Browser&#039;&#039;&#039; provides a simple interface to browse Java code. This is useful for test developers who write tests which use [[ElementaryBlock_Element/en#Groovy_Blocks|Groovy blocks]] to connect to the system under test. &lt;br /&gt;
&lt;br /&gt;
== Using Java Browser ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Select_Workspace_01.png|200px|thumb|right|Workspace selection dialog]]&lt;br /&gt;
[[Datei:JBrowser 01.png|200px|thumb|right|Java browser window]]&lt;br /&gt;
To open the Java Browser, select &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Productivity&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Java Browser&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Open...&#039;&#039;&amp;quot; and then select a [[#Workspace|workspace]]. To create a new workspace, enter a new, empty directory. &lt;br /&gt;
&lt;br /&gt;
After the workspace is chosen, a single Java Browser window appears. It shows Java packages, classes and methods as well &lt;br /&gt;
as source code if it&#039;s available. If the source code is not available then it still shows the class structure without actual methods&#039; source code.&lt;br /&gt;
&lt;br /&gt;
== Workspace ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Java Browser&#039;&#039;&#039; stores all Java code and sources in a folder called a &#039;&#039;workspace&#039;&#039;. You can freely move workspaces around or store them on a shared network drive. &lt;br /&gt;
&lt;br /&gt;
To create a workspace, select an empty directory. To add Java code to the workspace, open the workspace settings (in Java Browser window, select &#039;&#039;Workspace&#039;&#039; ► &#039;&#039;Settings&#039;&#039;). In the settings dialog you may add &amp;quot;.jar&amp;quot; files or directories containing &amp;quot;.class&amp;quot; files and attach sources to then. Of course, you may use the workspace settings dialog any time later to add or remove &amp;quot;.jar&amp;quot; or &amp;quot;.class&amp;quot; file directories.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Java_GUI_Plugins/en&amp;diff=29119</id>
		<title>Java GUI Plugins/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Java_GUI_Plugins/en&amp;diff=29119"/>
		<updated>2024-01-29T13:33:51Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Connection to Remote Systems */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Java_GUI_Plugins|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
== Supported Java Technologies ==&lt;br /&gt;
expecco supports the automation of Java applications implemented with Java Swing, Java SWT or JavaFX. Also supported are applications that combine several of these technologies, e.g. a Swing application with embedded JavaFX content.&lt;br /&gt;
&lt;br /&gt;
=== Java Swing ===&lt;br /&gt;
&lt;br /&gt;
This plugin for expecco allows you to create automated tests for Java applications whose user interfaces were created with Swing. The block library contains blocks for controlling and checking Swing user interfaces. This plugin is also integrated into the expecco GUI Test Extension. This extension supports the development of test sequences. &lt;br /&gt;
&lt;br /&gt;
==== Main Features ====&lt;br /&gt;
&lt;br /&gt;
* Automated operation and verification of Swing user interfaces&lt;br /&gt;
* Simultaneous operation of several applications&lt;br /&gt;
* Control of Swing user interfaces on remote target systems&lt;br /&gt;
* Control of Java applications already running independently (no change to source code necessary, no recompilation of the application necessary)&lt;br /&gt;
* Addressing of control elements by XPath&lt;br /&gt;
* Access at object level possible via Java Bridge Interface Library&lt;br /&gt;
* Integration into the [[Expecco GUI Tests_Extension Reference/en|expecco GUI Tests Extension]]&lt;br /&gt;
* Block library with actions and checks for Swing components&lt;br /&gt;
&lt;br /&gt;
=== Java SWT ===&lt;br /&gt;
Similar for applications created with the SWT GUI framework.&lt;br /&gt;
&lt;br /&gt;
=== JavaFX ===&lt;br /&gt;
Since Java 11, JavaFX is no longer included in the JDK. Therefore you have to install an additional JavaFX SDK, e.g. from [https://openjfx.io/ OpenJFX]. Then copy the jar files from the lib directory of the JavaFX JDK to &amp;lt;code&amp;gt;packages\exept\expecco\plugin\javafx\lib&amp;lt;/code&amp;gt; in the expecco installation directory.&lt;br /&gt;
&lt;br /&gt;
== Functionality ==&lt;br /&gt;
&lt;br /&gt;
The interface establishes a connection to the Java VM and provides functions for reading widget attributes, recording user input, and remotely controlling the application. In addition, a library provides additional building blocks for automating tests.&lt;br /&gt;
Essentially, the Java Swing plugin consists of two parts, the plugin&lt;br /&gt;
for expecco and the application control (agent). To control the Swing application, an agent is loaded into the Java Virtual Machine of the running Java application. A Java Development Kit 1.8 (JDK) or higher is required to load the agent. However, the application to be tested can be run in a normal Java Runtime Edition 1.8 (JRE).&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
On the computer where the application to be tested is to run (local or remote):&lt;br /&gt;
&lt;br /&gt;
* [http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html Java Development Kit 1.8] or higher (to load the agent)&lt;br /&gt;
* [http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html Java Runtime Edition 1.8] or higher (to run the application to be tested)&lt;br /&gt;
&lt;br /&gt;
The expecco requirements apply on the expecco computer.&lt;br /&gt;
&lt;br /&gt;
Please note that both the agent and the application to be tested must be started with either 32 or 64 bit Java, otherwise no connection is possible.&lt;br /&gt;
&lt;br /&gt;
Caused by JDK changes between Java versions, potential version conflicts may occur.&lt;br /&gt;
&lt;br /&gt;
The compatibility of the versions is as follows. [[Java GUI Plugins#Fehlerbehandlung|Further information on this.]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:JavaSwing Bridge Compatibility.png|border|200px|]]&lt;br /&gt;
&lt;br /&gt;
===Access Permissions===&lt;br /&gt;
&lt;br /&gt;
To be able to guarantee a connection on the target system, additional parameters must be specified when starting the application to be tested (as well as the Java agent).&lt;br /&gt;
&lt;br /&gt;
There are two ways to do this&lt;br /&gt;
&lt;br /&gt;
* Set an environment variable that is automatically loaded at the start of each Java application&lt;br /&gt;
* Manual transfer of parameters at each start of a Java application&lt;br /&gt;
* (Alternatively you can change access rights in the module-info.java files directly, but this is anything but practical)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Up to Java 11&#039;&#039;&#039; it should be sufficient to set the following parameters:&lt;br /&gt;
: &amp;lt;code&amp;gt;-Djdk.attach.allowAttachSelf=true&amp;lt;/code&amp;gt;&lt;br /&gt;
: &amp;lt;code&amp;gt;--illegal-access=permit&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Setting an environment variable works as follows (&#039;&#039;Example JDK_JAVA_OPTIONS which is loaded at every JVM start&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;for Windows Systems&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;setx JDK_JAVA_OPTIONS &amp;quot;-Djdk.attach.allowAttachSelf=true; --illegal-access=permit&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
* or via the GUI (Windows key + Pause).&lt;br /&gt;
&lt;br /&gt;
[[File:Windows Setenvironment.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;for Unix systems&#039;&#039;&#039;&lt;br /&gt;
* Bash: &amp;lt;code&amp;gt;export _JAVA_OPTIONS=&#039;-Djdk.attach.allowAttachSelf=true; --illegal-access=permit&#039;&amp;lt;/code&amp;gt; &lt;br /&gt;
* C Shell: &amp;lt;code&amp;gt;setenv _JAVA_OPTIONS &#039;-Djdk.attach.allowAttachSelf=true; --illegal-access=permit&#039;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Since Java 11&#039;&#039;&#039; there is a stricter separation for the encapsulation of modules:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;--illegal-access=permit&amp;lt;/code&amp;gt; will no longer work if the target application has a fixed module encapsulation ([https://stackoverflow.com/questions/46741907/what-is-an-automatic-module Details]).&lt;br /&gt;
In this case, additional parameters must be specified at program start which allow expecco access to the inherent resources.&lt;br /&gt;
Depending on the technology used, the required parameters can vary, which is why you have to find them out for yourself.&lt;br /&gt;
&amp;lt;code&amp;gt;jdeps list-deps JARNAME.jar&amp;lt;/code&amp;gt; Jdeps is a freely available (part of the jdk) very useful tool for this purpose.&lt;br /&gt;
A short overview of the commands can be found [https://doc.expecco.de/w2.x/images/0/03/Java_module_cheat_sheet.pdf here] [https://zeroturnaround.com/rebellabs ©]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example JavaFX&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
The environment variable &amp;lt;code&amp;gt;PATH_TO_FX&amp;lt;/code&amp;gt; which points to the JavaFX directory must be set (functionality see above)&lt;br /&gt;
and the following parameters must be available when starting the Java application:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toccolours mw-collapsible mw-collapsed&amp;quot;&amp;gt;&lt;br /&gt;
Parameter list (fold out)&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-collapsible-content&amp;quot;&amp;gt;&lt;br /&gt;
*&amp;lt;code&amp;gt;--modul-path &amp;quot;%PATH_TO_FX%&amp;quot; &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-modules=javafx.controls &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-modules=javafx.swing &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-modules=javafx.web &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.stage=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphicss/com.sun.javafx.stage=ALL-UNNAMED &amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.layout=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.controls/javafx.scene.control=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.controls/javafx.scene.control.skin=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.controls/javafx.scene.chart=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.controls/com.sun.javafx.charts=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.controls/com.sun.javafx.charts=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.controls/com.sun.javafx.scene.control=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.image=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.shape=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.text=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.application=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphicss/javafx.geometry=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.robot=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.graphicss/com.sun.glass.ui=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/com.sun.glass.ui=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/com.sun.glass.ui.win=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.graphics/javafx.scene.input=ALL-UNNAMED &amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.base/javafx.event=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.base/com.sun.javafx.runtime=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens javafx.base/com.sun.javafx.runtime=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.graphicss/com.sun.javafx.scene=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.graphicss/com.sun.javafx.util=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.graphicss/com.sun.javafx.scene.input=ALL-UNNAMED &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-exports javafx.web/com.sun.webkit.dom=ALL-UNNAMED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;--add-opens java.base/java.util=ALL-UNNAMED&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not want to supply 10+ command line parameters, you can use instead [[File:Java_fx_command_options.txt]]. Then you start your application with the java command:&lt;br /&gt;
    java @java_fx_command_options.txt ....&lt;br /&gt;
&lt;br /&gt;
If you still get a &amp;lt;code&amp;gt;java.lang.IllegalAccessError&amp;lt;/code&amp;gt;, you have to extend this parameter in the following way:&lt;br /&gt;
* Error text of the type &amp;lt;code&amp;gt;Module &amp;lt;module&amp;gt; does not open &amp;quot;&amp;lt;package&amp;gt;&amp;quot; for unnamed modules&amp;lt;/code&amp;gt;:&lt;br /&gt;
: &amp;lt;code&amp;gt;--add-opens &amp;lt;modules&amp;gt;/&amp;lt;package&amp;gt;=ALL-UNNAMED &amp;lt;/code&amp;gt;&amp;gt;&lt;br /&gt;
: Example:&#039;&#039; &amp;lt;code&amp;gt;Module java.base does not open java.lang for unnamed module&amp;lt;/code&amp;gt; &#039;&#039;solve with:&#039;&#039; &amp;lt;code&amp;gt;--add-opens java.base/java.lang=ALL-UNNAMED&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Error text of the type &amp;lt;code&amp;gt;cannot access the class &amp;lt;package&amp;gt;.&amp;lt;class name&amp;gt; (in module &amp;lt;module&amp;gt;), because the module &amp;lt;module&amp;gt; &amp;lt;package&amp;gt; does not export to the unnamed module&amp;lt;/code&amp;gt;:&lt;br /&gt;
: &amp;lt;code&amp;gt;---add-exports &amp;lt;modules&amp;gt;/&amp;lt;package&amp;gt;=ALL-UNNAMED &amp;lt;/code&amp;gt;&amp;gt;&lt;br /&gt;
: Example:&#039;&#039; &amp;lt;code&amp;gt;cannot access the class com.sun.javafx.scene.input.ExtendedInputMethodRequests (in the module javafx.graphics) because the module javafx.graphics com.sun.javafx.scene.input not exported into an unnamed module &amp;lt;/code&amp;gt; &#039;&#039;solve with:&#039;&#039; &amp;lt;code&amp;gt;--add-exports javafx.graphicss/com.sun.javafx.scene.input=ALL-UNNAMED&amp;lt;/code&amp;gt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tool Generate CmdLine File for arbitrarily modules (Java 11 et sqq.)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See [[JavaBridgeOpenModule/en|Generate CmdLine File for Java 11 et sqq.]]&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
=== Installation on the expecco Computer ===&lt;br /&gt;
&lt;br /&gt;
When installing expecco, make sure that the Java plugin is selected as the component to be installed.&lt;br /&gt;
&lt;br /&gt;
If the application to be tested for the development of test sequences is executed on the same computer, start expecco and under &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Plugins&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Java Bridge&#039;&#039;&amp;quot; &lt;br /&gt;
set the local path to a Java Development Kit 1.8 or higher.&lt;br /&gt;
&lt;br /&gt;
The mandatory setting here is &amp;lt;code&amp;gt;JDK Installation Path&amp;lt;/code&amp;gt; which is used for the main connection. &amp;lt;code&amp;gt;Java Installation Path&amp;lt;/code&amp;gt; is an alternative setting for Groovy which only requires a JRE. For local connections, the Java Agent is automatically started with these settings. &lt;br /&gt;
&lt;br /&gt;
[[Datei:JDKPfadEinstellungen.png|border|600px|]]&lt;br /&gt;
&lt;br /&gt;
=== Installation on Test Application Computer ===&lt;br /&gt;
&lt;br /&gt;
You have to copy the javaBin folder of the expecco bridge framework to the test computer. It is in the expecco installation directory at:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;...\exept\bridgeFramework\javaBridge\javaBin&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== expecco GUI Browser ==&lt;br /&gt;
&lt;br /&gt;
The expecco GUI-Browser is an additional tool which offers the possibility to analyze running applications and to develop test sequences. Then you can use the information, such as names and properties of individual elements, to perform actions with the function library or to interact with individual elements.&lt;br /&gt;
&lt;br /&gt;
=== Connecting ===&lt;br /&gt;
&lt;br /&gt;
The following is a short series of pictures that can be used as a &#039;&#039;&#039;guide&#039;&#039;&#039; when setting up a connection&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:JavaSwing GUI Browser.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
First open the &amp;lt;code&amp;gt;GUI Browser&amp;lt;/code&amp;gt; (black circle) and in the tab &amp;lt;code&amp;gt;Connect&amp;lt;/code&amp;gt; select the option &amp;lt;code&amp;gt;Java&amp;lt;/code&amp;gt; (red circle).&lt;br /&gt;
In the opening dialog you can now choose between 3 options.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Start Application on the Local Machine&#039;&#039;&#039;&lt;br /&gt;
: provides a convenient way to start a local Java application via command line command&lt;br /&gt;
* &#039;&#039;&#039;Connect to an already running Application on the Local machine&#039;&#039;&#039;&lt;br /&gt;
: Allows connection to locally running Java applications. The Java Agent is automatically started with the Java version you specified in the expecco settings.&lt;br /&gt;
* &#039;&#039;&#039;Connect to an already running Application on a Remote Machine&#039;&#039;&#039;&lt;br /&gt;
: Allows you to connect to an already started Java Agent on another machine. This will then connect to the Java application running there.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:JavaSwing Connection Window.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
A search for Java applications lists all running Java virtual machines on the target system (in the example: localhost). A selection of the individual entries lists further information about the respective application.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:JavaSwing Connection Connected.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
If a connection has been successfully established, it will automatically be entered in the Expecco configuration list. There you can also see the GUI structure of the application as a hierarchical tree. Information on how to proceed can be found here: [[Expecco_GUI_Tests_Extension_Reference| GUI Test Reference]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:JavaSwing Connection Reconnect.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
Closed connections stay in the GUI browser. If the application is still running, you can reestablish the connection. To do this, right-click on the entry and select &#039;&#039;Connect&#039;&#039; from the context menu.&lt;br /&gt;
If the connection settings have changed, you must reconfigure the connection. This can happen if you have restarted the application in the meantime. When using a remote system, this also applies to the agent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Connection to Remote Systems ===&lt;br /&gt;
[[File:JavaSwing Connection RemoteSetup.png|border|600px|]]]&lt;br /&gt;
&lt;br /&gt;
To establish a connection remotely, the Java Agent must first be started on the target computer. To do this, navigate to the directory &amp;lt;code&amp;gt;...\exept\bridgeFramework\javaBridge\javaBin&amp;lt;/code&amp;gt; on the computer.&lt;br /&gt;
There is a script which automatically detects the Java version in JAVA_HOME and starts the correct agent.&lt;br /&gt;
* Windows users start &amp;lt;code&amp;gt;startAgentLoader.bat&amp;lt;/code&amp;gt;&lt;br /&gt;
* UNIX users start &amp;lt;code&amp;gt;startAgentLoader.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
These scripts can be provided with parameters via the command line as shown in the picture.&lt;br /&gt;
* &amp;lt;code&amp;gt;-ip &amp;lt;HostnameOderIP&amp;gt;&amp;lt;/code&amp;gt; gives the agent a special IP to wait for a connection. Useful for specific network masks.&lt;br /&gt;
: Default host is 0.0.0.0.&lt;br /&gt;
* &amp;lt;code&amp;gt;-port &amp;gt;PortNumber&amp;lt;/code&amp;gt; gives the agent a specific port to wait for connections from Expecco.&lt;br /&gt;
: Default port is 56784.&lt;br /&gt;
&lt;br /&gt;
=== Warnings ===&lt;br /&gt;
[[Datei:JavaSwing Connection Warnings.png|border|600px|]]&lt;br /&gt;
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
If any problems occur with the applications in this list, as can be seen in the picture above,&lt;br /&gt;
the connection dialog automatically returns a suggested solution.&amp;lt;br&amp;gt; If the error that occurs would make a connection impossible, the corresponding entry is automatically marked as invalid.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
The following error messages may occur and can be easily corrected:&lt;br /&gt;
::{|&lt;br /&gt;
|JAVA VERSION MISMATCH&lt;br /&gt;
|As you can see in the picture, there may be Java version conflicts between the agent and the application.&amp;lt;br&amp;gt; In this case it is easiest to adjust the Expecco settings for Java Bridge.&amp;lt;br&amp;gt; A remote connection would have to start the program manually with the desired Java version instead.&amp;lt;br&amp;gt; The Java Agent, if called via the &amp;lt;code&amp;gt;startAgentLoader&amp;lt;/code&amp;gt; script, selects the version Based on &amp;lt;code&amp;gt;JAVA_HOME&amp;lt;/code&amp;gt; on the remote system&lt;br /&gt;
|-&lt;br /&gt;
|32 BIT - 64 BIT CONFLICT&lt;br /&gt;
|The 32 and 64 bit versions of Java are not compatible with each other. &amp;lt;br&amp;gt;Both the agent and the application must be started with the same &amp;quot;bit version&amp;quot; of Java.&amp;lt;br&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|UNABLE TO DETERMINE VERSION&lt;br /&gt;
|The agent cannot determine which Java version the application is using. &amp;lt;br&amp;gt;A connection may be possible, but there may be a potential version conflict.&lt;br /&gt;
|}&lt;br /&gt;
:&lt;br /&gt;
&lt;br /&gt;
== Cross-Technology Connections ==&lt;br /&gt;
If an application uses multiple Java technologies, you only need to establish one connection and then use the blocks from the library according to the technology of the element to be addressed. Since expecco 21.1 you can alternatively use blocks from the CommonJavaGUILibrary. Read more about the different libraries in the next section.&lt;br /&gt;
&lt;br /&gt;
=== Embedded JavaFX in Java Swing ===&lt;br /&gt;
If JavaFX is embedded in a Swing application, it contains a JFXPanel element. In the GUI browser, the JavaFX elements are displayed below this panel. For the FX blocks to find these embedded FX elements, the block &#039;&#039;Set FX Context To Panel&#039;&#039; from the Swing Library with the path to the JFXPanel must be executed at the beginning.&lt;br /&gt;
&lt;br /&gt;
=== WebView in JavaFX ===&lt;br /&gt;
If a WebView is included in JavaFX, its elements are displayed in the GUI browser below the WebView element. For these elements there are separate blocks in the JavaFX library, which are combined in the folder &#039;&#039;Embedded WebView&#039;&#039;. In order for the elements to be found in the test, the block &#039;&#039;Set WebView Context&#039;&#039; must first be executed on the element WebView.&lt;br /&gt;
&lt;br /&gt;
=== Embedded Java Swing in JavaFX ===&lt;br /&gt;
If Java Swing is embedded in a JavaFX application, it contains a SwingNode element. In the GUI browser, its content is still displayed parallel to the FX content. The modules of the Swing library can be used directly with these elements.&lt;br /&gt;
&lt;br /&gt;
=== Compound Paths ===&lt;br /&gt;
Since expecco 21.1 the CommonJavaGUITestLibrary contains blocks, which generally work with each of the three supported Java technologies as well as Embedded WebView in FX. Just as some blocks only work with special types of elements, there are blocks, which so far do not support all technologies. But the whole functionality provided by the specific Java libraries is also available here.&lt;br /&gt;
&lt;br /&gt;
For cross-technology connections, these blocks use compound paths, i.e. an embedded element is addressed by a path which combines the path to its embedder with the subpath of the element. For example let&#039;s take a look at a Swing application embedding FX elements using a JFXPanel. The path to an FX button then may look like this&lt;br /&gt;
 /frame/rootpane/layeredpane/panel/JFXPanel/Scene/Node/Button&lt;br /&gt;
where &#039;&#039;/frames/rootpane/layeredpane/panel/JFXPanel&#039;&#039; is the path within the Swing context to the JFXPanel and &#039;&#039;/Scene/Node/Button&#039;&#039; is the path to the button within the FX context of the JFXPanel. Blocks to switch the context are not needed anymore. The paths can also be shortened, but the embedding node, in this case the JFXPanel, has to be an explicit part of the path. E.g.&lt;br /&gt;
 //JFXPanel//Button&lt;br /&gt;
would also work.&lt;br /&gt;
&lt;br /&gt;
Compound paths only work with the blocks in the CommonJavaGUITestLibrary. The blocks in the specific Java libraries still work with the old path and can be used side by side. To switch back to the usage of the old paths and blocks in the GUI Browser, open the menu &#039;&#039;GUI Browser &amp;gt; Recording&#039;&#039; and uncheck &#039;&#039;Record Compound Paths&#039;&#039; there.&lt;br /&gt;
&lt;br /&gt;
== Libraries ==&lt;br /&gt;
There are several libraries that can be used for Java connections. Originally a separate library was provided for each technology, but since expecco 21.1 there is a common library that works with all supported Java technologies. Each of the libraries contains connect blocks that all establish a connection of the same type. Therefore, blocks from all libraries can be used in the same test using the same connection.&lt;br /&gt;
&lt;br /&gt;
=== JavaSwingLibrary ===&lt;br /&gt;
Contains blocks for testing JavaSwing applications and embedded JavaSwing content. There are also blocks to set the context for embedded JavaFX content (see JavaFXLibrary). Paths for these blocks always refer to the JavaSwing content only, e. g. even if it is embedded in a JavaFX application.&lt;br /&gt;
&lt;br /&gt;
=== JavaSWTLibrary ===&lt;br /&gt;
Contains blocks for testing JavaSWT applications.&lt;br /&gt;
&lt;br /&gt;
=== JavaFXLibrary ===&lt;br /&gt;
Contains blocks for testing JavaFX applications and embedded JavaFX content. To access embedded JavaFX elements within a Swing application, the context must first be set to the corresponding JFXPanel. There is a block in the JavaSwingLibrary for this purpose. The paths are then resolved within this context. Otherwise the paths are resolved within the existing stages. There are also blocks for embedded WebView. To use these the context must be set to the corresponding WebView.&lt;br /&gt;
&lt;br /&gt;
=== CommonJavaGUILibrary ===&lt;br /&gt;
Starting with expecco 21.1 the CommonJavaGUILibrary contains blocks which can be used with all Java elements. If an application uses different Java technologies, [[Java_GUI_Plugins/en#Compound_Paths|compound paths]] are used to specify an element. This eliminates the need to switch to different contexts.&lt;br /&gt;
&lt;br /&gt;
However, this library and the extension of the functionality of the block to each element type is still under construction, so some blocks do not yet work with all elements. Furthermore, the library also requires a corresponding new expecco version.&lt;br /&gt;
&lt;br /&gt;
== Example ==&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Set an anchor for the Skip Mode entry --&amp;gt;&lt;br /&gt;
==== The tree in the GUI browser does not show all elements of my application====&lt;br /&gt;
An application consists of many different elements. Some of them are not interactive, i.e. they are not directly visible to the user and are only used for formatting, such as panels. &lt;br /&gt;
&lt;br /&gt;
If many such elements are present, the tree can become very large and very deep. &lt;br /&gt;
As these elements are usually uninteresting for automation, they can be hidden in expecco by default.&lt;br /&gt;
If you need to access one of those elements, or need it to create a unique path, that behavior should be turned off. &lt;br /&gt;
&lt;br /&gt;
The JavaSwingLibrary contains the &#039;&#039;Set Skip Mode&#039;&#039; block for this purpose. On of the following modes can be selected:&lt;br /&gt;
::{|&lt;br /&gt;
|INTERACTIVE &lt;br /&gt;
|Collect only interactive elements&lt;br /&gt;
|-&lt;br /&gt;
|ALL&lt;br /&gt;
|Collect all elements&lt;br /&gt;
|-&lt;br /&gt;
|INTERACTIVE_HYBRID&lt;br /&gt;
|like INTERACTIVE, but with the fallback to ALL if a path cannot be resolved&lt;br /&gt;
|-&lt;br /&gt;
|ALL_HYBRID&lt;br /&gt;
|like ALL, but with the fallback to INTERACTIVE if a path cannot be resolved&lt;br /&gt;
|}&lt;br /&gt;
:Execution of the block changes the behavior for the current connection. It refers to what is displayed in the tree as well as how the paths on the blocks are handled. Since expecco 19.1 the default is ALL_HYBRID and in earlier versions it is INTERACTIVE.&lt;br /&gt;
&lt;br /&gt;
====I cannot connect, but all settings are correct====&lt;br /&gt;
Even though this should not happen in general, here are a few more aspects which affect the connection:&lt;br /&gt;
*Firewall&amp;lt;br&amp;gt;The firewall can interfere with the Java Agent&#039;s communication with the application.&amp;lt;br&amp;gt;Either set up an exception rule for the agent or deactivate the firewall for the duration of the test.&lt;br /&gt;
* Socket in use&amp;lt;br&amp;gt;It can happen, especially when debugging, that a previous instance of a Java agent was not closed correctly. This can lead to it occupying the socket and rejecting other connections.&amp;lt;br&amp;gt;Try &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Debugging&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Close all bridge connections / Close all socket connections&#039;&#039;&amp;quot;. &amp;lt;br&amp;gt;Be warned that this will also close all other existing (local) Expecco connections. In the case of remote connection, a restart of the agent and possibly of the application may help.&lt;br /&gt;
== See Also ==&lt;br /&gt;
[[Expecco GUI Tests Extension Reference/en]]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29106</id>
		<title>Release Notes 23.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29106"/>
		<updated>2024-01-11T08:51:47Z</updated>

		<summary type="html">&lt;p&gt;Matilk: link to 24.x release notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 24.x]]&amp;lt;br&amp;gt;&lt;br /&gt;
See also: [[Release Notes 22.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 23.2 (December 2023) ==&lt;br /&gt;
*Feature: [[Environment_Editor/en#Fields|Static (Step-) Variables]]&lt;br /&gt;
*Feature: DOM inspector (try an XML attachment) generates better xpath suggestions (alternatives in [[Attachment_Editor/en#XML_Inspector | attachment editor]])&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processors]] are now configurable both for individual test cases and for the overall result of a testplan&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processor]] activities are shown in a testplan&#039;s activity log (but not in a report)&lt;br /&gt;
*Feature: Qt-Library: New Action &#039;&#039;QButton::Click&#039;&#039;: direct click, not being delegated to a thread&lt;br /&gt;
*Feature: Qt-Testing: ExpeccoTestService library and Inject-Tool for QT5.15.0 and VS2022:  [[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]]&lt;br /&gt;
*Feature: [[Timeline/en|Timeline view]] for the activity log (Still experimental, might reach its limits with too large logs or while running)&lt;br /&gt;
*Feature: more [[Testplan_Editor/en#Execution_Settings | pathname options]] for testplan when generating ELF-per-run result files (in loops)&lt;br /&gt;
*Feature: a new [[Testplan_Editor/en#Execution_Settings | option]] in testplan to skip successful tests when looping&lt;br /&gt;
*Feature: enhanced manual test wizard with the option to execute the manual tests with a mobile device (Android, Apple IOS or Web-Browser) &lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Ruby_Elementary_Blocks |bridged Ruby elementary actions]]&lt;br /&gt;
*Feature: Improvements in the XML inspector (tree popup menu &amp;amp; string search)&lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Python_Elementary_Blocks |bridged Python elementary actions]] can now be cancelled and terminated&lt;br /&gt;
*Feature: Python settings: Reorganize Python paths, export Python bridge code for debugging in external IDE ([[Installing additional Frameworks/en#Python_Installation|Python_Installation]])&lt;br /&gt;
*Feature: improved [[Tools_TestSuiteDifferenceBrowser|difference viewer]] (project and version compare UI)&lt;br /&gt;
*Feature: environment: current value (possibly changed from initial value) is saved in .elf log file&lt;br /&gt;
*Feature: StandardLibrary: additional optional pins for encoding (e.g. #utf8) in &amp;quot;FileStream [ Open For xxxx ]&amp;quot; blocks&lt;br /&gt;
*Feature: Values that cannot be saved in a .elf log file (e.g. web elements) are now saved and restored as UnrestoreableDate instead of nil&lt;br /&gt;
*New Python Version: Delivered installation package for Python 3.11.6&lt;br /&gt;
*Change in the format of .elf log files to store handled error states. Older expecco versions cannot handle this and might have problems to open such a file.&lt;br /&gt;
*Bug Fix: log processor actions were themself added to the log, possibly leading to problems when executed again&lt;br /&gt;
*Bug Fix: time-limited actions with the &#039;&#039;timeLimitOK&#039;&#039; flag set did not trigger the enable output pin.&lt;br /&gt;
*Bug Fix: zip archive view generated wrong name-list if language setting was EN-US (AM/PM from timestamp was interpreted as part of filename)&lt;br /&gt;
*Bug Fix: unicode strings in environment variables could not be stored to CSV files&lt;br /&gt;
*Bug Fix: a cancelled compound action did write to an output pin in certain situations&lt;br /&gt;
&lt;br /&gt;
== Release 23.1 ==&lt;br /&gt;
*Feature: Continue an interrupted test plan (i.e. even in a new expecco session and/or on another machine) &lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Compound_Paths|compound paths]] for embedded elements.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): [[Selenium_WebDriver_Plugin/en#Recorder|Recorder]] shows available windows and the current frame context.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Shadow_Elements|shadow elements]] in the GUI browser and recorder, accessible by compound paths.&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Qt-Versions]])&lt;br /&gt;
*Feature: Expecco Remote Control &amp;amp; Monitoring Service with Web Front-End (App for Android or Apple IOS is available on request) ([[Expecco_Remote_Control_App/en|expecco Mobile Remote App]])&lt;br /&gt;
*Feature: Diagram Editor: default style for new connections (e.g. hidden)&lt;br /&gt;
*Feature: Diagram Editor: shortcut keys for environment-freeze and others&lt;br /&gt;
*Feature: Diagram Editor: connections can be named&lt;br /&gt;
*Feature: User defined menu operations: Activity-Log in case of an error&lt;br /&gt;
*Feature: Zip-Archive viewer/extractor/inspector in [[Attachment_Editor/en#Zip_Archive_Inspector | attachment editor]]&lt;br /&gt;
*Feature: ManualTest actions are now part of the base system; the extra plugin licence is only needed to import Excel test descriptions&lt;br /&gt;
*Feature: Logging with microsecond resolution timestamps now works in Windows (if enabled in the settings) &lt;br /&gt;
*Feature: Support XML report file fetching via the REST interface&lt;br /&gt;
*Feature: PCAN (USB Can-Bus Adapter) is now supported in 64-bit expecco&lt;br /&gt;
*Feature: Folders can pass Tags to new sub-elements (inherit)&lt;br /&gt;
*Feature: Menu entry to set Test Groups for Tree Elements&lt;br /&gt;
*Standard Library: Warning Dialog with Opt-out option (show only once)&lt;br /&gt;
*FMU/CBridge: [[Functional Mockup Interface | support FMI2 API; partial support for FMI3]]&lt;br /&gt;
*FMU/CBridge: download resources to CBridge (eg. unifmu generated python FMUs work)&lt;br /&gt;
*Fix: nth-root: lost precision when applied to higher than 64bit floats.&lt;br /&gt;
*Fix: LargeFloats rounding was broken&lt;br /&gt;
*Fix: WSDL import with namespace redefinitions&lt;br /&gt;
*New [[Mobile_Testing_Plugin/en#Windows|Mobile Testing Supplement]] for Windows with an option in the installer to add Appium to the Autostart.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29088</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29088"/>
		<updated>2023-12-22T09:42:59Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */ new supplement version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
With the &#039;&#039;Mobile Testing Plugin&#039;&#039; applications can be tested on Android and iOS devices. This includes both real and emulated devices. It does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Same versions as in the predecessor, but with updated chromedriver versions&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; startChromedriverTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29087</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29087"/>
		<updated>2023-12-22T09:37:37Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Windows */ new supplement version&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.2]&lt;br /&gt;
:Im Vergleich zum Vorgänger aktualisierte Chromedriver Versionen.&lt;br /&gt;
*expecco 23.1: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Timeline&amp;diff=29086</id>
		<title>Timeline</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Timeline&amp;diff=29086"/>
		<updated>2023-12-22T09:04:43Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Einleitung */ warning for large logs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Einleitung =&lt;br /&gt;
[[Datei:Timeline.png|800px|thumb|Der Reiter &amp;quot;Zeitleiste&amp;quot;]]&lt;br /&gt;
Die Zeitleiste (Timeline) kann ein hilfreiches Werkzeug sein, um die zeitliche Abfolge Ihrer Testsequenzen zu verstehen, insbesondere, wenn Aktionen parallel laufen. Sie finden sie in der &#039;&#039;Lauf&#039;&#039; Anzeige entweder eines Testplans oder eines Aktionsblocks. Sie verwendet die gesammelten [[Glossary/en#Activity_Log|Logdaten]] um anzuzeigen wann und wie lange eine Aktion ausgeführt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b style=&amp;quot;color:red&amp;quot;&amp;gt;Diese Funktionalität ist in expecco&amp;amp;nbsp;23.2 noch experimentell und kann bei großen Logs oder während des Laufs an ihre Grenzen stoßen.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Darstellung =&lt;br /&gt;
Die Zeitleiste zeigt die Unterblöcke des ausgewählten Blocks als Balken in der Farbe ihres Ausführungsstatus, wobei deren Länge und horizontale Position die Dauer und Startzeit der Ausführung widerspiegeln. Die Zeitskala oben passt sich der dargestellten Zeit an. Das aktuelle Zeitformat können Sie in der oberen rechten Ecke ablesen; z.B. bedeutet &#039;&#039;m:s&#039;&#039; eine Darstellung in Minuten und Sekunden, wobei die Sekunden noch Dezimalstellen aufweisen können, um die Millisekunden anzuzeigen.&lt;br /&gt;
&lt;br /&gt;
Anfangs wird nur die oberste Ebene der Unterblöcke des ausgewählten Blocks angezeigt. Wenn Blöcke parallel ausgeführt werden, landen sie in verschiedenen Zeilen; nacheinander ausgeführte Blocke stehen in einer Zeile. Allerdings bedeutet es für zwei Blöcke, die hintereinander stehen NICHT generell, dass der zweiten vom ersten gestartet wurde.&lt;br /&gt;
&lt;br /&gt;
Sie können Blöcke ausklappen, um deren Unterblöcke zu sehen. Ist ein Block breit genug, wird dies durch ein entsprechendes kleines Icon in der oberen linken Ecke angezeigt. Sie können Blöcke auf- und zuklappen, indem Sie auf dieses Icon klicken. Alternativ können Sie auf einen Block mit der rechten Maustaste klicken und erhalten im Kontextmenü die Möglichkeit, ihn auf- oder zuzuklappen. Die Unterblöcke werden unterhalb ihrer Eltern angezeigt, wobei sich etwaige parallele Blöcke weiter nach unten verschieben. Der Rahmen eines Blocks umfasst seine Unterblöcke um die Verschachtelung zu verdeutlichen. Sie können auch Strg gedrückt halten, um alle Kinder auszuklappen. Da die Zeitleiste nur die Informationen aus den Logdaten darstellt, werden auch nur Blöcke angezeigt, die einen Logeintrag haben. Blöcke, die im Log übersprungen wurden, werden nicht angezeigt.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie einen Block in der Zeitleiste anklicken, wird er ausgewählt, was durch einen roten Rahmen dargestellt wird. Die Hauptinformationen dieses Blocks werden zum Meldungsfenster in der unteren linken Ecke des expecco-Fensters hinzugefügt. Außerdem werden Sie als Tooltip angezeigt, wenn Sie mit der Maus über den Block fahren.&lt;br /&gt;
&lt;br /&gt;
= Navigation =&lt;br /&gt;
Standardmäßig wird die gesamte Dauer des Laufs im Fenster angezeigt. Sie können aber heranzoomen, um bestimmte Abschnitte besser zu analysieren. Sie können die Menübuttons und die Maus verwenden, um sich auf der Zeitleiste zu bewegen.&lt;br /&gt;
&lt;br /&gt;
== Menüzeile ==&lt;br /&gt;
[[Datei:Timeline_Menubar.png]]&lt;br /&gt;
# Höhe der Zeilen verringern&lt;br /&gt;
# Höhe der Zeilen vergrößern&lt;br /&gt;
# Zeitleiste auf verfügbaren Breite strecken&amp;lt;br&amp;gt;Ein Umschaltknopf: wenn er aktiviert ist, wird die gesamte Laufdauer auf die Breite des Reiters gestreckt.&lt;br /&gt;
# Herauszoomen&amp;lt;br&amp;gt;Die Breite der Zeitleiste verkleinern, sodass mehr Zeit auf weniger Platz dargestellt wird&lt;br /&gt;
# Hineinzoomen&amp;lt;br&amp;gt;Die Breite der Zeitleiste vergrößern, sodass weniger Zeit auf mehr Platz dargestellt wird und besser analysiert werden kann&lt;br /&gt;
# Springe zum Start der ausgewählten Aktion&lt;br /&gt;
# Springe zum Ende der ausgewählten Aktion&lt;br /&gt;
# Relative Ausführungszeiten&amp;lt;br&amp;gt;Die Block-Informationen bspw. im Tooltip zeigen die Startzeit relativ zum Beginn des dargestellten Blocks und die Dauer falls aktiviert, ansonsten absolute Start- und Endzeiten&lt;br /&gt;
&lt;br /&gt;
== Mauseingabe ==&lt;br /&gt;
Normales Scrollen verschiebt das Diagram vertikal, bei gedrückter Shift-Taste horizontal. Durch Scrollen bei gedrückter Strg-Taste können Sie an der Cursorposition zoomen. Falls das Strecken der Zeitleiste deaktiviert ist, können Sie an einem Punkt in der Zeitskala klicken und zu einem anderen ziehen, um einen Zeitabschnitt auszuwählen. Dieser wird dabei gelb markiert. Wenn Sie die Maustaste loslassen, wird die Zeitleiste auf diesen Abschnitt herangezoomt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Timeline_Select_Time.png]]&lt;br /&gt;
&lt;br /&gt;
= Auswählen =&lt;br /&gt;
Wie bereits erwähnt, können Sie einen Block durch Klicken auswählen. Wenn Sie doppelklicken, wird der Block im Baum ausgewählt und die Zeitleiste wechselt zur Darstellung seiner Unterblöcke.&lt;br /&gt;
&lt;br /&gt;
Sie können die Zeitleiste (und gleichzeitig das Netzwerk, die Logdaten und die Ein/Ausgänge) auch auf den ausgewählten Block fixieren, indem Sie den Toggle-Button [[Datei:Timeline_Lock_Button.png]] im Menü des Baums aktivieren. Dies wird durch ein kleines Schloss-Symbol neben dem Eintrag des fixierten Blocks im Baum angezeigt. Wenn Sie nun einen anderen Block im Baum auswählen, wird er in der Zeitleiste des fixierten Blocks ausgewählt. Genauso können Sie auf einen Block in der Zeitleiste doppelklicken und sein Eintrag wird im Baum ausgewählt ohne die angezeigte Zeitleiste zu ändern.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Timeline/en&amp;diff=29085</id>
		<title>Timeline/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Timeline/en&amp;diff=29085"/>
		<updated>2023-12-22T09:02:04Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Introduction */ warning for large logs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Datei:Timeline.png|800px|thumb|Timeline Tab]]&lt;br /&gt;
The Timeline can be a useful tool, when you want to understand the chronology of your test sequence, especially when actions are running in parallel. It can be found in the &#039;&#039;Run&#039;&#039; section of either a testplan or an action block. It uses the information collected in the [[Glossary/en#Activity_Log|Activity Log]] to show when and for how long an action was executed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b style=&amp;quot;color:red&amp;quot;&amp;gt;This feature is still experimental in expecco&amp;amp;nbsp;23.2 and may reach its limits with large logs or while running.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Representation =&lt;br /&gt;
The timeline shows the subblocks of the selected block as bars in the color of their execution state, where their length and horizontal position represents the duration and start time of their execution. The timescale at the top adapts to the presented time. You see the current time format in the top right corner, e.g. &#039;&#039;m:s&#039;&#039; means minutes and seconds separated by a colon, where the seconds may have digits after the decimal point to show the milliseconds.&lt;br /&gt;
&lt;br /&gt;
Initially only the top blocks of the selected blocks are shown. If blocks are executed in parallel, they go in different lines, consecutive blocks are in one line. However, if two blocks are one after the other in the same line, that does NOT indicate, that the first block triggered the second.&lt;br /&gt;
&lt;br /&gt;
You can expand blocks, to see its subblocks. If a block is wide enough, it shows a little expand icon in its left corner. You can expand or collapse the block by clicking on this icon. Alternatively, you can right click on a block and select expand or collapse from its context menu. The subblocks are displayed below their parent block, pushing any parallel block further down in the diagram. The frame of a block includes its subblocks, visualizing the nesting. If you hold Ctrl when expanding a block, it will expand all of its children. As the timeline only displays the information from the Activity Log, you can only see the blocks, that have an log entry. You cannot see blocks, that are skipped in the log.&lt;br /&gt;
&lt;br /&gt;
If you click on a block in the timeline it gets selected, which is indicated by a red frame. The main information of that block is added to the messages in the lower left corner of the expecco window. You also get this information as tooltip when hovering over a block.&lt;br /&gt;
&lt;br /&gt;
= Navigation =&lt;br /&gt;
As default the whole duration is displayed in the panel, but you can zoom in, to better see a certain section. You can use the buttons of the menu bar to navigate through the timeline and use the mouse.&lt;br /&gt;
&lt;br /&gt;
== Menu bar ==&lt;br /&gt;
[[Datei:Timeline_Menubar.png]]&lt;br /&gt;
# Decrease the height of lines&lt;br /&gt;
# Increase the height of lines&lt;br /&gt;
# Stretch the timeline to the available width&amp;lt;br&amp;gt;This is a toggle, if it is on, the whole run time is stretched to the width of the panel.&lt;br /&gt;
# Zoom out&amp;lt;br&amp;gt;Decrease the width of the timeline, so that more time is shown in less space.&lt;br /&gt;
# Zoom in&amp;lt;br&amp;gt;Increase the width of the timeline, so that less time is shown in more space and can be analyzed better.&lt;br /&gt;
# Jump to the start of the selected action&lt;br /&gt;
# Jump to the end of the selected action&lt;br /&gt;
# Relative execution times&amp;lt;br&amp;gt;The block information e.g. in the tooltip shows the start time relative to the start time of the displayed block and the duration if on, or the absolute start and end time if off.&lt;br /&gt;
&lt;br /&gt;
== Mouse Input ==&lt;br /&gt;
Normal scrolling moves the diagram vertically, scrolling with the Shift key held down moves it horizontally. You can zoom in and out on the cursor position by scrolling while holding down the Ctrl key. If stretch is disabled, you can click at a point in the timescale and drag to another to select a time period, which is highlighted in yellow. When you release the mouse button, the timeline zooms to that period.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Timeline_Select_Time.png]]&lt;br /&gt;
&lt;br /&gt;
= Selecting =&lt;br /&gt;
As earlier already mentioned, you can select a block by clicking on it. When double clicking on it, it gets selected in the tree and so the timeline will switch to only display the subblocks of this block.&lt;br /&gt;
&lt;br /&gt;
You can also lock the timeline (and as well the network, log and pin entries) to the block selected in the tree, by activating the toggle [[Datei:Timeline_Lock_Button.png]] in the menu of the tree. This will be indicated by a little lock icon next to the tree icon of the locked block. If you now select another block in the tree, it gets selected in the timeline of the locked block. Similar you can double click on a block in the timeline and its entry in the tree will be selected without changing the displayed timeline.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29084</id>
		<title>Release Notes 23.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29084"/>
		<updated>2023-12-22T08:54:38Z</updated>

		<summary type="html">&lt;p&gt;Matilk: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 22.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 23.2 (December 2023) ==&lt;br /&gt;
*Feature: [[Environment_Editor/en#Fields|Static (Step-) Variables]]&lt;br /&gt;
*Feature: DOM inspector (try an XML attachment) generates better xpath suggestions (alternatives in [[Attachment_Editor/en#XML_Inspector | attachment editor]])&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processors]] are now configurable both for individual test cases and for the overall result of a testplan&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processor]] activities are shown in a testplan&#039;s activity log (but not in a report)&lt;br /&gt;
*Feature: Qt-Library: New Action &#039;&#039;QButton::Click&#039;&#039;: direct click, not being delegated to a thread&lt;br /&gt;
*Feature: Qt-Testing: ExpeccoTestService library and Inject-Tool for QT5.15.0 and VS2022:  [[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]]&lt;br /&gt;
*Feature: [[Timeline/en|Timeline view]] for the activity log (Still experimental, might reach its limits with too large logs or while running)&lt;br /&gt;
*Feature: more [[Testplan_Editor/en#Execution_Settings | pathname options]] for testplan when generating ELF-per-run result files (in loops)&lt;br /&gt;
*Feature: a new [[Testplan_Editor/en#Execution_Settings | option]] in testplan to skip successful tests when looping&lt;br /&gt;
*Feature: enhanced manual test wizard with the option to execute the manual tests with a mobile device (Android, Apple IOS or Web-Browser) &lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Ruby_Elementary_Blocks |bridged Ruby elementary actions]]&lt;br /&gt;
*Feature: Improvements in the XML inspector (tree popup menu &amp;amp; string search)&lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Python_Elementary_Blocks |bridged Python elementary actions]] can now be cancelled and terminated&lt;br /&gt;
*Feature: Python settings: Reorganize Python paths, export Python bridge code for debugging in external IDE ([[Installing additional Frameworks/en#Python_Installation|Python_Installation]])&lt;br /&gt;
*Feature: improved [[Tools_TestSuiteDifferenceBrowser|difference viewer]] (project and version compare UI)&lt;br /&gt;
*Feature: environment: current value (possibly changed from initial value) is saved in .elf log file&lt;br /&gt;
*Feature: StandardLibrary: additional optional pins for encoding (e.g. #utf8) in &amp;quot;FileStream [ Open For xxxx ]&amp;quot; blocks&lt;br /&gt;
*Feature: Values that cannot be saved in a .elf log file (e.g. web elements) are now saved and restored as UnrestoreableDate instead of nil&lt;br /&gt;
*New Python Version: Delivered installation package for Python 3.11.6&lt;br /&gt;
*Change in the format of .elf log files to store handled error states. Older expecco versions cannot handle this and might have problems to open such a file.&lt;br /&gt;
*Bug Fix: log processor actions were themself added to the log, possibly leading to problems when executed again&lt;br /&gt;
*Bug Fix: time-limited actions with the &#039;&#039;timeLimitOK&#039;&#039; flag set did not trigger the enable output pin.&lt;br /&gt;
*Bug Fix: zip archive view generated wrong name-list if language setting was EN-US (AM/PM from timestamp was interpreted as part of filename)&lt;br /&gt;
*Bug Fix: unicode strings in environment variables could not be stored to CSV files&lt;br /&gt;
*Bug Fix: a cancelled compound action did write to an output pin in certain situations&lt;br /&gt;
&lt;br /&gt;
== Release 23.1 ==&lt;br /&gt;
*Feature: Continue an interrupted test plan (i.e. even in a new expecco session and/or on another machine) &lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Compound_Paths|compound paths]] for embedded elements.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): [[Selenium_WebDriver_Plugin/en#Recorder|Recorder]] shows available windows and the current frame context.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Shadow_Elements|shadow elements]] in the GUI browser and recorder, accessible by compound paths.&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Qt-Versions]])&lt;br /&gt;
*Feature: Expecco Remote Control &amp;amp; Monitoring Service with Web Front-End (App for Android or Apple IOS is available on request) ([[Expecco_Remote_Control_App/en|expecco Mobile Remote App]])&lt;br /&gt;
*Feature: Diagram Editor: default style for new connections (e.g. hidden)&lt;br /&gt;
*Feature: Diagram Editor: shortcut keys for environment-freeze and others&lt;br /&gt;
*Feature: Diagram Editor: connections can be named&lt;br /&gt;
*Feature: User defined menu operations: Activity-Log in case of an error&lt;br /&gt;
*Feature: Zip-Archive viewer/extractor/inspector in [[Attachment_Editor/en#Zip_Archive_Inspector | attachment editor]]&lt;br /&gt;
*Feature: ManualTest actions are now part of the base system; the extra plugin licence is only needed to import Excel test descriptions&lt;br /&gt;
*Feature: Logging with microsecond resolution timestamps now works in Windows (if enabled in the settings) &lt;br /&gt;
*Feature: Support XML report file fetching via the REST interface&lt;br /&gt;
*Feature: PCAN (USB Can-Bus Adapter) is now supported in 64-bit expecco&lt;br /&gt;
*Feature: Folders can pass Tags to new sub-elements (inherit)&lt;br /&gt;
*Feature: Menu entry to set Test Groups for Tree Elements&lt;br /&gt;
*Standard Library: Warning Dialog with Opt-out option (show only once)&lt;br /&gt;
*FMU/CBridge: [[Functional Mockup Interface | support FMI2 API; partial support for FMI3]]&lt;br /&gt;
*FMU/CBridge: download resources to CBridge (eg. unifmu generated python FMUs work)&lt;br /&gt;
*Fix: nth-root: lost precision when applied to higher than 64bit floats.&lt;br /&gt;
*Fix: LargeFloats rounding was broken&lt;br /&gt;
*Fix: WSDL import with namespace redefinitions&lt;br /&gt;
*New [[Mobile_Testing_Plugin/en#Windows|Mobile Testing Supplement]] for Windows with an option in the installer to add Appium to the Autostart.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29074</id>
		<title>Release Notes 23.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29074"/>
		<updated>2023-12-15T17:10:42Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 23.2 (upcoming) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 22.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 23.2 (upcoming) ==&lt;br /&gt;
*Feature: [[Environment_Editor/en#Fields|Static (Step-) Variables]]&lt;br /&gt;
*Feature: DOM inspector (try an XML attachment) generates better xpath suggestions (alternatives in [[Attachment_Editor/en#XML_Inspector | attachment editor]])&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processors]] are now configurable both for individual test cases and for the overall result of a testplan&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processor]] activities are shown in a testplan&#039;s activity log (but not in a report)&lt;br /&gt;
*Feature: Qt-Library: New Action &#039;&#039;QButton::Click&#039;&#039;: direct click, not being delegated to a thread&lt;br /&gt;
*Feature: Qt-Testing: ExpeccoTestService library and Inject-Tool for QT5.15.0 and VS2022:  [[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]]&lt;br /&gt;
*Feature: [[Timeline/en|Timeline view]] for the activity log&lt;br /&gt;
*Feature: more [[Testplan_Editor/en#Execution_Settings | pathname options]] for testplan when generating ELF-per-run result files (in loops)&lt;br /&gt;
*Feature: a new [[Testplan_Editor/en#Execution_Settings | option]] in testplan to skip successful tests when looping&lt;br /&gt;
*Feature: enhanced manual test wizard with the option to execute the manual tests with a mobile device (Android, Apple IOS or Web-Browser) &lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Ruby_Elementary_Blocks |bridged Ruby elementary actions]]&lt;br /&gt;
*Feature: Improvements in the XML inspector (tree popup menu &amp;amp; string search)&lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Python_Elementary_Blocks |bridged Python elementary actions]] can now be cancelled and terminated&lt;br /&gt;
*Feature: improved [[Tools_TestSuiteDifferenceBrowser|difference viewer]] (project and version compare UI)&lt;br /&gt;
*Feature: environment: current value (possibly changed from initial value) is saved in .elf log file&lt;br /&gt;
*Feature: StandardLibrary: additional optional pins for encoding (e.g. #utf8) in &amp;quot;FileStream [ Open For xxxx ]&amp;quot; blocks&lt;br /&gt;
*Feature: Values that cannot be saved in a .elf log file (e.g. web elements) are now saved and restored as UnrestoreableDate instead of nil&lt;br /&gt;
*New Python Version: Delivered installation package for Python 3.11.6&lt;br /&gt;
*Change in the format of .elf log files to store handled error states. Older expecco versions cannot handle this and might have problems to open such a file.&lt;br /&gt;
*Bug Fix: log processor actions were themself added to the log, possibly leading to problems when executed again&lt;br /&gt;
*Bug Fix: time-limited actions with the &#039;&#039;timeLimitOK&#039;&#039; flag set did not trigger the enable output pin.&lt;br /&gt;
*Bug Fix: zip archive view generated wrong name-list if language setting was EN-US (AM/PM from timestamp was interpreted as part of filename)&lt;br /&gt;
*Bug Fix: unicode strings in environment variables could not be stored to CSV files&lt;br /&gt;
*Bug Fix: a cancelled compound action did write to an output pin in certain situations&lt;br /&gt;
&lt;br /&gt;
== Release 23.1 ==&lt;br /&gt;
*Feature: Continue an interrupted test plan (i.e. even in a new expecco session and/or on another machine) &lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Compound_Paths|compound paths]] for embedded elements.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): [[Selenium_WebDriver_Plugin/en#Recorder|Recorder]] shows available windows and the current frame context.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Shadow_Elements|shadow elements]] in the GUI browser and recorder, accessible by compound paths.&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Qt-Versions]])&lt;br /&gt;
*Feature: Expecco Remote Control &amp;amp; Monitoring Service with Web Front-End (App for Android or Apple IOS is available on request) ([[Expecco_Remote_Control_App/en|expecco Mobile Remote App]])&lt;br /&gt;
*Feature: Diagram Editor: default style for new connections (e.g. hidden)&lt;br /&gt;
*Feature: Diagram Editor: shortcut keys for environment-freeze and others&lt;br /&gt;
*Feature: Diagram Editor: connections can be named&lt;br /&gt;
*Feature: User defined menu operations: Activity-Log in case of an error&lt;br /&gt;
*Feature: Zip-Archive viewer/extractor/inspector in [[Attachment_Editor/en#Zip_Archive_Inspector | attachment editor]]&lt;br /&gt;
*Feature: ManualTest actions are now part of the base system; the extra plugin licence is only needed to import Excel test descriptions&lt;br /&gt;
*Feature: Logging with microsecond resolution timestamps now works in Windows (if enabled in the settings) &lt;br /&gt;
*Feature: Support XML report file fetching via the REST interface&lt;br /&gt;
*Feature: PCAN (USB Can-Bus Adapter) is now supported in 64-bit expecco&lt;br /&gt;
*Feature: Folders can pass Tags to new sub-elements (inherit)&lt;br /&gt;
*Feature: Menu entry to set Test Groups for Tree Elements&lt;br /&gt;
*Standard Library: Warning Dialog with Opt-out option (show only once)&lt;br /&gt;
*FMU/CBridge: [[Functional Mockup Interface | support FMI2 API; partial support for FMI3]]&lt;br /&gt;
*FMU/CBridge: download resources to CBridge (eg. unifmu generated python FMUs work)&lt;br /&gt;
*Fix: nth-root: lost precision when applied to higher than 64bit floats.&lt;br /&gt;
*Fix: LargeFloats rounding was broken&lt;br /&gt;
*Fix: WSDL import with namespace redefinitions&lt;br /&gt;
*New [[Mobile_Testing_Plugin/en#Windows|Mobile Testing Supplement]] for Windows with an option in the installer to add Appium to the Autostart.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29073</id>
		<title>Release Notes 23.x</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Release_Notes_23.x&amp;diff=29073"/>
		<updated>2023-12-14T13:57:18Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Release 23.2 (upcoming) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also: [[Release Notes 22.x]]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Release 23.2 (upcoming) ==&lt;br /&gt;
*Feature: [[Environment_Editor/en#Fields|Static (Step-) Variables]]&lt;br /&gt;
*Feature: DOM inspector (try an XML attachment) generates better xpath suggestions (alternatives in [[Attachment_Editor/en#XML_Inspector | attachment editor]])&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processors]] are now configurable both for individual test cases and for the overall result of a testplan&lt;br /&gt;
*Feature: [[Testplan_Editor/en#Log_Processor_Action|log processor]] activities are shown in a testplan&#039;s activity log (but not in a report)&lt;br /&gt;
*Feature: Qt-Library: New Action &#039;&#039;QButton::Click&#039;&#039;: direct click, not being delegated to a thread&lt;br /&gt;
*Feature: Qt-Testing: ExpeccoTestService library and Inject-Tool for QT5.15.0 and VS2022:  [[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Delivered versions for QT and build environment]]&lt;br /&gt;
*Feature: [[Timeline/en|Timeline view]] for the activity log&lt;br /&gt;
*Feature: more [[Testplan_Editor/en#Execution_Settings | pathname options]] for testplan when generating ELF-per-run result files (in loops)&lt;br /&gt;
*Feature: a new [[Testplan_Editor/en#Execution_Settings | option]] in testplan to skip successful tests when looping&lt;br /&gt;
*Feature: enhanced manual test wizard with the option to execute the manual tests with a mobile device (Android, Apple IOS or Web-Browser) &lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Ruby_Elementary_Blocks |bridged Ruby elementary actions]]&lt;br /&gt;
*Feature: Improvements in the XML inspector (tree popup menu &amp;amp; string search)&lt;br /&gt;
*Feature: [[Expecco_API/en#Bridged_Python_Elementary_Blocks |bridged Python elementary actions]] can now be cancelled and terminated&lt;br /&gt;
*Feature: improved [[Tools_TestSuiteDifferenceBrowser|difference viewer]] (project and version compare UI)&lt;br /&gt;
*Feature: environment: current value (possibly changed from initial value) is saved in .elf log file&lt;br /&gt;
*Feature: StandardLibrary: additional optional pins for encoding (e.g. #utf8) in &amp;quot;FileStream [ Open For xxxx ]&amp;quot; blocks&lt;br /&gt;
*Feature: Values that cannot be saved in a .elf log file (e.g. web elements) are now saved and restored as UnrestoreableDate instead of nil&lt;br /&gt;
*New Python Version: Delivered installation package for Python 3.11.6&lt;br /&gt;
*Bug Fix: log processor actions were themself added to the log, possibly leading to problems when executed again&lt;br /&gt;
*Bug Fix: time-limited actions with the &#039;&#039;timeLimitOK&#039;&#039; flag set did not trigger the enable output pin.&lt;br /&gt;
*Bug Fix: zip archive view generated wrong name-list if language setting was EN-US (AM/PM from timestamp was interpreted as part of filename)&lt;br /&gt;
*Bug Fix: unicode strings in environment variables could not be stored to CSV files&lt;br /&gt;
*Bug Fix: a cancelled compound action did write to an output pin in certain situations&lt;br /&gt;
&lt;br /&gt;
== Release 23.1 ==&lt;br /&gt;
*Feature: Continue an interrupted test plan (i.e. even in a new expecco session and/or on another machine) &lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Compound_Paths|compound paths]] for embedded elements.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): [[Selenium_WebDriver_Plugin/en#Recorder|Recorder]] shows available windows and the current frame context.&lt;br /&gt;
*Feature: Webtest (Selenium WebDriver): Support of [[Selenium_WebDriver_Plugin/en#Shadow_Elements|shadow elements]] in the GUI browser and recorder, accessible by compound paths.&lt;br /&gt;
*Feature: Qt-Plugin supports Qt6 ([[QT_Testing/en#ExpeccoTestService_Library%3A_Delivery_in_Expecco_Versions|Qt-Versions]])&lt;br /&gt;
*Feature: Expecco Remote Control &amp;amp; Monitoring Service with Web Front-End (App for Android or Apple IOS is available on request) ([[Expecco_Remote_Control_App/en|expecco Mobile Remote App]])&lt;br /&gt;
*Feature: Diagram Editor: default style for new connections (e.g. hidden)&lt;br /&gt;
*Feature: Diagram Editor: shortcut keys for environment-freeze and others&lt;br /&gt;
*Feature: Diagram Editor: connections can be named&lt;br /&gt;
*Feature: User defined menu operations: Activity-Log in case of an error&lt;br /&gt;
*Feature: Zip-Archive viewer/extractor/inspector in [[Attachment_Editor/en#Zip_Archive_Inspector | attachment editor]]&lt;br /&gt;
*Feature: ManualTest actions are now part of the base system; the extra plugin licence is only needed to import Excel test descriptions&lt;br /&gt;
*Feature: Logging with microsecond resolution timestamps now works in Windows (if enabled in the settings) &lt;br /&gt;
*Feature: Support XML report file fetching via the REST interface&lt;br /&gt;
*Feature: PCAN (USB Can-Bus Adapter) is now supported in 64-bit expecco&lt;br /&gt;
*Feature: Folders can pass Tags to new sub-elements (inherit)&lt;br /&gt;
*Feature: Menu entry to set Test Groups for Tree Elements&lt;br /&gt;
*Standard Library: Warning Dialog with Opt-out option (show only once)&lt;br /&gt;
*FMU/CBridge: [[Functional Mockup Interface | support FMI2 API; partial support for FMI3]]&lt;br /&gt;
*FMU/CBridge: download resources to CBridge (eg. unifmu generated python FMUs work)&lt;br /&gt;
*Fix: nth-root: lost precision when applied to higher than 64bit floats.&lt;br /&gt;
*Fix: LargeFloats rounding was broken&lt;br /&gt;
*Fix: WSDL import with namespace redefinitions&lt;br /&gt;
*New [[Mobile_Testing_Plugin/en#Windows|Mobile Testing Supplement]] for Windows with an option in the installer to add Appium to the Autostart.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29049</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29049"/>
		<updated>2023-11-30T14:55:59Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* WebDriverAgent-Signierung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000$nbsp;ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29048</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29048"/>
		<updated>2023-11-30T11:57:56Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Signing WebDriverAgent */ wdaLaunchTimeout&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
With the &#039;&#039;Mobile Testing Plugin&#039;&#039; applications can be tested on Android and iOS devices. This includes both real and emulated devices. It does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; startChromedriverTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
Once the WebDriverAgent is installed on the device, it will be reused for later connections und connecting should work faster. The signed version is then already on your Mac as well and doesn&#039;t have to be built again. This should speed up the connect with other devices as well. If you know, that the connect has to build and sign the WebDriverAgent first, it is advisable to set the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;. This timeout specifies how long Appium waits for the WebDriverAgents to start up on the device and is per default set to 60000&amp;amp;nbsp;ms. Building often takes a little longer than one minute, so the connect attempt will be canceled. A value of 120000 will be more reliable here.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29047</id>
		<title>Mobile Testing Plugin/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin/en&amp;diff=29047"/>
		<updated>2023-11-30T11:45:33Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Problems and Solutions */ first iOS connect&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Mobile_Testing_Plugin|Deutsche Version]] | &#039;&#039;&#039;English Version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
With the &#039;&#039;Mobile Testing Plugin&#039;&#039; applications can be tested on Android and iOS devices. This includes both real and emulated devices. It does not matter whether real mobile devices or emulated devices are used. The plugin can (and usually is) used in conjunction with the [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]], which supports the creation of tests. It can also be used to record test procedures.&lt;br /&gt;
&lt;br /&gt;
[http://appium.io/ Appium] is used to connect to the devices. Appium is a free open source framework for testing and automating mobile applications.&lt;br /&gt;
&lt;br /&gt;
We recommend to go through the [[Mobile_Testing_Tutorial/en|Tutorial]] to familiarize yourself with the Mobile Plugin. This tutorial leads step by step through the creation of a test case using an example and explains the necessary basics.&lt;br /&gt;
&lt;br /&gt;
= Installation and Setup =&lt;br /&gt;
To use the &#039;&#039;Mobile Testing Plugin&#039;&#039;, you must have installed expecco together with the corresponding plugin, and you need the appropriate licenses. expecco communicates with the mobile devices via an Appium server, which either runs on the same computer as expecco, or on a second computer. This must be accessible for expecco.&lt;br /&gt;
&lt;br /&gt;
== Installation Overview ==&lt;br /&gt;
&#039;&#039;&#039;Computer running expecco:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to Android devices :&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement (see below), of which we regularly provide a new version&lt;br /&gt;
* Android SDK, you can also get it with the Mobile Testing Supplement&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
&#039;&#039;&#039;Computer connected to iOS devices&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium Server, you can install it via the Mobile Testing Supplement for MacOS (see below), of which we regularly provide a new version&lt;br /&gt;
* Xcode in a version that supports the iOS version used, available from the Apple App Store&lt;br /&gt;
* Java JDK version 8, 9, 10 or 11&lt;br /&gt;
* Apple Developer Certificate incl. matching private key (to sign the WebDriverAgent)&lt;br /&gt;
* Provisioning Profile for the mobile devices to be used&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; Please note that due to the requirements (no connection to non-Apple devices available) iOS devices can only be controlled from a Mac.&lt;br /&gt;
&lt;br /&gt;
Depending on the setup, the above-mentioned computers can also be the same device. expecco can either connect to a remote Appium Server and mobile devices connected to it via the network, or start an Appium Server locally itself and use it with local mobile devices. However, some of expecco&#039;s functions that make it easier to create test cases are only available if the mobile devices are connected to the same computer on which expecco is running. A possible setup may therefore look like the following figure:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
The following explains how to install Appium and other necessary applications for Windows and Mac OS.&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
The easiest way is to install everything from our Mobile Testing Supplement. However, newer versions do not contain a JDK anymore due to a change in Oracle&#039;s license terms, so you have to install it additionally. Of course, you are free to install Appium directly to use the version you want. However, to then be able to start an Appium server with expecco, a suitable batch file must be available and specified in the [[Mobile_Testing_Plugin/en#Plugin_Configuration|settings]]. However, connections can also be established to other running Appium servers.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Same versions as in the predecessor, but the installer now allows to add Appium to the Autostart.&lt;br /&gt;
*expecco 22.2 and 22.1: [https://download.exept.de/transfer/h-expecco-22.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 from platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* We added the capability&#039;&#039; startChromedriverTimeout &#039;&#039;to Appium, to get a timeout earlier, if Chromedriver cannot be initialized. (see [[#startChromedriverTimeout|Problems and Solutions]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Contains Appium version 1.22.0, Node still is version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Only minor changes compared to the previous version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Compared to the previous version, Appium was updated to version 1.16.0-rc.1 and node 12 is used. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:This installs Appium in the version 1.12.0 and now additionally contains build-tools in the version 28.0.3 in the android-sdk. Apart from this, it is the same as the previous version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:This installs Appium in the version 1.8.1. In addition, an installation of &#039;&#039;Android Debug Bridge&#039;&#039; and &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) is offered. This covers drivers for a broad range of Android devices, and you won&#039;t have to install an individual driver for each device. A &#039;&#039;&#039;JDK is not contained anymore (due to a change in Oracle&#039;s license terms)&#039;&#039;&#039;, you have to download it on your own, e.g. from [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: same procedure as for expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:This installs a Java JDK Version 8, android-sdk and Appium Version 1.6.4. The supplement also offers a universal adb driver ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]). This driver supports a wide range of Android Devise, and avoids the need to search for individual device-specific drivers.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:It installs a Java JDK version 8, android-sdk and Appium version 1.4.16. During the installation the graphical user interface of Appium is started, you can close this window immediately. The supplement also offers a universal adb driver (ClockworkMod). This combines drivers for a wide range of Android devices so that you do not have to search for and install a separate driver for each device.&lt;br /&gt;
&lt;br /&gt;
If expecco has to use mobile devices that are connected to another computer, you have to start an Appium server there. You can do this by using the file &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt;. The server is then started on default port 4723. If you want to use a different port number, start the server with&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The server is ready, as soon as the line&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
is displayed, where you can read the used port number at the end.&lt;br /&gt;
&lt;br /&gt;
If your Android device is connected to a remote machine,&lt;br /&gt;
you may want to see the live screen locally using a tool like&lt;br /&gt;
[https://github.com/Genymobile/scrcpy scrcpy].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When Appium is started for the first time – either standalone or by expecco – it may happen that the Windows firewall blocks access to the node server. Allow the access or Appium cannot be started.&lt;br /&gt;
&lt;br /&gt;
== Mac OS ==&lt;br /&gt;
Note: the following can be ignored if you do not plan to test iOS (iPhone) devices. The Mac setup is not needed for Android devices.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Automation with iOS devices needs [https://developer.apple.com/xcode/ Xcode]. You can install it from the App Store. Please make sure that the version matches the tested iOS versions.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
This table is only a simplified overview, better see [https://xcodereleases.com/ Xcode releases] or [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode versions] for the exact versions. For new iOS minor versions, there is usually also a new release of Xcode, e.g. for iOS 10.2 you need at least Xcode 8.2, for iOS 10.3 at least Xcode 8.3, etc. So if you are upgrading to a newer iOS version, you will usually need a newer Xcode version as well. Newer versions of Xcode may not run on older operating systems, which in turn may require an operating system upgrade. If you also want to test older iOS versions, it can be useful to install the corresponding Xcode versions in parallel.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
You can install Appium either as command-line tool or use it with [https://github.com/appium/appium-desktop Appium Desktop], which provides a GUI to start the server. Meanwhile there is also Appium 2.0, which is not tested with expecco yet and therefore not recommended to use.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Download the newest version of [https://github.com/appium/appium-desktop/releases/ Appium Desktop]. For the Mac, it is best to take the dmg file and install it to the applications. When starting &#039;&#039;Appium Server GUI&#039;&#039; you will probably get the error message, that it is not possible for security reasons. In this case, open the context menu of the app file (right click or Ctrl + click) and choose &#039;&#039;Open&#039;&#039; there. Then confirm that you really want to open the application. From now on you can open the application normally.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Since Xcode 14 there are problems with signing the WebDriverAgent, which Appium loads on the device for the automation. This means that no connection is possible with version 1.22.3-4 of Appium Desktop. In newer versions of WebDriverAgent, this problem is solved, but currently there is no version of Appium Desktop using such a new version (as of November 2022). However, you can manually download a new version (e.g. 4.10.2) and replace the files in Appium. To do this, download one of the two archive files (zip or tar.gz) containing the source code from the [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent download page]. Then open and extract this file. Copy the contents of the folder &#039;&#039;WebDriverAgent-4.10.2&#039; to&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
If you navigate there by Finder, make a context click (right click or Ctrl + click) on the application and choose &#039;&#039;Show Package Contents&#039;&#039; from the menu. Replace all files that are already present with the same name.&lt;br /&gt;
&lt;br /&gt;
==== Install Appium using npm ====&lt;br /&gt;
You can install Appium using npm (Node Package Manager) as well. To do this, you have to install node/npm first. This can be done using [https://github.com/nvm-sh/nvm nvm] (Node Version Manager), which you can get on Github. If the following installation instructions should not work for you, you will find detailed information in the [https://github.com/nvm-sh/nvm#readme Readme] there.&lt;br /&gt;
&lt;br /&gt;
Open a Terminal window. Then clone the Github repository of nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
and load it&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Then execute&lt;br /&gt;
 command -v nvm&lt;br /&gt;
to see if it works. It should print &#039;&#039;nvm&#039;&#039;. If there is no response, execute&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
and try again.&lt;br /&gt;
&lt;br /&gt;
Now you can install node with the following command.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
As there are problems installing Appium using the newest version of node, we recommend this version.&lt;br /&gt;
&lt;br /&gt;
After node is installed, you can use it to install Appium:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
The Appium server now simply can be started with the command&lt;br /&gt;
 appium&lt;br /&gt;
The output will then be written directly to the terminal.&lt;br /&gt;
&lt;br /&gt;
This version also has problems with signing the WebDriverAgent, like explained in [[#Appium_Desktop | Appium Desktop]]. Therefore download a newer version of WebDriverAgent in this case as well and replace the old files. You will find them at&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
We provide older versions of Appium via the Mobile Testing Supplement for Mac OS, with which you can easily install it:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.2)]&lt;br /&gt;
:Contains Appium version 1.18.3 and uses node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement for Mac OS (1.2.0)]&lt;br /&gt;
:Only a few changes compared to the previous version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.98)]&lt;br /&gt;
:Appium is updated to version 1.16.0-rc.1 and node 12 is used.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.96)]&lt;br /&gt;
:This version contains Appium 1.12.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.1.94)]&lt;br /&gt;
:This version contains Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11:[http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement for Mac OS (1.0.94)]&lt;br /&gt;
:This version contains Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement for Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
After you have downloaded the supplement, you can move it to a directory of your choice (e.g. your home directory) and unpack it there. A suitable command in a shell could look like this, adjust the version number accordingly:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
If your default Xcode installation is the one you want to use, you can start Appium directly from the file in the &#039;&#039;bin&#039;&#039; directory with the appropriate version number:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
If you want to use another Xcode than the one configured as default, you have to tell Appium the corresponding path by using the environment variable &#039;&#039;DEVELOPER_DIR&#039;&#039;. For example, if you have installed Xcode in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039;, you can start Appium this way:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
To find out what is set as the default Xcode installation on your system, use this command:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
If Appium cannot find your Xcode installation, a message like this appears:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
In such a case, restart Appium by specifying a valid &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Signing WebDriverAgent ====&lt;br /&gt;
For automation, Appium installs an App called WebDriverAgent on the device and therefore has to be able to sign it. You need an Apple account and a respective certificate for this. For evaluation you can use a free account. This has the disadvantage that created profiles are only valid for one week and must be recreated afterwards. Also be careful when sharing the account, as certificates may be revoked or invalidated by automatic generation. As a result, apps that have already been signed can no longer be used.&lt;br /&gt;
&lt;br /&gt;
If you already have a respective certificate and its associated private key in your keychain on the Mac, you can have the WebDriverAgent automatically signed. If not, it is recommended to set and manage the signing using Xcode.&lt;br /&gt;
&lt;br /&gt;
First, connect the device you want to use to your Mac via USB. Make sure both the Mac and the device are in the same network or there will be problems when connection with Appium. Start Xcode and open &#039;&#039;Preferences&#039;&#039;. Go to the Accounts page and create an entry with your account. You can then click on &#039;&#039;Manage Certificates...&#039;&#039; to see the certificates that belong to that account. To run tests, you need an iOS Development Certificate and the associated private key. If you do not already have one, create one. If you already have one, but it is not in your keychain (indicated by &amp;quot;Not in Keychain&amp;quot;), you can import it. You can do that by the [https://support.apple.com/en-us/guide/keychain-access/welcome/mac keychain access] on your Mac, if you have exported it previously from the keychain, where it is stored. The certificate with the associated key should be in the keychain &#039;&#039;Login&#039;&#039;. It can be exported from there as PKCS#12 file (typical ending .p12). To import a certificate into your keychain, select the option &#039;&#039;Import objects&#039;&#039; from the &#039;&#039;File&#039;&#039; menu. If you don&#039;t know where the certificate is stored, you can also revoke it in Xcode and recreate it in your keychain. However, only do this if you know that the old certificate is no longer in use because it can no longer be used afterwards. Now the keychain should contain an iOS development certificate.&lt;br /&gt;
&amp;lt;!--(Den folgenden Teil braucht man wohl nicht mehr, wenn es in Xcode eingestellt ist)From the right-click menu, select Information. Under the details of the certificate you will find the Team ID, which is referred to here as the Organizational Unit. Enter it in the Team ID field of the plug-in&#039;s settings, see [[#Plugin_Configuration|Plugin Configuration]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now open the WebDriverAgent project in Xcode. If you have installed the Mobile Testing Supplement, you will find it in this directory at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
If you have installed Appium Desktop, you will find it at&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can use the Finder to navigate to the Xcode project file and open it by double clicking. Note, that you have to perform a context click (right click or Ctrl + click) on the Appium Server GUI app and select &#039;&#039;Show Package Contents&#039;&#039; in the menu, to get to its subdirectory.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Select &#039;&#039;WebDriverAgentLib&#039;&#039; and the page &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039;. In the section &#039;&#039;Signing&#039;&#039; set the option &#039;&#039;Automatically manage signing&#039;&#039; and then select a team. Now switch to &#039;&#039;WebDriverAgentRunner&#039;&#039; and do the same there.&lt;br /&gt;
&amp;lt;!-- (The following seems to not be relevant anymore.) Here you should see errors indicating that no Provisioning Profiles have been created or found. Therefore, go to the &#039;&#039;Build Settings&#039;&#039; page and look for the entry &#039;&#039;Product Bundle Identifier&#039;&#039; in the &#039;&#039;Packaging&#039;&#039; section. Change this from com.facebook.WebDriverAgentRunner to something Xcode accepts by changing the prefix. Xcode can now generate a matching Provisioning Profile and the errors on the General page should disappear. After that you can quit Xcode. --&amp;gt;&lt;br /&gt;
By setting the team, the errors showing up for WebDriverAgentRunner should disappear. If Xcode should not be able to create a Provisioning Profile matching the Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039;, you can edit the latter so that it fits your certificate. After that you can quit Xcode or you can, like explained further below, directly start the build in Xcode, so the project will be already built when Appium wants to use it.&lt;br /&gt;
&lt;br /&gt;
If you now connect to your device from expecco, the WebDriverAgent will be installed and started on it and then switch to the app to be tested. You may still have to trust the execution of the WebDriverAgent on the device. It maybe a sign that you have to do this, if the app WebDriverAgent first appears on the device and tries to start, but then is uninstalled again. To trust the execution, open the settings during the connection setup on the device and then the entry &#039;&#039;Device management&#039;&#039; under &#039;&#039;General&#039;&#039;. This entry is only visible if a developer app is installed on the device. You may therefore have to wait until the WebDriverAgent is installed before the entry appears. Select the entry of your Apple account and trust it. Since the WebDriverAgent will be uninstalled again if the start did not work, you have to do this during the connection setup. If this is too hectic for you, you can also execute the following code:&lt;br /&gt;
&lt;br /&gt;
 xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
or&lt;br /&gt;
 xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
This installs the WebDriverAgent on the device without deleting it again.&lt;br /&gt;
&lt;br /&gt;
If there are problems while installing the WebDriverAgent, you can also try and start the build in Xcode. Make sure the right target &#039;&#039;WebDriverAgent&#039;&#039; is selected. Error messages in Xcode might indicate easier what the problem is about. Sometimes it even helps to try for a second time, if it took too long for the first time and got aborted. It may occur, that you are asked several times during the build to enter the password for the keychain.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Read also the documentation of Appium on [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Setting up tests with iOS devices]. Refer to the [https://support.apple.com/en-us/HT204460 Apple documentation] for details on installing and trusting of apps.&lt;br /&gt;
&lt;br /&gt;
== Plugin Configuration ==&lt;br /&gt;
Before you start, please check the settings of the Mobile Testing Plugin and adjust them if necessary. Select the menu item &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;amp;#8594; &amp;quot;&#039;&#039;Extensions&#039;&#039;&amp;quot; &amp;amp;#8594;  &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (see fig.). By default, these paths are found automatically (1). To adjust a path manually, deactivate the corresponding check mark at the right. You&#039;ll see a drop-down list with some paths to choose from. If an entered path is wrong or cannot be found, the field is marked red and a message appears. Make sure that all paths are specified correctly.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Plugin Configuration]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Enter the path to the executable file with which Appium can be started in the command line. Under Windows this file will usually be called &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot;. This path is used when expecco starts an Appium server.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Enter the path to the executable that starts Node (also called (also called &amp;quot;Node.js&amp;quot;). This path is passed to Appium when a server is started so that Appium can find it independently of the PATH variable. Under Windows this file is usually called &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Enter the path to a JDK (Java Development Kit)here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable. To specify which Java should be used by expecco, set this path in the Java Bridge settings.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Enter the path to an Android SDK here. This path is passed to each Appium server. Leave the field blank to use the value from the environment variable.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: The path to the adb command. Under Windows the file is called &amp;quot;&amp;lt;code&amp;gt;adb.exe&amp;lt;/code&amp;gt;&amp;quot;. This file is used by expecco, for example, to get the list of connected devices. This path should be selected automatically, if the command is found in the ANDROID_HOME directory. This is also used by Appium. If expecco and Appium use different versions of adb, conflicts may occur.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: This file is only needed to start the AVD and the SDK Manager, which deal with phone emulators. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: The path to the &amp;quot;aapt&amp;quot; command here. Under Windows this file is called &amp;quot;&amp;lt;code&amp;gt;aapt.exe&amp;lt;/code&amp;gt;&amp;quot;. expecco uses &amp;quot;aapt&amp;quot; only in the connection editor to read the package and activities of an &amp;quot;apk&amp;quot; file. The file in the ANDROID_HOME directory will be selected automatically, if present there.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | JDK Configuration]]&lt;br /&gt;
&lt;br /&gt;
Starting with expecco 2.11, there is an additional field called &#039;&#039;Team ID&#039;&#039;. If you run iOS tests, enter the Team ID of your certificate here. This is used for every iOS connection, unless you change the value in the connection settings in individual cases. For information on how to obtain the team ID, please refer to the section on [[#Signing| signing]] for installations on Mac OS. With expecco 2.10 and older, you can only enter the Team ID as capability for each connection setting separately. However, you must use the [[#Extended_View|extended view]] to do this. Enter the capability &#039;&#039;xcodeOrgId&#039;&#039; here and set the Team ID of the certificate as value.&lt;br /&gt;
&lt;br /&gt;
The server address setting at the bottom of the page refers to the behavior of the connection editor. It checks at the end whether the server address ends in &#039;&#039;/wd/hub&#039;&#039; as this is the usual form. If not, a dialog asks how to react. The defined behavior can be viewed and changed here.&lt;br /&gt;
&lt;br /&gt;
Also switch to the entry &#039;&#039;Java Bridge&#039;&#039; (see figure). Here you have to specify the path to your Java installation, which is used by expecco. Enter a JDK here. If you want to use the one from the Mobile Testing Supplement under Windows, the path is&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
You can also use the system settings.&lt;br /&gt;
&lt;br /&gt;
== Prepare Android Device ==&lt;br /&gt;
If you connect an Android device under Windows, you may still need an adb driver for the device. You can usually find a suitable driver on the manufacturer&#039;s website. If you have installed the universal driver from the Mobile Testing Supplement, everything should already work for most devices. In some cases, Windows will automatically try to install a driver when you connect the device for the first time. &amp;lt;br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Attention&#039;&#039;&#039;: Before you can control a mobile device with the Appium plugin, you have to allow this debugging!&lt;br /&gt;
&lt;br /&gt;
For Android devices, you can find this option in the settings under &#039;&#039;[https://developer.android.com/studio/debug/dev-options Developer Options]&#039;&#039; called &#039;&#039;USB-Debugging&#039;&#039;. If the developer options are not displayed, you can unlock them by tapping Build Number seven times in About the Phone.&lt;br /&gt;
&lt;br /&gt;
Also enable the &#039;&#039;Stay awake&#039;&#039; feature to prevent the device from turning off the screen during test creation or execution.&lt;br /&gt;
&lt;br /&gt;
For security reasons, USB debugging must be allowed for each computer individually. When connecting the device to the PC via USB, you must agree to the connection on the device. If you haven&#039;t done this for your computer yet, but no corresponding dialog appears on the device, it may help to unplug and reconnect the device. This can happen especially if you have installed the ADB driver while the device was already connected via USB. If this doesn&#039;t help either, open the notifications by dragging them from the top of the screen. There you will find the USB connection and you can open the options. Select another type of connection; usually MTP or PTP should work.&lt;br /&gt;
&lt;br /&gt;
You can also test on an emulator. It does not need to be prepared separately, as it is already designed for USB debugging. It is even possible to start an emulator at the beginning of the test.&lt;br /&gt;
&lt;br /&gt;
To check if a device you have connected to your computer can be used, open the [[#Connection_Editor|connection editor]]. The device should be displayed there.&lt;br /&gt;
&lt;br /&gt;
=== Connection via WLAN ===&lt;br /&gt;
It is possible to connect to Android devices via Wireless LAN. For devices using Android 11 or newer, this can be done wirelessly, else you have to connect initially via USB. Since expecco 22.1, WiFi connections can be established using the [[Mobile_Testing_Plugin/en#Connection_Editor|Connection Editor]]. It is also possible to do this using a command window.&lt;br /&gt;
==== Wireless Connect (Android 11) ====&lt;br /&gt;
In the developer options of your device, enable wireless debugging and open its options. You initially have to pair your machine with the device. To do this, choose &amp;quot;&#039;&#039;Pair device with pairing code&#039;&#039;&amp;quot; to get a pairing code and an IP address with port. Then open a command window (terminal window) on your machine and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
where &amp;lt;tt&amp;gt;&amp;lt;Device IP Address&amp;gt;:&amp;lt;Pairing Port&amp;gt;&amp;lt;/tt&amp;gt; is the IP address and port as shown on the device. After that, you will be asked for the pairing code. If everything went right, the popup on the device should have closed and your machine is added to the list of paired devices. Then enter at the command window:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;Device IP Address&amp;gt;:&amp;lt;Debugging Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The IP address is the same as for pairing, but the port is different. Both are shown as IP address &amp;amp; Port on the device. The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted. Restarting the device often disables wireless debugging and the used port is changed. The pairing, however, is permanent and has not to be done again the next time you connect.&lt;br /&gt;
==== Start via USB ====&lt;br /&gt;
First, connect your device via USB. Then open a command window (terminal window) and enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device listens for a TCP/IP connection on port 5555. If you have several devices connected or emulators running, you have to specify which device you mean. Enter in this case:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
to get a list of all devices, where the first column gives the device&#039;s ID.&lt;br /&gt;
Then, enter:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;deviceID&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
with the device identification of the desired device. You can now disconnect the USB connection.&amp;lt;br&amp;gt;Now you have to find out the IP address of your device. You can usually find it somewhere in the device&#039;s settings, for example in the Status or WLAN settings of the phone. Then type in:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP address of device&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
The device should now be connected via WLAN and can be used in the same way as with a USB connection. You can check this by entering &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; again or open the connection dialog in expecco. In the list, the device appears with its IP address and port. Remember that the WLAN connection no longer exists when the ADB server or the device is restarted.&lt;br /&gt;
&lt;br /&gt;
== Preparing an iOS-Device and App ==&lt;br /&gt;
Control of iOS devices is only possible via a Mac. Please also read the section [[#Mac_OS|Installation under Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Before you can control a mobile device with the Mobile Testing Plugin, you must allow debugging for iOS devices with iOS 8 or higher. Activate the option &amp;quot;&#039;&#039;Enable UI Automation&#039;&#039;&amp;quot; under the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; menu in the device settings.&amp;lt;br&amp;gt;If you cannot find the &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; entry in the settings, proceed as follows: Connect the device to the Mac via USB. If necessary, you must still agree to the connection on the device. Start Xcode and then select &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot; from the menu bar at the top of the screen in the &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; menu. A window opens in which a list of the connected devices is displayed. Select your device there. Then the entry &amp;quot;&#039;&#039;Developer&#039;&#039;&amp;quot; should appear in the settings on the device. You may have to exit the settings and restart.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Alert unter iOS]]&lt;br /&gt;
It is not possible to establish a connection to the device as long as it shows certain alerts. Such an alert may appear if FaceTime is activated (by displaying a message about SMS charges as shown in the screenshot). Be sure to configure the device so that it does not show such alerts when idle.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 and later ===&lt;br /&gt;
You can test any app which is executable or already installed on the device used. If the app is available as a development build, the UDID of the device must be stored in the app. In any case, the WebDriverAgent must be signed for the device. Please read the section about [[#Signing|signing]] under Mac OS.&lt;br /&gt;
&lt;br /&gt;
If you want to use the Home button in a test, you must activate &amp;quot;AssistiveTouch&amp;quot; on the device. You will find this option in the settings under &amp;quot;&#039;&#039;General&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Operating Help&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;AssistiveTouch&#039;&#039;&amp;quot;. Then place the menu in the middle of the upper edge of the screen. You can then record pressing the Home button with the corresponding menu entry in the recorder or use the &amp;quot;&#039;&#039;Press Home Button&#039;&#039;&amp;quot; block directly.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
The app you want to use must be available as a development build. The UDID of the device must also be stored in the app.&lt;br /&gt;
&lt;br /&gt;
=== Sign the development build ===&lt;br /&gt;
A development build of an app is only allowed for a limited number of devices and cannot be started on other devices. However, it is possible to exchange the certificate and the usable devices in a development build.&lt;br /&gt;
&lt;br /&gt;
* Evaluation with demo app of eXept:&lt;br /&gt;
:We will be happy to provide you with a demo app which is available as a development build and which we can sign for your device. Please send the UDID of your device to your eXept contact person. How to determine the UDID of your device is described in the following section.&lt;br /&gt;
&lt;br /&gt;
* Using your own app for your test device:&lt;br /&gt;
:If you receive a development build (IPA file) from the app developers that is approved for your test device, you can use it directly. To do this, you must tell the developers the UDID of your device so they can enter it. &#039;&#039;&#039;You can use Xcode to read the UDID of a device&#039;&#039;&#039;. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window opens in which a list of the connected devices is displayed. Select your device and search for the &#039;&#039;Identifier&#039;&#039; entry in Properties. The UDID is a 40-digit hexadecimal number.&lt;br /&gt;
&lt;br /&gt;
* Externally developed app for your test device:&lt;br /&gt;
:You can also re-sign apps to make them run on other devices. However, this process is complicated and requires access to an Apple Developer account. A documentation on the procedure is currently in preparation.&lt;br /&gt;
&lt;br /&gt;
:For the evaluation we will gladly support you with the re-signing of your app..&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Log in to the [https://developer.apple.com/ Apple-Webinterface]. Navigate to &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. If necessary, create a Developer Certificate and a Provisioning Profile for your device here and download both. If you don&#039;t have a Developer Account yet, create one here: https://developer.apple.com/enroll/. For this you have to register with an Apple-ID.&lt;br /&gt;
&lt;br /&gt;
# Find out Team ID (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Under &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; select development certificate (under &#039;&#039;+&#039;&#039; create, if not available) and download&lt;br /&gt;
# Under &#039;&#039;App ID&#039;&#039; create Wildcard App ID, if not present. Note App ID (AppID = Prefix.ID)&lt;br /&gt;
# Add device, find out UDID (or &#039;&#039;Identifier&#039;&#039;) of the device (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (above in menu bar) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Create commission profiles: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; Select &#039;&#039;AppID&#039;&#039; -&amp;gt; Select certificate -&amp;gt; Select device -&amp;gt; Create profile name -&amp;gt; Download provisioning profiles.&lt;br /&gt;
# Import the downloaded certificate (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Certificate (.cer)&lt;br /&gt;
# Copy SHA1 fingerprint. Right click on Certificate -&amp;gt; &#039;&#039;Information&#039;&#039;, then scroll to the bottom of the page).&lt;br /&gt;
# Create Entitlements.plist (&#039;&#039;Open Terminal&#039; -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;path to ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Path to Commission Profile (e.g. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Path for the result ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
To re-sign, you can use the corresponding script from the Mobile Testing Supplement for Mac OS or any other tool (e.g. isign).&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For more information about using iOS devices, see also the &lt;br /&gt;
[http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Appium documentation].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
You can also use apps that are already natively present on the device. To do this, you must know their bundle ID and then enter it in the connection settings. Here is a small selection of common apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You can find further Bundle-IDs [https://github.com/joeblau/apple-bundle-identifiers here].&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
In the demo test suites for expecco you will also find examples for tests with the Mobile Testing Plugin. To do this, select the option &amp;quot;&#039;&#039;Example from File&#039;&#039;&amp;quot; on the start screen and open the folder named &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
The test suite contains two simple test plans: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; and &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Both tests use an Android emulator, which you must start before starting. The apps used in the test are part of the basic equipment of the emulator and therefore no longer need to be installed. Since the apps may differ under every Android version, it is important that your emulator runs under Android 6.0. In addition, the language must be set to English.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: This test connects to the calculator and enters the formula &#039;&#039;2+3&#039;&#039;. The result of the calculator is compared with the expected value &#039;&#039;5&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: This test connects to the calculator and then opens the message service. There it waits for an incoming message from the number &#039;&#039;15555215556&#039;&#039;, in which a formula to be calculated is sent. The message is generated before via a socket at the emulator. When the message arrives, it is opened by the test and its contents are read. Then the calculator is opened again, the received formula is entered and the result is read. The test then switches back to the message service and sends the result as an answer.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
These are part of the tutorial for the Mobile Testing Plugin. The included test case is incomplete and will be added during the tutorial. Please read the section [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
There is a tutorial describing the basic procedure for creating tests with the Mobile Testing Plugin. It is based on a supplied example consisting of a simple app and an expecco test suite.&lt;br /&gt;
&lt;br /&gt;
You find it on the page [[Mobile_Testing_Tutorial/en|Mobile Testing Tutorial]] in two versions for Android and iOS devices.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_Android|First steps with Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt; [[Mobile_Testing_Tutorial/en#First_steps_with_iOS|First steps with iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialogs of the Mobile Testing Plugin =&lt;br /&gt;
== Connection Editor ==&lt;br /&gt;
You can use the Connection Editor to quickly define, change, or establish connections. Depending on the task, the dialog has small differences and is opened differently:&lt;br /&gt;
*If you want to establish a connection, access the dialog in the GUI browser by clicking on &#039;&#039;Connect&#039;&#039; and then selecting &#039;&#039;Mobile Testing&#039;&#039;.&lt;br /&gt;
*To change or copy an existing connection in the GUI browser, select it, right-click and select &#039;&#039;Edit Connection&#039;&#039; or &#039;&#039;Copy Connection&#039;&#039; from the context menu.&lt;br /&gt;
*If you do not want to create connection settings for the GUI browser but for use in a test, choose &#039;&#039;Create Connection Settings&#039;&#039; from the Mobile Testing Plugin menu.... This only allows you to create the settings for a connection without creating a connection in the GUI browser.&lt;br /&gt;
&lt;br /&gt;
The Connection Editor menu has several buttons, some of which are only visible when creating connection settings:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&#039;&#039;Delete Settings&#039;&#039;: Resets all entries. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Load settings from file&#039;&#039;: Allows to open a saved settings file (*.csf). Its settings are transferred to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Load settings from attachment&#039;&#039;: Allows you to open an attachment with connection settings from an open project. These settings are applied to the dialog. Entries already made without conflict are retained.&lt;br /&gt;
#&#039;&#039;Save settings to file&#039;&#039; and&lt;br /&gt;
#&#039;&#039;Save settings to attachment&#039;&#039;: Here you can save the entered settings to a file (*.csf) or create them as an attachment in an open project. Both options have a delayed menu in which you can choose to save only a certain part of the settings. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Advanced View&#039;&#039;: Allows you to switch to the advanced view to make additional settings. Read more about this at the end of this chapter. (Only visible when creating settings.)&lt;br /&gt;
#&#039;&#039;Help&#039;&#039;: A help text for the respective step is shown or hidden on the right side.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The dialog is divided into three steps. In the first step you select the device you want to use, in the second step you select which App should be used and in the last step the settings for the Appium server are made.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 1: Select Device ===&lt;br /&gt;
In the upper part you will see a list of all connected Appium devices that are detected. With the checkbox below you can hide devices that are detected but not ready. If you want to enter a device that is not connected, you can create it with the corresponding button &#039;&#039;Enter Android device&#039;&#039; or &#039;&#039;Enter iOS device&#039;&#039;. However, you need to know the required properties of your device. The device is then created in a second device list and can be selected there. If no list with connected elements can be displayed, various messages are displayed instead:&lt;br /&gt;
*No devices found&lt;br /&gt;
*:expecco could not find any Android devices.&lt;br /&gt;
*:To automatically configure a connection to a device, make sure&lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*No available devices found&lt;br /&gt;
*:expecco could not find any available Android devices. But not available ones were found, e.g. with the status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:To configure a connection to a device automatically, make sure that &lt;br /&gt;
*:*it is connected&lt;br /&gt;
*:*it is turned on&lt;br /&gt;
*:*that it has an appropriate adb driver installed&lt;br /&gt;
*:*it is enabled for debugging (see below).&lt;br /&gt;
*:To view unavailable devices, enable this option below.&lt;br /&gt;
*Connection lost&lt;br /&gt;
*:expecco has lost the connection to the adb server. Try to re-establish the connection by clicking on the button.&lt;br /&gt;
*Connection failed&lt;br /&gt;
*:expecco could not connect to the adb server. Possibly it is not running or the specified path is not correct.&lt;br /&gt;
*:Check the adb configuration in the settings and try to start the adb server and establish a connection by clicking on the button.&lt;br /&gt;
*Connect ...&lt;br /&gt;
*:expecco connects to the adb server. This may take a few seconds.&lt;br /&gt;
*Start adb-Server ...&lt;br /&gt;
*:expecco starts the adb-Server. This may take a few seconds.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--With &#039;&#039;Automation by&#039;&#039; you can specify, which automation engine is to be used. If you leave the setting at &#039;&#039;(Default)&#039;&#039; the corresponding capability is not set at all. Otherwise Appium, Selendroid and from expecco 2.11 XCUITest are available. Selendroid is usually only used for Android devices prior to version 4.1.--&amp;gt;With &#039;&#039;Next&#039;&#039; you get to the next step. If you enter settings for the GUI browser, this is only possible once a device has been selected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Note on unlocking&amp;lt;/span&amp;gt;: In newer Android versions the developer options are no longer offered in the settings at first. If your Android device does not show an entry for &amp;quot;&#039;&#039;Developer options&#039;&#039;&amp;quot; in the settings, first select the entry &amp;quot;&#039;&#039;Phone info&#039;&#039;&amp;quot;, then &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; and click on the entry &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot; several times.&lt;br /&gt;
&lt;br /&gt;
==== Manage Chromedrivers ====&lt;br /&gt;
If the App you want to automate uses WebViews with Chrome, Appium needs to have access to an appropriate Chromedriver. If you have selected a device in the list, you can use &amp;quot;&#039;&#039;Manage Chromedrivers&#039;&#039;&amp;quot; to see, which Chrome versions are installed on the device and which Chromedriver versions are provided by expecco. With this dialog you can also download required Chromedriver versions. Beware that there may be several Chrome versions on the device. An App doesn&#039;t have to use the version of the installed Chrome browser for its WebViews. The Chromedriver you use should fit your app for everything to work properly. You can also change the path to the Chromedriver in the capabilities generated at the end of the connection editor.&lt;br /&gt;
&lt;br /&gt;
==== Connect WiFi Android Device ====&lt;br /&gt;
&lt;br /&gt;
You can connect to Android devices using WiFi as well. In this case, the device has to be connected to ADB first, see [[Mobile_Testing_Plugin/en#Connection_via_WLAN|Connection via WLAN]]. Since expecco 22.1, the connection editor provides a dialog helping to set this up, which can be used instead of the command window. For devices using Android 11 or newer, you can pair the device with your machine here by specifying the appropriate parameters and then establish the connection by specifying the IP address and port. You can also use this to establish a wireless connection for devices that are connected via USB. When you select the corresponding device in the list, the required information is read out automatically.&lt;br /&gt;
&lt;br /&gt;
Note that establishing a wireless connection is not part of the connection settings. If you want to establish a new connection with the generated settings, you must make sure that the device is connected to ADB with the specified IP address and port so that it can be found. The ADB connection will be lost if the ADB server or the device are restarted. The permission for wireless debugging is also often reset when the device is restarted and the debug port can then change. Therefore, a wireless connection must always be established manually.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 2: Select App===&lt;br /&gt;
Here you can enter information about the app to be tested. You can decide if you want to use an app that is already installed on the device or if you want to install an app for the test. Select the appropriate tab above. Depending on whether you selected an Android or an iOS device in the previous step, the required input will change.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:If you have selected a connected device in the first step, the packages of all installed apps are automatically retrieved and you can select from the drop-down lists. The installed apps are divided into third-party packages and system packages; select the appropriate package list. This selection does not belong to the settings, but only provides the corresponding package list. You can use the filter to further narrow down the list and then select the desired package. The activities of the selected package are also automatically retrieved and made available as a drop-down list. Select the activity you want to start. As a rule, an activity is automatically entered from the list. If you are not using a connected device, you must enter the package and the activity manually.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. If you are using a local Appium server, you can use the right button to navigate to the App installation file and enter this path. If possible, the corresponding package and the activity are also entered in the fields below. However, this entry is not necessary.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App on Device&#039;&#039;&lt;br /&gt;
**:Specify the bundle ID of an installed app. You can find out the IDs of the installed apps using Xcode, for example. Start Xcode and select &#039;&#039;Devices&#039;&#039; from the menu bar at the top of the screen in the &#039;&#039;Window&#039;&#039; menu. A window will open displaying a list of connected devices. If you select your device, you will see a list of the apps you have installed in the overview.&lt;br /&gt;
**&#039;&#039;Install App&#039;&#039;&lt;br /&gt;
**:Under &#039;&#039;App&#039;&#039;, enter the path to an app. The path must be valid for the Appium server being used. You can also specify a URL. For the requirements of apps for real devices, please read the section  [[#iOS-Ger.C3.A4t_and_App_Preparing|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
In the lower part you can specify whether the app should be reset or uninstalled when the connection is terminated, and whether it should be reset initially. Again, the corresponding capability is not set if you select &#039;&#039;(Default)&#039;&#039;. With &#039;&#039;Next&#039;&#039; you get to the next step.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Step 3: Server Settings===&lt;br /&gt;
In the last step, a list of all the capabilities that result from your entries in the previous steps is first displayed in the upper part. If you are familiar with Appium and want to set additional capabilities that are not covered by the connection editor, you can click on &#039;&#039;Edit&#039;&#039; to open the extended view. See the section below for more information.&lt;br /&gt;
&lt;br /&gt;
If you enter settings for the GUI browser, you can enter the &#039;&#039;Connection name&#039;&#039; with which the connection is displayed. This is also the name under which devices can use this connection when it is established. If you leave the field blank, a name will be generated. If the box &amp;quot;&#039;&#039;Managed by expecco&#039;&#039;&amp;quot; is checked, expecco will start a local Appium server on a free port, or use a free server that has already been started. To use your own server, turn this feature off and enter the appropriate address. You will get the local default address and already used addresses to choose from.&lt;br /&gt;
&lt;br /&gt;
In older expecco versions the box is labeled &amp;quot;&#039;&#039;Start on demand&#039;&#039;&amp;quot;. In this case, you must also enter an address if you want expecco to start the server. expecco then tries to start an Appium server at the given address when connecting, if none is running there yet. This server will then also be shut down when the connection is terminated. This only works for local addresses. Make sure that you only use port numbers that are free. It is best to only use odd port numbers from the standard port 4723. The following port number is also used when establishing a connection, which could otherwise lead to conflicts.&lt;br /&gt;
&lt;br /&gt;
Depending on how you opened the dialog, there are now different buttons to close it. In any case you have the option to save. This opens a dialog where you can either select an open project to save the settings there as an attachment, or choose to save it to a file that you can then specify. Saving does not close the dialog, allowing you to select another option.&lt;br /&gt;
&lt;br /&gt;
If you have opened the editor for establishing a connection, you can finally click on &#039;&#039;Connect&#039;&#039; or &#039;&#039;Start and connect server&#039;&#039;, depending on whether the check mark for server start is set. For changing or copying a connection in the GUI Browser, this option is called &#039;&#039;Apply&#039;&#039;, since in this case only the connection entry is changed or created, but the connection setup is not started. If necessary, you can do this afterwards via the context menu. If you have changed capabilities of an existing connection, a dialog then prompts you to decide whether these changes should be applied directly by closing the connection and establishing the new connection or not. In this case, the changes only take effect after you reestablish the connection.&lt;br /&gt;
&lt;br /&gt;
To use the connection editor, also read the corresponding section in the respective tutorial in step 1. (Android: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo|Run Demo]], iOS: [[Mobile_Testing_Tutorial/en#Step_1:_Run_Demo_2|Run Demo]]).&lt;br /&gt;
&lt;br /&gt;
===Extended View===&lt;br /&gt;
The extended view of the connection editor can be obtained either by clicking on &#039;&#039;Edit&#039;&#039; in the third step or at any time via the corresponding menu item if you have started the editor via the plugin menu. This view displays a list of all configured Appium Capabilities. You can add, change or remove further entries to this list. To add a capability, select it from the drop-down list of the input field. In this list all known capabilities are sorted into the categories &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; and &#039;&#039;iOS&#039;&#039;. If you have selected a capability, a short information text is displayed. You can also enter a capability manually in the field. Then click on &#039;&#039;Add&#039;&#039; to add the capability to the list. There you can set the value in the right column. To delete an entry, select it and click on &#039;&#039;Remove&#039;&#039;. With &#039;&#039;Back&#039;&#039; you leave the extended view.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Running Appium Servers ==&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will find the entry &#039;&#039;Appium-Server...&#039;&#039;. This opens a window with an overview of all Appium servers started by expecco and on which port they are running. By clicking on the icon in the column &#039;&#039;Show Log&#039;&#039; you can view the logfile of the corresponding server. This is deleted when the server is shut down. With the icons in the column &#039;&#039;Exit&#039;&#039; the corresponding server can be terminated. However, this is prevented if expecco still has an open connection via this server. The rightmost column shows for which connection the server is in use. If it reads &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039;, the server is currently not used by expecco.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
When opening the editor to start an Appium connection, an Appium server is started immediately to speed up the connection process. For this purpose, expecco always keeps one idle running Appium server. Additional running servers however, which are not in use anymore, will be terminated automatically after a while.&lt;br /&gt;
&lt;br /&gt;
In the menu of the Mobile Testing Plugin you will also find the entry &#039;&#039;Close all Connections and Servers&#039;&#039;. This is intended for cases where connections or servers cannot be terminated in any other way. If possible, always terminate connections in the GUI browser or by executing a corresponding block. Servers that you have started in the server overview should be terminated there; servers that were started with a connection are automatically terminated with this connection.&lt;br /&gt;
&lt;br /&gt;
Note that only servers started and managed by expecco are listed in the overview. Possible other Appium servers that were started in a different way are not recognized.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
If the GUI browser is connected to a device, the integrated recorder can be used to record a test section with that device. To start the recorder, select the appropriate connection in the GUI browser and click the Record button. A new window opens for the recorder. The recorded actions are created in the GUI browser work area. It is therefore possible to edit the recorded data in parallel.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Components of the Recorder Window====&lt;br /&gt;
#&#039;&#039;&#039;Continue/Pause Recording&#039;&#039;&#039;: You can pause the recording by clicking the right icon. You will then see a large pause sign in the view. All actions that you perform now in the recorder are executed, but no blocks are recorded. You can switch back to normal recording mode by clicking the left icon.&lt;br /&gt;
#&#039;&#039;&#039;Stop Recording&#039;&#039;&#039;: Stops the recording and closes the recorder window.&lt;br /&gt;
#&#039;&#039;&#039;Update&#039;&#039;&#039;: Gets the current image and element tree from the device. This is necessary if the device takes longer to execute an action or if something changes without being triggered by the recorder. Since expecco 21.2, there is an additional submenu here that can be used to enable automatic update by checking for changes in the background (see also &#039;&#039;Automatic Update&#039;&#039; further below).&lt;br /&gt;
#&#039;&#039;&#039;Follow Mouse&#039;&#039;&#039;: Select the element under the mouse pointer in the GUI browser.&lt;br /&gt;
#&#039;&#039;&#039;Element Highlighting&#039;&#039;&#039;: The element under the mouse is outlined in red.&lt;br /&gt;
#&#039;&#039;&#039;Show Elements&#039;&#039;&#039;: Show the borders of all elements in the view.&lt;br /&gt;
#&#039;&#039;&#039;Tools&#039;&#039;&#039;: Selection, which  tool is used for recording. The selected action is triggered with each click on the view. The following actions are available:&lt;br /&gt;
#*Element Actions:&lt;br /&gt;
#**Click: Short click on the element under cursor. To determine more precisely which element is used, use the Follow Mouse or Element Highlighting function.&lt;br /&gt;
#**Tap with Duration (Element): Similar to click, except that the duration of the click will be recorded as well. This allows the recording of long clicks.&lt;br /&gt;
#**Tap with Position (Element): Similar to click, but additionally records the position inside the element. The position can be recorded relative to the element size or, when pressing Ctrl while clicking, as absolute position from the upper left corner of the element.&lt;br /&gt;
#**Set Text: Allows to set the text of an input field.&lt;br /&gt;
#**Clear Text: Clears the text of an input field.&lt;br /&gt;
#*Device Actions:&lt;br /&gt;
#**Tap (Screen): Triggers a click at the screen position.&lt;br /&gt;
#**Tap with Duration (Screen): Triggers a click at the screen position, which also considers the duration.&lt;br /&gt;
#**Swipe: Swipe in a straight line from the point where you press the mouse button until you release it. The duration is also recorded.&lt;br /&gt;
#:Please note for this actions that the result may differ on different devices, e.g. with different screen resolutions.&lt;br /&gt;
#*Test Flow Blocks&lt;br /&gt;
#**Check Attribute: Compares the value of a specified attribute of the element with a predefined value. The result triggers the corresponding output.&lt;br /&gt;
#**Assert Attribut: Compares the value of a specified attribute of the element with a predefined value. If the values are not equal, the test fails.&lt;br /&gt;
#**Get Attribute: Gets the current value of a specified attribute of the element.&lt;br /&gt;
#*Auto&lt;br /&gt;
#:If the Auto tool is selected, you can use all actions by specific input methods: &#039;&#039;Click&#039;&#039;, &#039;&#039;Tap Element&#039;&#039; and &#039;&#039;Swipe&#039;&#039; still work by clicking, but are distinguished by the duration and movement of the cursor. To trigger a &#039;&#039;Tap&#039;&#039;, hold down Ctrl while clicking. The remaining actions are available in a context menu by right-clicking on the element.&lt;br /&gt;
#&#039;&#039;&#039;Context Actions&#039;&#039;&#039;: Here you can record actions concerning contexts:&lt;br /&gt;
#*Switch to Context: Shows a list of all currently available contexts and you can select to which one you want to switch.&lt;br /&gt;
#*Get Current Context: Gets the handle of the current context.&lt;br /&gt;
#*Get Context Handles: Gets a list of all currently available contexts.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Only for Android. Simulates pressing the buttons Back, Home, Menu and Power.&lt;br /&gt;
#&#039;&#039;&#039;Home Button&#039;&#039;&#039;: Only for iOS since expecco 2.11. Allows pressing the Home button.Prior to expecco 19.2, it only works if AssistiveTouch is activated and the menu is located in the middle of the upper screen border. From expecco 19.2 on, the function no longer uses AssistiveTouch.&lt;br /&gt;
#&#039;&#039;&#039;Help&#039;&#039;&#039;: Opens this online documentation on the general page about [[GuiBrowser_Recorder/en|GUI Browser recorders]].&lt;br /&gt;
#&#039;&#039;&#039;View&#039;&#039;&#039;: Shows a screenshot of the device. Actions are triggerd by mouse depending on the selected tool. If a new action can be recorded, the window has a green frame, else it is red.&lt;br /&gt;
#&#039;&#039;&#039;Resize Window to Image&#039;&#039;&#039;: Resizes the recorder window so that the screenshot can be displayed completely.&lt;br /&gt;
#&#039;&#039;&#039;Resize Image to Window&#039;&#039;&#039;: Scales the screenshot to a size that makes use of the full size of the window.&lt;br /&gt;
#&#039;&#039;&#039;Adjust Display&#039;&#039;&#039;: Opens a dialog to adjust the displayed image, if expecco does not show it right. You can correct the scaling or rotate the image by 90°.&lt;br /&gt;
#&#039;&#039;&#039;Correct Orientation&#039;&#039;&#039;: Corrects the image if it is upside down. Using the arrow to the right, the image can also be rotated by 90°, if this should ever be necessary. Since expecco 19.1 you find this functionality under &#039;&#039;Adjust Display&#039;&#039;. The orientation of the image is irrelevant for the functionality of the recorder, it only works on the elements it receives.&lt;br /&gt;
#&#039;&#039;&#039;Scaling&#039;&#039;&#039;: Changes the scaling of the screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Messages&#039;&#039;&#039;: Shows the path of the current selected element or other messages. It has a context menu to show a list of previous messages.&lt;br /&gt;
&lt;br /&gt;
====Usage====&lt;br /&gt;
Each click in the window triggers an action and is recorded in the workspace of the GUI browser. There you can run, edit, or create a new block from what you have recorded. You find the actions to trigger softkeys directly in the menu bar (see above). To record actions on elements, either change the selection of the tool in the menu bar (see above) and then click on the element or select the corresponding action from the context menu by right-clicking on the corresponding element. For text input it is also possible to place the cursor over the element and enter the text. This opens the input dialog for this action. On how to use the recorder, see also step 2 in the tutorial ([[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_Block_with_the_Recorder|Android]] resp. [[Mobile_Testing_Tutorial/en#Step_2:_Creating_a_block_with_the_Recorder_2|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Hide elements====&lt;br /&gt;
Since expecco 21.2 it is also possible to hide the selected element in the recorder from the context menu. This means that this element cannot be selected from now on. This function is useful for ignoring elements that are in the foreground to be able to access elements below them. To undo this state, you have to find the corresponding element in the tree of the GUI browser, which also has such an entry in the context menu.&lt;br /&gt;
&lt;br /&gt;
====Automatic Update====&lt;br /&gt;
The recorder doesn&#039;t show a live image of the device, but only a snapshot. Therefore an update is needed after changes to match what is displayed on the device. The recorder updates automatically after executing an action. Since expecco 20.2 there are further automatic updates possible. You can enable the, in the menu &amp;quot;View&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
One option is, to check after an action has been executed, if there are further changes after the first update. If so, a second update is triggered. This shall fix the problem, that the recorder is not up to date after an action, because the update has been done too early.&lt;br /&gt;
&lt;br /&gt;
The second option is to enable a periodical update. After a set interval the recorder is automatically updated if there are changes. Thereby the recorder view is mostly up to date, but this causes an overhead regarding the communication to the device.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid Apps and WebViews =&lt;br /&gt;
&#039;&#039;&#039;!!! IMPORTANT NOTICE - If you have problems switching to the webview, please set the &amp;quot;Default Application - Browser App&amp;quot; in Android Settings to &amp;quot;Chrome&amp;quot; !!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid apps contain platform native elements as well as other elements that are integrated in a WebView. These elements can also be used, but you first have to switch to the corresponding context. With the block &#039;&#039;Get Current Context&#039;&#039; you get the current context. Initially this is &#039;&#039;NATIVE_APP&#039;&#039;, i.e. the context of the native elements. With the block &#039;&#039;Get Context Handles&#039;&#039; you get a collection of all existing contexts. If there is a WebView context, it is called &#039;&#039;WEBVIEW_1&#039;&#039; or &#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039; with the package of the WebView. Several WebView contexts are also possible. For each WebView context, there is a corresponding WebView element in the native context. You can use the &#039;&#039;Switch to Context&#039;&#039; block to switch to such a context and from now on only have access to the elements in this context.&lt;br /&gt;
&lt;br /&gt;
In the GUI browser, the existing contexts are displayed at the top of the tree as well as the tree of a context is inserted below the corresponding WebView element.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;Customizing XPath using the GUI Browsers&amp;quot;&amp;gt;&amp;lt;!-- name before 01.10.2020--&amp;gt;&amp;lt;/span&amp;gt;Customizing XPath using the GUI Browser=&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; und &#039;&#039;Verify&#039;&#039;, das Eingabefeld der Zahl &#039;&#039;4006381333986&#039;&#039; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des GTIN-13-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &#039;&#039;Pfad überprüfen&#039;&#039; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &#039;&#039;Verify Path: OK&#039;&#039; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit * zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &#039;&#039;GTIN-13 (EAN-13)&#039;&#039; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &#039;&#039;hierarchy&#039;&#039; (für iOS wäre es &#039;&#039;AppiumAUT&#039;&#039;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &#039;&#039;android.widget.&#039;&#039;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &#039;&#039;XCUIElementType&#039;&#039; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &#039;&#039;FrameLayout&#039;&#039; ist ein Kindelement von &#039;&#039;hierarchy&#039;&#039;, &#039;&#039;LinearLayout&#039;&#039; ist ein Kind von &#039;&#039;FrameLayout&#039;&#039; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &#039;&#039;hierarchy&#039;&#039; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &#039;&#039;TextView&#039;&#039;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &#039;&#039;Button&#039;&#039; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &#039;&#039;resource-id&#039;&#039;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &#039;&#039;name&#039;&#039; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem @ eingeleitet und der Wert mit einem = in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &#039;&#039;Test&#039;&#039; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &#039;&#039;Lauf&#039;&#039;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &#039;&#039;Eigenschaften&#039;&#039;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Problems and Solutions=&lt;br /&gt;
== Locators depend on the version or are variable ==&lt;br /&gt;
In this case consider to either store the locators (xPath) in a variable or to define a locator mapping inside a screenplay attachment. It is also possible to store just parts of an locator (e.g. locator path of a parent or attribute value) in a variable and add them in the freeze value of the locator pin by &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Invisible UI Elements ==&lt;br /&gt;
Note that the [[#Recorder|Recorder]] also considers items that you cannot see on the screen. Therefore, turn on element highlighting or use the follow mouse function and the element tree in the GUI browser to determine if the correct element is used. It can happen, that invisible elements are in front of other elements and cover them, so that the desired element cannot be selected in the recorder. See section [[#Hide_elements|Hide elements]] for a solution to this.&lt;br /&gt;
&lt;br /&gt;
== iOS: Cable not certified ==&lt;br /&gt;
In some cases, when connecting an iOS device via USB, a message appears indicating that the cable used is not certified. In this case, replacing the respective cable is the only solution.&lt;br /&gt;
&lt;br /&gt;
== iOS: Alerts when connecting ==&lt;br /&gt;
Make sure that no alerts are open when connecting to an iOS device. Otherwise the connection will fail because the app cannot be brought to the foreground. See also [[#Preparing_an_iOS-Device_and_App|Preparing an iOS-Device and App]].&lt;br /&gt;
&lt;br /&gt;
== iOS: .ipa cannot be installed ==&lt;br /&gt;
Note that on iOS simulators no &#039;&#039;.ipa&#039;&#039; files can be installed but only &#039;&#039;.app&#039;&#039; files.&lt;br /&gt;
&lt;br /&gt;
==iOS: First Connect is not working==&lt;br /&gt;
If there is not already a signed build of the WebDriverAgent on your Mac, it has to be created during the first connect. Usually, this can take a little longer than one minute. Per default Appium uses a timeout of 60000&amp;amp;nbsp;ms to wait for the WebDriverAgent to start on the device, so the connect will be canceled in that case. You can set this timeout with the capability &#039;&#039;wdaLaunchTimeout&#039;&#039;, e.g. to &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Moreover, the signing settings have to be correct. In our experience, the most reliable solution is to set automatic signing in the WebDriverAgent Xcode project an selecting the team there. See the explanation in section [[#Signing_WebDriverAgent|Signing WebDriverAgent]] for that. In this case you should &#039;&#039;&#039;not&#039;&#039;&#039; use the capabilities &#039;&#039;xcodeConfigFile&#039;&#039; resp. &#039;&#039;xcodeOrgId&#039;&#039; and &#039;&#039;xcodeSigningId&#039;&#039;, as they could cause a conflict. Caution: If you have set a Team ID in the Mobile Testing settings, expecco will automatically set this as &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Pay attention to your device during the first connect. You might have to agree to the installation by entering your password. On the Mac you might need to enter the password to allow access to the key chain for signing, often several times.&lt;br /&gt;
&lt;br /&gt;
== Android: Device not visible in the connect editor ==&lt;br /&gt;
If an Android device connected via USB does not appear in the connection editor, try changing the USB connection type. Usually MTP or PTP should work. Check again, if &amp;quot;USB Debugging&amp;quot; is enabled in the developer options on the device (these options are disabled on some devices and have to be enabled first using a trick.) See also [[#Prepare_Android_Device|Prepare Android Device]].&lt;br /&gt;
&lt;br /&gt;
== Android: Truncated Elements at Bottom ==&lt;br /&gt;
For Android devices that automatically show and hide the navigation bar/softkeys, the recorder may cut off elements in the lower area that would be hidden by the softkeys, even if they are not displayed at this time. In this case it is advisable to set the softkeys so that they are permanently displayed.&lt;br /&gt;
&lt;br /&gt;
For newer Android versions there usually is no such option. Even if the controls are visible all the time, they don&#039;t have their own space, but are on top of the content of the app. Therefore, there is an area on the lower part of the screen, which cannot be automated, because it is not counted to the active area of the app. Appium will then truncate the elements there. This area can even be larger then the needed by the controls. This is a known issue for Samsung devices with Android 11. Since the information about the size of the app area is already provided on Android level, we cannot offer a solution for this, but can only hope that the problem will be fixed by the manufacturer. You may try to get better results by setting the control to gestures, but this bears the same issue.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test Hangs While Finding an Element==&lt;br /&gt;
The block &#039;&#039;Find Element by XPath&#039;&#039; and all element blocks wait until an element is present for the given path. The timeout for this can be set either directly at the block or in the environment variables. However, if the element should already be present, but the test doesn&#039;t continue anyway, the reason could be in the UIAutomator/UIAutomator2. It waits for the app to go to the idle state before it even starts to search for the element. This may take longer, if the app e.g. runs an animation in the background or executes other kinds of actions. Fetching the page source, e.g. when updating in the GUI browser or in the recorder, can also take longer for this reason. There is a default timeout of 10 seconds after which it no longer waits for the idle state. This timeout can be set in Appium (waitForIdleTimeout). If you want to change the value of this timeout, you can do this since expecco 21.2 by executing the Smalltalk code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; before the test. The timeout is given in milliseconds, so the example sets it to 2 seconds.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Updating the Tree or Switching to Webview Context takes too long==&lt;br /&gt;
Especially with older devices it can happen that newer Chromedriver cannot be initialized. This makes it impossible to switch to the webview context. However, this is only detected over a timeout by Appium, which is 4 minutes by default. Since expecco also tries to switch to the webview context when building the tree in the GUI browser, this can lead to very long loading times. Since there is no way to decrease this timeout in Appium, we have added a corresponding capability to the version we provide in the MobileTestingSupplement. Starting with version 1.13.1.0 of the [[#Windows|MobileTestingSupplement]], &#039;&#039;chromedriverStartTimeout&#039;&#039; can be used to set the timeout in milliseconds. The switch still doesn&#039;t work then, but expecco doesn&#039;t take as long to update the tree and the context switch module fails faster. The connection dialog adds this capability automatically starting with expecco 22.1. &lt;br /&gt;
&lt;br /&gt;
== No Action on Click ==&lt;br /&gt;
The block to click on an element is successful, but no action was performed on the device.&lt;br /&gt;
:This can happen if the element is hidden by another element and therefore clicking on the element is not possible. In this case, Appium does not throw an error, but simply nothing happens. If you would like to make a click at the position of the element anyways, even if it is hidden, use the block &#039;&#039;Tap&#039;&#039; instead and pass the location of the element to it (&#039;&#039;Get Location&#039;&#039;). If instead you want to check before a click whether the element is hidden at this moment, try whether the properties &#039;&#039;Is Displayed&#039;&#039; or &#039;&#039;Is Enabled&#039;&#039; might help you.&lt;br /&gt;
&lt;br /&gt;
== No Update After Action ==&lt;br /&gt;
An action was triggered on the recorder and a block has been recorded, but the recorder still shows the old image.&lt;br /&gt;
:The recorder doesn&#039;t show a live image of the device, but only a snapshot. After an action has been executed, the recorder will update automatically. However, it can happen, that the image has already been updated before the effects of the action are fully completed on the device. In this case you should update the recorder by hand using the icon with the blue arrows. Since expecco 20.2 you can also enable automatic updates for this case. See also the description for the [[#Recorder|recorder]].&lt;br /&gt;
&lt;br /&gt;
== Attribute &amp;quot;clickable&amp;quot; is wrong ==&lt;br /&gt;
An element has for the attribute/property &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; the value &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, but is actually clickable.&lt;br /&gt;
:The attribute &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; has to be set explicitly by the app developer and does not affect the behavior of the app. You should generally disregard this attribute in your tests. Unfortunately, many apps exist where the programmer was &amp;quot;lazy&amp;quot; about this.&lt;br /&gt;
&lt;br /&gt;
==Connecting Fails==&lt;br /&gt;
If the connection to the Appium server fails, you will receive an error message in expecco similar to the one shown below.&lt;br /&gt;
&lt;br /&gt;
[[File:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Here you can see the type of error that has occurred. Click on &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; to get more information. Possible errors are:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:The specified server is not running or is not reachable. Check the server address.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Read the message after &#039;&#039;Original Error&#039;&#039; in the first line of the details:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Either the device is not connected properly or the udid is not correct.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::This error can have various causes. Either the WebDriverAgent could actually not be built because the signing settings are wrong or the appropriate provisioning profile is missing. Please read the section about [[#Signing|Signing]].  It is also possible that the WebDriverAgent cannot be started on the device, for example because an alert is in the foreground or you did not trust the developer.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::The specified app cannot be installed on the iOS device because it is not entered in the app&#039;s Provisioning Profile.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the file is located in the specified path on your Mac.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::The specified &#039;&#039;apk&#039;&#039; file is probably broken.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::The path to the app is wrong. Make sure that the &#039;&#039;apk&#039;&#039; file is located in the specified path.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If the error is not due to one of the causes listed above, the automation applications on the device may no longer function properly. In this case it helps to uninstall them from the mobile device. They are then automatically reinstalled the next time a connection is established.&lt;br /&gt;
&lt;br /&gt;
*For iOS devices, this is the WebDriverAgent, which you can simply uninstall from the home screen. This usually solves problems caused by changing the used Mac or the Xcode version.&lt;br /&gt;
&lt;br /&gt;
*For Android devices, it is the UIAutomator2; here, a problem occurs sporadically on some devices, the cause is currently unknown to us. To uninstall, on the device, navigate to &amp;quot;&#039;&#039;Settings&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Applications&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; and search the list for the following entries:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Click on the respective application and then on &amp;quot;&#039;&#039;Uninstall&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;The corresponding entry may have a slightly different name on some devices.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If this doesn&#039;t help, check the output of the Appium server. For a server started by expecco, you can find the log in the list of [[#Running_Appium_Servers|Running Appium Servers]].&lt;br /&gt;
&lt;br /&gt;
==I do not have a Mac==&lt;br /&gt;
Maybe this site will help you: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29046</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29046"/>
		<updated>2023-11-30T11:01:38Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Probleme und Lösungen */ erster Verbindungsaufbau iOS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000 ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
&lt;br /&gt;
==iOS: Erster Verbindungsaufbau funktioniert nicht==&lt;br /&gt;
Wenn auf Ihrem Mac noch kein signierter Build des WebDriverAgents liegt, muss dieser beim ersten Verbindungsaufbau erst erzeugt werden. Das kann in der Regel etwas länger als eine Minute dauern. Standardmäßig verwendet Appium aber einen Timeout von 60000&amp;amp;nbsp;ms um zu warten bis der WebDriverAgent auf dem Gerät startet, so dass der Aufbau in diesen Fällen abgebrochen wird. Sie können den Timeout mit der Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; setzen, z.B. auf &#039;&#039;120000&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Außerdem müssen die Einstellungen für die Signierung passen. Am zuverlässigsten funktioniert das nach unserer Erfahrung, wenn man im Xcode-Projekt des WebDriverAgents auf automatische Signierung stellt und das Team setzt. Siehe dazu die Erklärung im Abschnitt [[#WebDriverAgent-Signierung|WebDriverAgent-Signierung]]. In diesem Fall sollten Sie die Capabilities &#039;&#039;xcodeConfigFile&#039;&#039; bzw. &#039;&#039;xcodeOrgId&#039;&#039; und &#039;&#039;xcodeSigningId&#039;&#039; &#039;&#039;&#039;nicht&#039;&#039;&#039; verwenden, da es sonst zu Konflikten kommen kann. Achtung: Wenn Sie eine Team-ID in den Mobile-Testing-Einstellungen gesetzt haben, setzt expecco diese automatisch als &#039;&#039;xcodeOrgId&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
Achten Sie beim ersten Verbindungsaufbau außerdem auf Ihr Gerät, da Sie dort möglicherweise der Installation per Passwort zustimmen müssen. Auf dem Mac kann die Eingabe des Passworts zur Freigabe des Schlüsselbunds für die Signierung nötig werden, häufig auch mehrmals.&lt;br /&gt;
&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29045</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29045"/>
		<updated>2023-11-30T10:32:32Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* WebDriverAgent-Signierung */ wdaLaunchTimeout&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
Ist der WebDriverAgent einmal auf dem Gerät installiert, wird er für spätere Verbindungen wieder verwendet und der Verbindungsaufbau sollte schneller funktionieren. Ebenso liegt dann die signierte Version bereits auf Ihrem Mac und muss nicht erneut gebaut werden, was die Verbindung zu weiteren Geräten ebenfalls beschleunigt. Wenn Sie wissen, dass bei Ihrem Verbindungsaufbau der WebDriverAgent erst noch signiert und gebaut werden muss, ist es ratsam, die Capability &#039;&#039;wdaLaunchTimeout&#039;&#039; zu setzen. Dieser Timeout, wie lange auf den Start der WebDriverAgents auf dem Gerät gewartet werden soll, liegt standardmäßig bei 60000 ms. Der Build dauert aber häufig über eine Minute, sodass der Versuch zum Verbindungsaufbau dann abgebrochen wird. Ein Wert von 120000 hat sich hier als besser erwiesen.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29042</id>
		<title>Mobile Testing Plugin</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Mobile_Testing_Plugin&amp;diff=29042"/>
		<updated>2023-11-23T12:10:35Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Deutsche Version&#039;&#039;&#039; | [[Mobile_Testing_Plugin/en|English Version]]&lt;br /&gt;
&lt;br /&gt;
= Einleitung =&lt;br /&gt;
Mit dem &#039;&#039;Mobile Testing Plugin&#039;&#039; können Anwendungen auf Android- und iOS-Geräten getestet werden. Dabei ist es egal, ob reale mobile Endgeräte oder emulierte Geräte verwendet werden. Das Plugin kann (und wird üblicherweise) zusammen mit dem [[Expecco_GUI_Tests_Extension_Reference|GUI-Browser]] verwendet werden, der das Erstellen von Tests unterstützt. Zudem ist damit das Aufzeichnen von Testabläufen möglich.&lt;br /&gt;
&lt;br /&gt;
Zur Verbindung mit den Geräten wird [http://appium.io/ Appium] verwendet. Appium ist ein freies Open-Source-Framework zum Testen und Automatisieren von mobilen Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Zur Einarbeitung in das Mobile Plugin empfehlen wir das [[Mobile_Testing_Tutorial|Tutorial]] zu bearbeiten. Dieses führt anhand eines Beispiels Schritt für Schritt durch die Erstellung eines Testfalls und erklärt die nötigen Grundlagen.&lt;br /&gt;
&lt;br /&gt;
= Installation und Aufbau =&lt;br /&gt;
Zur Verwendung des Mobile Testing Plugins müssen Sie expecco inkl. des Plugins Mobile Testing installiert haben und Sie benötigen die entsprechenden Lizenzen. expecco kommuniziert mit den Mobilgeräten über einen Appium-Server, der entweder auf demselben Rechner wie expecco läuft, oder auf einem zweiten Rechner. Dieser muss für expecco erreichbar sein.&lt;br /&gt;
&lt;br /&gt;
==Installationsübersicht==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Rechner, auf dem expecco läuft:&#039;&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem Android-Geräte angeschlossen sind:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Android SDK&#039;&#039;, dieses erhalten Sie ebenfalls mit dem Mobile Testing Supplement&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Rechner, an dem iOS-Geräte angeschlossen sind&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;:&#039;&#039;&#039;&lt;br /&gt;
* Appium-Server&#039;&#039;, diesen können Sie über das Mobile Testing Supplement für Mac OS installieren (s.u.), von dem wir regelmäßig einen neue Version zur Verfügung stellen&#039;&#039;&lt;br /&gt;
* Xcode &#039;&#039;in einer Version, die die verwendete iOS-Version unterstützt, erhältlich über den Apple App Store&#039;&#039;&lt;br /&gt;
* Java JDK Version 8, 9, 10, 11 oder neuer &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;&lt;br /&gt;
* Apple-Entwickler-Zertifikat mit zugehörigem privaten Schlüssel &#039;&#039;(zum Signieren des WebDriverAgents)&#039;&#039;&lt;br /&gt;
* Provisioning Profile mit den verwendeten Mobilgeräten&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Je nach Aufbau können die oben genannten Rechner auch das selbe Gerät sein. expecco kann sich sowohl über das Netzwerk mit einem entfernten Appium-Server und dort angeschlossenen Mobilgeräten verbinden, als auch lokal selbst einen Appium-Server starten und diesen mit lokalen Mobilgeräten verwenden. Einige Funktionen von expecco, die die Erstellung von Testfällen erleichtern, sind jedoch nur verfügbar, wenn die Mobilgeräte am selben Rechner angeschlossen sind, auf dem auch expecco läuft. Ein möglicher Aufbau kann daher wie in folgender Abbildung aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAufbau.png | 400px]]&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die Installation von Appium und anderer nötiger Programme für Windows und Mac OS erklärt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;: Zum Zeitpunkt der Erstellung dieses Dokuments wurden Versionen bis 11 auf Funktion verifiziert. Neuere Versionen sollten - sofern nicht grundlegende Änderungen von Oracle vorgenommen wurden, ebenfalls funktionieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;2)&amp;lt;/sup&amp;gt;: Beachten Sie, dass aufgrund der Voraussetzungen (keine Anbindung an nicht-Apple Geräte verfügbar) iOS-Geräte nur von einem Mac aus angesteuert werden können. Sie benötigen also einen Mac als &amp;quot;Vermittler&amp;quot; (siehe auch unten: [[#Ich habe keinen Mac | &amp;quot;Ich habe keinen Mac&amp;quot;]])&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
Am einfachsten installieren Sie alles mit unserem Mobile Testing Supplement&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;. In neueren Versionen ist allerdings aufgrund geänderter Lizenzbedingungen seitens Oracle kein JDK mehr enthalten, sodass sie dieses zusätzlich installieren müssen. Sie können natürlich Appium auch direkt installieren, um die Version zu verwenden, die Sie möchten. Um dann einen Appium-Server mit expecco starten zu können, muss allerdings eine entsprechende Batchdatei vorhanden sein und in den [[Mobile_Testing_Plugin#Konfiguration_des_Plugins|Einstellungen]] angegeben werden. Verbindungen können aber auch zu anderen laufenden Appium-Servern aufgebaut werden.&lt;br /&gt;
*&#039;&#039;&#039;expecco 23.1&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-23.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.3.1]&lt;br /&gt;
:Gleiche Versionen wie der Vorgänger, aber der Installer erlaubt nun, Appium zum Autostart hinzuzufügen.&lt;br /&gt;
*expecco 22.2 und 22.1: [https://download.exept.de/transfer/h-expecco-22.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.13.2.0]&lt;br /&gt;
:Appium 1.22.3*&lt;br /&gt;
:Node 14.17.5&lt;br /&gt;
:adb 1.0.41 aus platform-tools 33.0.2&lt;br /&gt;
:&#039;&#039;* Wir haben Appium um die Capability&#039;&#039; startChromedriverTimeout &#039;&#039;erweitert, um schneller einen Timeout zu bekommen, wenn der Chromedriver nicht gestartet werden kann. (siehe [[#startChromedriverTimeout|Probleme und Lösungen]])&#039;&#039;&lt;br /&gt;
*expecco 21.2: [https://download.exept.de/transfer/h-expecco-21.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.12.0.0]&lt;br /&gt;
:Enthält die Appium-Version 1.22.0, Node ist weiterhin in der Version 12.13.1.&lt;br /&gt;
*expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.1.0]&lt;br /&gt;
:Nur kleine Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
*expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.10.0.0]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und node 12 verwendet. &lt;br /&gt;
*expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.8.1.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.12.0 und enthält nun zusätzlich build-tools der Version 28.0.3 im android-sdk. Ansonsten ist es gleich wie die vorige Version.&lt;br /&gt;
*expecco 18.2: [http://download.exept.de/transfer/h-expecco-18.2.0/MobileTestingSupplement.exe Mobile Testing Supplement 1.7.3.0]&lt;br /&gt;
:Dieses installiert Appium in der Version 1.8.1. Außerdem bietet das Supplement auch an, &#039;&#039;Android Debug Bridge&#039;&#039; und &#039;&#039;Google USB Driver&#039;&#039; ([https://gsmusbdrivers.com/download/adb-fastboot-drivers/ adb-setup-1.4.3]) zu installieren. Damit sind Treiber für ein breites Spektrum an Android-Geräten abgedeckt, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen. Ein &#039;&#039;&#039;JDK ist (aufgrund geänderter Lizenzbedingungen seitens Oracle) nicht mehr enthalten&#039;&#039;&#039;, dieses müssen Sie selbst herunterladen, z.B. von [https://www.oracle.com/technetwork/java/javase/downloads/index.html Oracle].&lt;br /&gt;
*expecco 18.1: wie expecco 2.11&lt;br /&gt;
*expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/MobileTestingSupplement_1.6.0.2_Setup.exe Mobile Testing Supplement 1.6.0.2]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.6.4. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
*expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_1.5.0.0_Setup.exe Mobile Testing Supplement 1.5.0.0]&lt;br /&gt;
:Dieses installiert ein Java JDK der Version 8, android-sdk und Appium in der Version 1.4.16. Während der Installation wird die grafische Oberfläche von Appium gestartet, dieses Fenster können Sie sofort wieder schließen. Außerdem bietet das Supplement auch einen universellen adb-Treiber ([http://download.clockworkmod.com/test/UniversalAdbDriverSetup.msi ClockworkMod]) an. Dieser vereint Treiber für ein breites Spektrum an Android-Geräten, sodass Sie nicht für jedes Gerät einen eigenen Treiber suchen und installieren müssen.&lt;br /&gt;
&lt;br /&gt;
Wenn expecco Mobilgeräte verwenden soll, die an einem anderen Rechner angeschlossen sind, müssen Sie dort einen Appium-Server starten. Dies können Sie mit der Datei &amp;lt;code&amp;gt;appium_standalone.cmd&amp;lt;/code&amp;gt; tun. Der Server wird dann mit dem Standard-Port 4723 gestartet. Falls Sie eine andere Portnummer verwenden wollen, starten Sie den Server mit&lt;br /&gt;
&lt;br /&gt;
 appium_standalone.cmd -p &amp;lt;portnummer&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Server ist bereit, sobald die Zeile&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Appium REST http interface listener started on 0.0.0.0:4723&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
angezeigt wird, wobei Sie am Ende die verwendete Portnummer ablesen können.&lt;br /&gt;
&lt;br /&gt;
Beim ersten Starten von Appium – sowohl im Standalone als auch gestartet von expecco – kann es vorkommen, dass die Windows-Firewall den Node-Server blockiert. Lassen Sie den Zugriff zu, sonst kann Appium nicht gestartet werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;) Sie können natürlich auch die Command Line Tools (adb, sdkmanager, avdmanager etc.) einer vorhandenen Android Studio Version verwenden, sowie Appium separat installieren.&lt;br /&gt;
Da sich diese Tools regelmäßig ändern, und es in der Vergangenheit zu Inkompatibilitäten und Fehlern nach Releasewechseln kam, empfehlen wir zu Beginn, das mitgelieferte Paket zu verwenden. Dies ist möglicherweise nicht das aktuellste, wurde aber auf Lauffähigkeit getestet.&lt;br /&gt;
&lt;br /&gt;
Falls das Android Mobilgerät an einem entfernen Rechner angeschlossen ist,&lt;br /&gt;
können Sie den aktuellen Bildschirminhalt z.B. mit dem [https://github.com/Genymobile/scrcpy scrcpy] tool live mitverfolgen.&lt;br /&gt;
&lt;br /&gt;
== Mac OS (nicht erforderlich für Android-Tests)==&lt;br /&gt;
Hinweis: Wenn Sie nicht vorhaben, iOS-Geräte (iPhone, iPad, etc.) zu testen, können Sie das Folgende ignorieren. &#039;&#039;&#039;Der Apple-Rechner sowie das Mac-Setup werden für Android-Geräte nicht benötigt&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Xcode ===&lt;br /&gt;
Zur Automatisierung mit iOS-Geräten wird [https://developer.apple.com/xcode/ Xcode] benötigt. Sie erhalten dieses über den App Store. Dabei ist darauf zu achten, dass die Version zu den getesteten iOS-Versionen passt.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;iOS&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;  &lt;br /&gt;
|&#039;&#039;&#039;Xcode&#039;&#039;&#039;&lt;br /&gt;
|&#039;&#039;&#039;macOS&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|10.x&lt;br /&gt;
|8.x&lt;br /&gt;
|10.12 (Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|11.x&lt;br /&gt;
|9.x&lt;br /&gt;
|10.13 (High Sierra)&lt;br /&gt;
|-&lt;br /&gt;
|12.x&lt;br /&gt;
|10.x&lt;br /&gt;
|10.14 (Mojave)&lt;br /&gt;
|-&lt;br /&gt;
|13.x&lt;br /&gt;
|11.x&lt;br /&gt;
|10.15 (Catalina)&lt;br /&gt;
|-&lt;br /&gt;
|14.x&lt;br /&gt;
|12.x&lt;br /&gt;
|11.0 (Big Sur)&lt;br /&gt;
|-&lt;br /&gt;
|15.x&lt;br /&gt;
|13.x&lt;br /&gt;
|12.0 (Monterey)&lt;br /&gt;
|-&lt;br /&gt;
|16.x&lt;br /&gt;
|14.x&lt;br /&gt;
|12.5 (Monterey)&lt;br /&gt;
|}&lt;br /&gt;
Diese Tabelle gibt nur eine vereinfachte Übersicht, lesen Sie besser unter [https://xcodereleases.com/ Xcode Releases] oder [https://en.wikipedia.org/wiki/Xcode#Version_comparison_table Xcode-Versionen] welche Version Sie brauchen. Für neue iOS Minor-Versionen gibt es in der Regel auch ein Update für Xcode, z.B. brauchen Sie für iOS 10.2 mindestens Xcode 8.2, für iOS 10.3 mindestens Xcode 8.3 usw. &lt;br /&gt;
Wenn Sie also auf eine neuere iOS-Version wechseln, benötigen Sie in der Regel auch eine neuere Xcode-Version. Neuere Versionen von Xcode laufen möglicherweise nicht auf älteren Betriebssystemen, was wiederum eine Aktualisierung des Betriebssystems erforderlich machen kann. Falls Sie auch ältere iOS-Versionen testen wollen kann es sinnvoll sein, die entsprechenden Xcode-Versionen parallel zu installieren.&lt;br /&gt;
&lt;br /&gt;
=== Appium ===&lt;br /&gt;
Der Appium-Server kann entweder als Kommandozeilen-Anwendung installiert werden oder über [https://github.com/appium/appium-desktop Appium Desktop] verwendet werden, welcher den Server über ein GUI zur Verfügung stellt. Mittlerweile gibt es auch Appium 2.0, was wir aber bisher noch nicht mit expecco getestet haben und daher nicht empfehlen.&lt;br /&gt;
&lt;br /&gt;
==== Appium Desktop ====&lt;br /&gt;
Laden Sie die neueste Version von [https://github.com/appium/appium-desktop/releases/ Appium Desktop] herunter. Für den Mac nehmen Sie am besten die dmg-Datei und installieren sie in den Anwendungen. Beim Starten der Anwendung &#039;&#039;Appium Server GUI&#039;&#039; erhalten Sie wahrscheinlich eine Fehlermeldung, dass es aus Sicherheitsgründen nicht möglich ist. Öffnen Sie dann das Kontextmenü auf der Anwendungsdatei (Rechtsklick bzw. Strg + Klick) und wählen Sie dort &#039;&#039;Öffnen&#039;&#039; aus. Bestätigen Sie dann, dass Sie die Anwendung wirklich öffnen wollen. Fortan können Sie die Anwendung normal öffnen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:OpenAppiumServerGUI1.png|text-top]] [[Datei:OpenAppiumServerGUI2.png|text-top]]&lt;br /&gt;
&lt;br /&gt;
Ab Xcode 14 gibt es Probleme beim Signieren des WebDriverAgents, den Appium zur Automatisierung auf das Gerät spielt. Dadurch ist mit der Version 1.22.3-4 von Appium Desktop kein Verbindungsaufbau möglich. Das Problem ist in neueren Versionen des WebDriverAgents behoben, es gibt aber aktuell noch keine Version von Appium Desktop, die eine solche Version enthält (Stand November 2022). Sie können aber manuell eine neue Version herunterladen (z.B. 4.10.2)  und die Dateien in Appium ersetzen. Laden Sie dazu von der [https://github.com/appium/WebDriverAgent/releases/ WebDriverAgent Download-Seite] eine der beiden Archivdateien (zip oder tar.gz) mit dem Source Code herunter. Öffnen und entpacken Sie dann diese Datei. Den Inhalt des Ordners WebDriverAgent-4.10.2 müssen Sie nun nach&lt;br /&gt;
&lt;br /&gt;
 /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
kopieren. Wenn Sie über den Finder dorthin navigieren, machen Sie auf die Anwendung &#039;&#039;Appium Server GUI&#039;&#039; einen Kontextklick (Rechtsklick bzw. Strg + Klick) und wählen Sie im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039;. Ersetzen Sie alle Dateien, die bereits mit gleichem Namen enthalten sind.&lt;br /&gt;
&lt;br /&gt;
==== Appium über npm installieren ====&lt;br /&gt;
Sie können Appium auch über npm (Node Package Manager) installieren. Dazu müsen Sie erst node/npm installieren. Das geht mit [https://github.com/nvm-sh/nvm nvm] (Node Version Manager) was Sie von Github bekommen. Falls die folgende Installationsanleitung bei Ihnen nicht funktionieren sollte, finden Sie dort ausführlichere Informationen im [https://github.com/nvm-sh/nvm#readme Readme].&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie ein Terminal-Fenster. Klonen Sie dann das Github-Repository von nvm&lt;br /&gt;
 curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash&lt;br /&gt;
und laden Sie es&lt;br /&gt;
 export NVM_DIR=&amp;quot;$([ -z &amp;quot;${XDG_CONFIG_HOME-}&amp;quot; ] &amp;amp;&amp;amp; printf %s &amp;quot;${HOME}/.nvm&amp;quot; || printf %s &amp;quot;${XDG_CONFIG_HOME}/nvm&amp;quot;)&amp;quot; [ -s &amp;quot;$NVM_DIR/nvm.sh&amp;quot; ] &amp;amp;&amp;amp; \. &amp;quot;$NVM_DIR/nvm.sh&amp;quot; # This loads nvm&lt;br /&gt;
&lt;br /&gt;
Führen Sie danach&lt;br /&gt;
 command -v nvm&lt;br /&gt;
aus, um zu testen, ob es funktioniert hat. Es sollte &#039;&#039;nvm&#039;&#039; ausgegeben werden. Kommt keine Antwort, führen Sie&lt;br /&gt;
 touch ~/.zshrc&lt;br /&gt;
aus, und versuchen Sie es erneut.&lt;br /&gt;
&lt;br /&gt;
Nun können Sie node mit dem folgenden Befehl installieren.&lt;br /&gt;
 nvm install 16.15.1&lt;br /&gt;
Da es mit der aktuellen Version von node Probleme beim Installieren von Appium gibt, empfehlen wir diese Version.&lt;br /&gt;
&lt;br /&gt;
Nachdem node installiert ist, können Sie Appium darüber installieren:&lt;br /&gt;
 npm install -g appium&lt;br /&gt;
&lt;br /&gt;
Den Appium-Server können Sie nun einfach über den Befehl&lt;br /&gt;
 appium&lt;br /&gt;
starten. Die Ausgabe erfolgt dann direkt im Terminal.&lt;br /&gt;
&lt;br /&gt;
Auch bei dieser Version gibt es das Problem bei der Signierung des WebDriverAgents, wie bei [[#Appium_Desktop | Appium Desktop]] beschrieben. Laden Sie also auch in diesem Fall eine neuere Version des WebDriverAgents herunter und ersetzen Sie die alten Dateien. Diese finden Sie unter&lt;br /&gt;
 /Users/&amp;lt;user&amp;gt;/.nvm/versions/16.15.1/lib/appium/node_modules/appium-webdriveragent/&lt;br /&gt;
&lt;br /&gt;
==== Mobile Testing Supplement ====&lt;br /&gt;
Ältere Appium-Versionen stellen wir Ihnen über das Mobile Testing Supplement für Mac OS zur Verfügung, mit dem Sie es einfach installieren können:&lt;br /&gt;
* &#039;&#039;&#039;expecco 20.2&#039;&#039;&#039;: [https://download.exept.de/transfer/h-expecco-20.2.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.2)]&lt;br /&gt;
:Enthält Appium Version 1.18.3 und verwendet node 14.&lt;br /&gt;
&lt;br /&gt;
* expecco 20.1: [https://download.exept.de/transfer/h-expecco-20.1.0/Mobile_Testing_Supplement_for_Mac_OS.tar.bz2 Mobile Testing Supplement für Mac OS (1.2.0)]&lt;br /&gt;
:Nur wenige Änderungen im Vergleich zur vorigen Version.&lt;br /&gt;
&lt;br /&gt;
* expecco 19.2: [http://download.exept.de/transfer/h-expecco-19.2.0/MobileTestingSupplement_for_MacOS.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.98)]&lt;br /&gt;
:Im Vergleich zur vorigen Version wurde Appium auf die Version 1.16.0-rc.1 aktualisiert und es wird node 12 verwendet. &lt;br /&gt;
&lt;br /&gt;
* expecco 19.1: [http://download.exept.de/transfer/h-expecco-19.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.96.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.96)]&lt;br /&gt;
:Diese Version enthält Appium 1.12.0. &lt;br /&gt;
&lt;br /&gt;
* expecco 18.1: [http://download.exept.de/transfer/h-expecco-18.1.0/Mobile_Testing_Supplement_for_Mac_OS_1.1.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.1.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.8.0.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.11: [http://download.exept.de/transfer/h-expecco-2.11.1/Mobile_Testing_Supplement_for_Mac_OS_1.0.94.tar.bz2 Mobile Testing Supplement für Mac OS (1.0.94)]&lt;br /&gt;
:Diese Version enthält Appium 1.6.4.&lt;br /&gt;
&lt;br /&gt;
* expecco 2.10: [http://download.exept.de/transfer/h-expecco-2.10.0/Mobile_Testing_Supplement_for_Mac_OS_1.0.tar.bz2 Mobile Testing Supplement für Mac OS]&lt;br /&gt;
:Diese Version entält Appium 1.4.16.&lt;br /&gt;
&lt;br /&gt;
Nachdem Herunterladen des Supplements, können Sie es in ein Verzeichnis Ihrer Wahl (z. B. Ihr Home-Verzeichnis) verschieben und dort entpacken. Ein geeigneter Befehl in einer Shell könnte wie folgt aussehen, passen Sie dabei die Versionsnummer entsprechend an:&lt;br /&gt;
&lt;br /&gt;
 tar -xvpf Mobile_Testing_Supplement_for_Mac_OS_1.1.98.tar.bz2&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Ihre Standard-Xcode-Installation verwenden wollen, können Sie Appium direkt über die Datei im &#039;&#039;bin&#039;&#039;-Verzeichnis mit der entsprechenden Versionsnummer starten:&lt;br /&gt;
&lt;br /&gt;
 Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Falls Sie ein anderes Xcode als das als Standard konfigurierte verwenden wollen, müssen Sie Appium den entsprechenden Pfad über die Umgebungsvariable &#039;&#039;DEVELOPER_DIR&#039;&#039; angeben. &lt;br /&gt;
Wenn Sie Xcode z. B. in &#039;&#039;/Applications/Xcode-11.3.app&#039;&#039; installiert haben, müssten Sie Appium so starten:&lt;br /&gt;
&lt;br /&gt;
 DEVELOPER_DIR=&amp;quot;/Applications/Xcode-11.3.app/Contents/Developer&amp;quot; Mobile_Testing_Supplement/bin/start-appium-1.16.0-rc.1&lt;br /&gt;
&lt;br /&gt;
Was als Standard-Xcode-Installation gesetzt ist, zeigt der Befehl:&lt;br /&gt;
&lt;br /&gt;
 xcode-select -p&lt;br /&gt;
&lt;br /&gt;
Wenn Appium Ihre Xcode-Installation nicht findet, erscheint beim Verbinden eine Fehlermeldung in der Art:&lt;br /&gt;
&#039;&#039;&amp;lt;blockquote&amp;gt;org.openqa.selenium.SessionNotCreatedException - A new session could not be created. (Original error: Could not find path to Xcode, environment variable DEVELOPER_DIR set to: /Applications/Xcode.app but no Xcode found)&amp;lt;/blockquote&amp;gt;&#039;&#039;&lt;br /&gt;
Starten Sie in diesem Fall Appium erneut, unter Angabe eines gültigen &#039;&#039;DEVELOPER_DIR&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== WebDriverAgent-Signierung ====&lt;br /&gt;
Zur Automatisierung lädt Appium eine App namens WebDriverAgent auf das Gerät und muss sie dafür signieren können. Dazu brauchen Sie einen Apple-Account und ein entsprechendes Zertifikat. Zur Evaluierung können Sie einen kostenlosen Account verwenden. Dieser hat den Nachteil, dass erstellte Profile nur eine Woche gültig sind und danach neu erstellt werden müssen. Seien Sie auch vorsichtig, wenn Sie sich den Account teilen, da es vorkommen kann, dass Zertifikate widerrufen werden oder durch automatische Generierung ungültig werden. Als Folge können bereits signierte Apps nicht mehr verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie bereits ein entsprechendes Zertifikat mit dem zugehörigen privaten Schlüssel in Ihrer [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac haben, können Sie den WebDriverAgent automatisch signieren lassen. Ansonsten empfiehlt es sich, die Signierung über Xcode einzustellen und zu verwalten.&lt;br /&gt;
&lt;br /&gt;
Schließen Sie zuerst das Gerät, das Sie verwenden möchten, über USB an den Mac an. Stellen Sie sicher, dass sich der Mac und das Gerät im selben Netzwerk befinden, ansonsten kann es beim Verbindungsaufbau mit Appium zu Problemen kommen. Starten Sie Xcode und öffnen Sie &#039;&#039;Preferences&#039;&#039;. Wechseln Sie zur Seite der Accounts und legen Sie einen Eintrag mit Ihrem Account an. Anschließend können Sie auf &#039;&#039;Manage Certificates...&#039;&#039; klicken, um die Zertifikate zu sehen, die zu diesem Account gehören. Zum Ausführen von Tests benötigen Sie ein iOS-Development-Zertifikat und den dazugehörigen privaten Schlüssel. Wenn Sie noch keines besitzen, erstellen Sie eines. Wenn Sie bereits eines haben, aber es nicht in Ihrem Schlüsselbund vorhanden ist (erkennbar an dem Hinweis &amp;quot;Not in Keychain&amp;quot;), können Sie es importieren. Das können Sie über die [https://support.apple.com/de-de/guide/keychain-access/welcome/mac Schlüsselbundverwaltung] auf dem Mac machen, wenn Sie es zuvor aus dem Schlüsselbund exportiert haben, in dem es sich befindet. Das Zertifikat mit dem zugehörigen Schlüssel sollte sich im Schlüsselbund &#039;&#039;Anmeldung&#039;&#039; befinden. Dort kann es als PKCS#12-Datei (Endung typischerweise .p12) exportiert werden. Um ein Zertifikat in Ihren Schlüsselbund zu importieren, wählen Sie im Menü &#039;&#039;Ablage&#039;&#039; die Option &#039;&#039;Objekte importieren&#039;&#039;. Falls Sie nicht wissen, wo das Zertifikat gespeichert ist, können Sie es in Xcode auch widerrufen und in Ihrem Schlüsselbund neu anlegen. Machen Sie das jedoch nur, wenn Sie wissen, dass das alte Zertifikat nicht mehr in Verwendung ist, da es danach nicht mehr benutzt werden kann. Nun sollte Ihr Schlüsselbund ein iOS-Development-Zertifikat enthalten.&lt;br /&gt;
&amp;lt;!---(Ich habe den folgenden Teil mal rausgenommen. Man braucht das nicht, wenn es in Xcode eingestellt ist.) Wählen Sie im Rechtsklick-Menü den Punkt &#039;&#039;Informationen&#039;&#039; aus. Unter den Details des Zertifikats finden Sie die Team-ID, die hier als Organisationseinheit bezeichnet wird. Tragen Sie diese in den Einstellungen des Plugins im Feld &#039;&#039;Team-ID&#039;&#039; ein, siehe [[#Konfiguration_des_Plugins|Konfiguration des Plugins]].--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie nun das WebDriverAgent-Projekt in Xcode. Wenn Sie das Mobile Testing Supplement installiert haben, finden Sie es in dessen Verzeichnis unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Wenn Sie Appium Desktop installier haben, finden Sie es unter&lt;br /&gt;
 &#039;&#039;&amp;lt;nowiki&amp;gt;/Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj&amp;lt;/nowiki&amp;gt;&#039;&#039;&lt;br /&gt;
Sie können einfach im Finder zu der Xcode-Project-Datei navigieren und Sie über einen Doppelklick öffnen. Beachten Sie dabei, dass Sie dabei auf die Anwendung Appium Server GUI einen Kontextklick (Rechtsklick bzw. Strg + Klick) machen und im Menü &#039;&#039;Paketinhalt anzeigen&#039;&#039; auswählen müssen, um in deren Unterverzeichnis zu gelangen.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingWebDriverAgentXcode.png]]&lt;br /&gt;
&lt;br /&gt;
Wählen Sie &#039;&#039;WebDriverAgentLib&#039;&#039; und die Seite &#039;&#039;Signing &amp;amp; Capabilities&#039;&#039; aus. Setzen Sie dort im Abschnitt &#039;&#039;Signing&#039;&#039; die Option &#039;&#039;Automatically manage signing&#039;&#039; und wählen Sie dann ein Team aus. Wechseln Sie nun zu &#039;&#039;WebDriverAgentRunner&#039;&#039; und tun Sie dort dasselbe.&lt;br /&gt;
&amp;lt;!--(Das Folgende scheint nicht mehr aktuell zu sein.) Es sollten an dieser Stelle Fehler angezeigt werden, dass kein Provisioning Profile angelegt oder gefunden wurde. Wechseln Sie deshalb zur Seite &#039;&#039;Build Settings&#039;&#039; und suchen Sie hier im Abschnitt &#039;&#039;Packaging&#039;&#039; den Eintrag &#039;&#039;Product Bundle Identifier&#039;&#039;. Ändern Sie diesen von com.facebook.WebDriverAgentRunner zu etwas, das von Xcode akzeptiert wird, indem Sie den Präfix ändern. Xcode kann nun ein passendes Provisioning Profile generieren und die Fehler auf der General-Seite sollten verschwinden. Danach können Sie Xcode beenden. --&amp;gt;&lt;br /&gt;
Durch das Setzen des Teams sollten die Fehler für den WebDriverAgentRunner verschwinden. Sollte Xcode kein passendes Provisioning Profile für die Bundle ID &#039;&#039;com.facebook.WebDriverAgentRunner&#039;&#039; erstellen können, können Sie diese anpassen, dass sie zu Ihrem Zertifikat passt. Danach können Sie Xcode beenden oder auch, wie weiter unten beschrieben, direkt den Build über Xcode starten, damit das Projekt bereits gebaut ist, wenn Appium es verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie sich nun von expecco eine Verbindung zu Ihrem Gerät aufbauen, wird der WebDriverAgent darauf installiert und gestartet, um anschließend zur zu testenden App zu wechseln. Eventuell muss auf dem Gerät muss der Ausführung des WebDriverAgents vertraut noch werden. Ein Anzeichnen dafür kann sein, dass die App WebDriverAgent zwar auf dem Gerät erscheint und zu starten versucht, danach aber wieder deinstalliert wird. Öffnen Sie dazu während des Verbindungsaufbaus auf dem Gerät in die Einstellungen und dort unter &#039;&#039;Allgemein&#039;&#039; den Eintrag &#039;&#039;Geräteverwaltung&#039;&#039;. Dieser Eintrag ist nur sichtbar, wenn eine Entwickler-App auf dem Gerät installiert ist. Sie müssen daher möglicherweise warten, bis der WebDriverAgent installiert ist, bevor der Eintrag erscheint. Wählen Sie dort den Eintrag Ihres Apple-Accounts und vertrauen Sie ihm. Da der WebDriverAgent wieder deinstalliert wird, wenn der Start nicht funktioniert hat, müssen Sie dies während des Verbindungsaufbaus tun. Falls Ihnen das zu hektisch ist, können Sie auch folgenden Code ausführen:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;xcodebuild -project Mobile_Testing_Supplement/lib/node_modules/appium-1.16.0-rc.1/node_modules/appium-xcuitest-driver/WebDriverAgent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
  xcodebuild -project /Applications/Appium\ Server\ GUI.app/Contents/Resources/app/node_modules/appium/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination &#039;id=&amp;lt;udid&amp;gt;&#039; test&lt;br /&gt;
&lt;br /&gt;
Damit wird der WebDriverAgent auf dem Gerät installiert ohne dass er wieder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Wenn es Probleme beim Installieren des WebDriverAgents gibt, können Sie auch versuchen, den Build über Xcode zu starten. Stellen Sie sicher, dass das richtige Target &#039;&#039;WebDriverAgent&#039;&#039; ausgewählt ist. Fehlermeldungen in Xcode zeigen vielleicht einfacher, wo das Problem liegt. Manchmal hilft es auch, es ein zweites Mal zu versuchen, weil es möglicherweise beim ersten Mal zu lange gedauert hat und abgebrochen wurde. Es kann sein, dass Sie während des Builds mehrmals aufgefordert werden, das Passwort für Ihren Schlüsselbund anzugeben.&lt;br /&gt;
&lt;br /&gt;
[[Datei:WebDriverAgentCodesign.png]]&lt;br /&gt;
&lt;br /&gt;
Lesen Sie auch die Dokumentation von Appium zum [https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md Aufsetzen von Tests mit iOS-Geräten]. In der [https://support.apple.com/en-us/HT204460 Dokumentation von Apple] finden Sie nähere Informationen zum Installieren und Vertrauen von Apps.&lt;br /&gt;
&lt;br /&gt;
== Konfiguration des Plugins ==&lt;br /&gt;
Bevor Sie loslegen, sollten Sie die Einstellungen des Mobile Testing Plugins überprüfen und ggf. anpassen.&lt;br /&gt;
&lt;br /&gt;
Öffnen Sie im Menü den Punkt &amp;quot;&#039;&#039;Extras&#039;&#039;&amp;quot;  &amp;amp;#8594; &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; und dort unter &amp;quot;&#039;&#039;Erweiterungen&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot; (s. Abb.). Standardmäßig werden diese Pfade automatisch gefunden (1). Um einen Pfad manuell anzupassen, deaktivieren Sie den entsprechenden Haken rechts davon. Sie erhalten in einer Drop-down-Liste einige Pfade zur Auswahl. Ist ein eingetragener Pfad falsch oder kann er nicht gefunden werden, wird das Feld rot markiert und es erscheint ein diesbezüglicher Hinweis. Stellen Sie sicher, dass alle Pfade richtig angegeben sind.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingEinstellungen.png | thumb | 400px | Konfiguration des Plugins]]&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;appium&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an mit der Appium in der Kommandozeile gestartet werden kann. Unter Windows wird diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;appium.cmd&amp;lt;/code&amp;gt;&amp;quot; heißen. Dieser Pfad wird benutzt, wenn expecco einen Appium-Server startet.&lt;br /&gt;
*&#039;&#039;&#039;node&#039;&#039;&#039;: Geben Sie hier den Pfad zur ausführbaren Datei an, die Node (auch &amp;quot;Node.js&amp;quot;) startet. Dieser Pfad wird beim Starten eines Servers an Appium weitergegeben, damit Appium ihn unabhängig von der PATH-Variablen findet. Unter Windows heißt diese Datei in der Regel &amp;quot;&amp;lt;code&amp;gt;node.exe&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
*&#039;&#039;&#039;JAVA_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem JDK an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden. Um einzustellen, welches Java von expecco verwendet werden soll, setzen Sie diesen Pfad in den Einstellungen für die Java Bridge.&lt;br /&gt;
*&#039;&#039;&#039;ANDROID_HOME&#039;&#039;&#039;: Geben Sie hier den Pfad zu einem SDK von Android an. Dieser Pfad wird an jeden Appium-Server weitergegeben. Lassen Sie das Feld frei, um den Wert aus der Umgebungsvariablen zu verwenden.&lt;br /&gt;
*&#039;&#039;&#039;adb&#039;&#039;&#039;: Hier steht der Pfad zum adb-Befehl. Unter Windows heißt die Datei adb.exe. Diese wird von expecco beispielsweise verwendet, um die Liste der angeschlossenen Geräte zu erhalten. Diesen Pfad sollten Sie automatisch wählen lassen, da dann der Befehl im ANDROID_HOME-Verzeichnis verwendet wird. Dieser wird auch von Appium verwendet. Falls expecco und Appium jedoch verschiedene Versionen von adb verwenden kann es zu Konflikten kommen.&lt;br /&gt;
*&#039;&#039;&#039;android.bat&#039;&#039;&#039;: Diese Datei wird nur benötigt, um damit den AVD und den SDK Manager zu starten. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
*&#039;&#039;&#039;aapt&#039;&#039;&#039;: Geben Sie hier den Pfad zum aapt-Befehl an. Unter Windows heißt diese Datei &#039;&#039;aapt.exe&#039;&#039;. expecco verwendet aapt nur im Verbindungseditor, um das Paket und die Activities einer apk-Datei zu lesen. Automatisch wird hier die Datei im ANDROID_HOME-Verzeichnis gesucht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingJavaBridgeEinstellungen.png | thumb | 400px | Konfiguration des JDKs]]&lt;br /&gt;
&lt;br /&gt;
Ab expecco 2.11 gibt es das Feld &#039;&#039;Team-ID&#039;&#039;. Wenn Sie iOS-Tests ausführen, tragen Sie hier die Team-ID Ihres Zertifikats ein. Diese wird für jede iOS-Verbindung verwendet, außer Sie setzen den Wert im Einzelfall in den Verbindungseinstellungen um. Wie Sie die Team-ID erhalten, lesen Sie im Abschnitt zur [[#Signierung|Signierung]] ber der Installation auf Mac OS. Mit expecco 2.10 können Sie die Team-ID nur für jede Verbindungseinstellung extra als Capability eintragen. Dazu müssen Sie jedoch die [[#Erweiterte_Ansicht|erweiterte Ansicht]] verwenden. Geben Sie hier die Capability &#039;&#039;xcodeOrgId&#039;&#039; an und setzen Sie als Wert die Team-ID des Zertifikats.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung zur Serveradresse unten auf der Seite bezieht sich auf das Verhalten des Verbindungseditors. Dieser prüft am Ende, ob die Serveradresse auf &#039;&#039;/wd/hub&#039;&#039; endet, da dies die übliche Form ist. Falls nicht, wird in einem Dialog gefragt, wie darauf reagiert werden soll. Das festgelegte Verhalten kann hier eingesehen und verändert werden.&lt;br /&gt;
&lt;br /&gt;
Wechseln Sie ebenfalls zum Eintrag &#039;&#039;Java Bridge&#039;&#039; (s. Abb.). Hier muss der Pfad zu Ihrer Java-Installation angegeben werden, die von expecco benutzt wird. Tragen Sie hier ein JDK ein. Falls Sie unter Windows das aus dem Mobile Testing Supplement verwenden möchten, lautet der Pfad&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;C:\Program Files (x86)\exept\Mobile Testing Supplement\jdk&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie können auch die Systemeinstellungen verwenden.&lt;br /&gt;
&lt;br /&gt;
== Android-Gerät vorbereiten ==&lt;br /&gt;
Wenn Sie ein Android-Gerät unter Windows anschließen benötigen Sie möglicherweise noch einen adb-Treiber für das Gerät. Einen passenden Treiber finden Sie üblicherweise auf der jeweiligen Webseite des Herstellers. Haben Sie den Universal-Treiber aus dem Mobile Testing Supplement installiert, sollte für die meisten Geräte bereits alles funktionieren. In einigen Fällen versucht auch Windows automatisch einen Treiber zu installieren, wenn Sie das Gerät zum ersten mal anschließen.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
===USB-Debugging Einschalten===&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039;&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Appium-Plugin ansteuern können, müssen Sie für dieses Debugging erlauben!&lt;br /&gt;
&lt;br /&gt;
Für Android-Geräte finden Sie diese Option in den Einstellungen unter &#039;&#039;[https://www.droidwiki.org/wiki/Entwickleroptionen Entwickleroptionen]&#039;&#039; mit dem Namen &#039;&#039;[https://www.droidwiki.org/USB-Debugging USB-Debugging]&#039;&#039;. Falls die Entwickleroptionen nicht angezeigt werden, können Sie diese freischalten, indem Sie unter &amp;quot;&#039;&#039;Über das Telefon&#039;&#039;&amp;quot; siebenmal auf &amp;quot;&#039;&#039;Build-Nummer&#039;&#039;&amp;quot; tippen.&lt;br /&gt;
&lt;br /&gt;
===Wach bleiben Aktivieren===&lt;br /&gt;
Aktivieren Sie auch die Funktion &#039;&#039;Wach bleiben&#039;&#039;, damit das Gerät nicht während der Testerstellung oder -ausführung den Bildschirm abschaltet.&lt;br /&gt;
&lt;br /&gt;
Aus Sicherheitsgründen muss USB-Debugging für jeden Computer einzeln zugelassen werden. Beim Verbinden des Geräts mit dem PC über USB müssen Sie dabei am Gerät der Verbindung zustimmen. Falls Sie dies für Ihren Computer noch nicht getan haben, aber auf dem Gerät kein entsprechender Dialog erscheint, kann es helfen, das Gerät aus- und wieder einzustecken. Das kann insbesondere dann passieren, wenn Sie den ADB-Treiber installiert haben während das Gerät bereits über USB angeschlossen war. Falls auch das nicht hilft, öffnen Sie die Benachrichtigungen, indem Sie sie vom oberen Bildschirmrand herunter ziehen. Dort finden Sie die USB-Verbindung und Sie können die Optionen dazu öffnen. Wählen Sie einen anderen Verbindungstypen aus; in der Regel sollten MTP oder PTP funktionieren.&lt;br /&gt;
&lt;br /&gt;
Sie können auch auf einem Emulator testen. Dieser muss nicht gesondert vorbereitet werden, da er bereits für USB-Debugging ausgelegt ist. Es ist sogar möglich, einen Emulator bei Testbeginn zu starten.&lt;br /&gt;
&lt;br /&gt;
Um zu überprüfen, ob ein Gerät, das Sie an Ihren Rechner angeschlossen haben, verwendet werden kann, öffnen Sie den [[#Verbindungseditor|Verbindungseditor]]. Das Gerät sollte dort angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung über WLAN ===&lt;br /&gt;
Es ist auch möglich, Android-Geräte über WLAN zu verbinden. Für Geräte mit Android 11 oder neuer ist dies direkt über WLAN möglich, im anderen Fall müssen Sie das Gerät zuerst über USB verbinden. Ab expecco 22.1 können Sie eine WLAN-Verbindung über den [[Mobile Testing Plugin#Verbindungseditor|Verbindungseditor]] aufbauen. Ansonsten ist es auch über die Eingabeaufforderung möglich.&lt;br /&gt;
==== Drahtlos verbinden über die Eingabeaufforderung mit expecco Versionen vor 22.1 (ab Android 11) ====&lt;br /&gt;
Mit expecco ab Version 22.1 funktioniert das einfacher über den Verbindungseditor.&lt;br /&gt;
&lt;br /&gt;
Erlauben Sie in den Entwickleroptionen des Geräts Debugging über WLAN und öffnen Sie dessen Optionen. Sie müssen zuerst das Gerät mit dem  Rechner koppeln. Wählen Sie dazu &amp;quot;&#039;&#039;Gerät mit einem Kopplungscode koppeln&#039;&#039;&amp;quot;, um einen Kopplungscode und eine IP-Adresse mit Port zu erhalten. Öffnen Sie dann auf dem Rechner die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb pair &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
wobei Sie &amp;lt;tt&amp;gt;&amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Kopplungsport&amp;gt;&amp;lt;/tt&amp;gt; durch die auf dem Gerät angezeigte IP-Adresse &amp;amp; Port ersetzen. Danach werden Sie aufgefordert, den Kopplungscode einzugeben. Wenn alles geklappt hat, sollte sich das Popup auf dem Gerät schließen und der Rechner als gekoppeltes Gerät angezeigt werden. Geben Sie dann in der Eingabeaufforderung ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;:&amp;lt;Debug-Port&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Die IP-Adresse ist hier noch die gleiche wie beim Koppeln, aber der Port ist ein anderer. Beides wird als IP-Adresse &amp;amp; Port auf dem Gerät angezeigt. Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie entweder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden. Häufig wird beim Neustart des Geräts auch die Erlaubnis für das Debugging über WLAN wieder zurückgesetzt und der verwendete Port ändert sich. Die Kopplung bleibt aber bestehen und muss beim nächsten Verbinden nicht noch einmal durchgeführt werden.&lt;br /&gt;
&lt;br /&gt;
==== WLAN Verbindung über USB starten (Android 10 und früher) ====&lt;br /&gt;
Verbinden Sie zunächst das Gerät über USB mit dem Rechner. Öffnen Sie dann die Eingabeaufforderung und geben Sie dort ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit lauscht das Gerät auf eine TCP/IP-Verbindung an Port 5555. Sollten Sie mehrere Geräte angeschlossen oder Emulatoren laufen haben, müssen Sie genauer angeben, welches Gerät Sie meinen. Geben Sie in diesem Fall ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb devices -l&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Sie erhalten eine Liste aller Geräte, wobei die erste Spalte deren Kennung ist. Schreiben Sie dann stattdessen&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb -s &amp;lt;Gerätekennung&amp;gt; tcpip 5555&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
mit der Gerätekennung des gewünschten Geräts. Sie können die USB-Verbindung nun trennen. Jetzt müssen Sie die IP-Adresse Ihres Gerätes in Erfahrung bringen. Sie finden diese üblicherweise irgendwo in den Einstellungen des Geräts, beispielsweise beim Status oder in den WLAN-Einstellungen. Geben Sie dann ein:&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;adb connect &amp;lt;IP-Adresse des Geräts&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
Damit sollte das Gerät nun über WLAN verbunden sein und kann genauso verwendet werden, wie mit USB-Verbindung. Sie können dies überprüfen, indem Sie wieder &amp;lt;tt&amp;gt;adb devices -l&amp;lt;/tt&amp;gt; eingeben oder in expecco den Verbindungsdialog öffnen. In der Liste taucht das Gerät mit seiner IP-Adresse und dem Port auf. Bedenken Sie, dass die WLAN-Verbindung nicht mehr besteht, wenn der ADB-Server oder das Gerät neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung zu einem Emulator ===&lt;br /&gt;
Sie benötigen dazu den Emulator selbst, sowie mindestens ein AVD (Android Virtual Device). Hinweise zu Installation finden Sie in der [https://developer.android.com/studio/run/emulator Android Studio Dokumentation].&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Android Studio bereits mit den Defaulteinstellungen installiert haben &amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;, sollte der Emulator bereits mitinstalliert sein. Falls nicht, wählen Sie in Android Studio &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Manager&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;Android SDK&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;SDK Tools&#039;&#039;&amp;quot; - &#039;&#039;Android Emulator&#039;&#039;&amp;quot;, sowie dort die &amp;quot;&#039;&#039;Platform Tools&#039;&#039;&amp;quot;.&lt;br /&gt;
Alternativ geht das auch über die Kommandzeile mit dem &amp;quot;sdkmanager&amp;quot; Kommando.&lt;br /&gt;
&lt;br /&gt;
Als nächstes benötigen Sie mindestens ein AVD; auch dies geht am einfachsten über den Dialog in Android Studio:&lt;br /&gt;
wählen sie &amp;quot;&#039;&#039;Configure&#039;&#039;&amp;quot; - &amp;quot;&#039;&#039;AVD Manager&#039;&#039;&amp;quot; und folgen den Anweisungen (Deviceauswahl, Platform und Android Version).  &lt;br /&gt;
&lt;br /&gt;
Auch wenn Sie den Emulator automatisieren benötigen sie Appium; installieren Sie dieses entweder mit dem Mobile Testing Supplement, oder direkt von der Appium homepage (https://github.com/appium/appium-desktop/releases).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1)&amp;lt;/sup&amp;gt;Android Studio selbst wird nicht von expecco benötigt; es bietet aber kompfortable Dialoge zum Installieren von Paketen und AVDs.&lt;br /&gt;
&lt;br /&gt;
== iOS-Gerät und App vorbereiten ==&lt;br /&gt;
Das Ansteuern von iOS-Geräten ist nur über einen Mac möglich. Lesen Sie daher auch den Abschnitt zur [[#Mac_OS|Installation unter Mac OS]].&lt;br /&gt;
&lt;br /&gt;
Bevor Sie ein Mobilgerät mit dem Mobile Testing Plugin ansteuern können, müssen Sie für iOS-Geräte ab iOS 8 Debugging erlauben. Aktivieren Sie dazu die Option &#039;&#039;Enable UI Automation&#039;&#039; unter dem Menüpunkt &#039;&#039;Entwickler&#039;&#039; in den Einstellungen des Geräts. Falls Sie den Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen nicht finden, gehen Sie wie folgt vor: Schließen Sie das Gerät über USB an den Mac an. Dabei müssen Sie ggf. am Gerät noch der Verbindung zustimmen. Starten Sie Xcode und wählen Sie dann in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie dort Ihr Gerät aus. Danach sollte der Eintrag &#039;&#039;Entwickler&#039;&#039; in den Einstellungen auf dem Gerät auftauchen. Dazu müssen Sie möglicherweise die Einstellungen beenden und neu starten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Alert.png | thumb | 270px | Beispiel für einen Alert unter iOS]]&lt;br /&gt;
Ein Verbindungsaufbau zu dem Gerät ist nicht möglich solange es bestimmte Alerts zeigt. Ein solcher Alert kann z.&amp;amp;#x202f;B. erscheinen wenn FaceTime aktiviert ist, indem ein Hinweis auf anfallende SMS-Gebühren angezeigt wird (siehe Screenshot). Achten Sie darauf, das Gerät so zu konfigurieren, dass es im Leerlauf keine solchen Alerts zeigt.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.11 und später ===&lt;br /&gt;
Sie können beliebige Apps testen, die auf dem verwendeten Gerät lauffähig oder bereits installiert sind. Wenn die App als Development-Build vorliegt, muss die UDID des Geräts in der App hinterlegt sein. In jedem Fall muss der WebDriverAgent für das Gerät signiert werden. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]] unter Mac OS.&lt;br /&gt;
&lt;br /&gt;
Falls Sie in einem Test den Home-Button verwenden wollen, müssen Sie auf dem Gerät AssistiveTouch aktivieren. Sie finden diese Option in den Einstellungen unter &#039;&#039;Allgemein&#039;&#039; &amp;gt; &#039;&#039;Bedienungshilfen&#039;&#039; &amp;gt; &#039;&#039;AssistiveTouch&#039;&#039;. Platzieren Sie dann das Menü in der Mitte des oberen Bildschirmrands. Sie können das Drücken des Home-Buttons dann mit dem entsprechenden Menüeintrag im Recorder aufzeichnen oder direkt den Baustein &#039;&#039;Press Home Button&#039;&#039; benutzen.&lt;br /&gt;
&lt;br /&gt;
=== expecco 2.10 ===&lt;br /&gt;
Die App, die Sie verwenden wollen, muss als Development-Build vorliegen. Außerdem muss die UDID des Geräts in der App hinterlegt sein.&lt;br /&gt;
&lt;br /&gt;
=== Development-Build signieren ===&lt;br /&gt;
Ein Development-Build einer App ist nur für eine begrenzte Zahl von Geräten zugelassen und kann auf anderen Geräten nicht gestartet werden. Es ist aber möglich, das Zertifikat und die verwendbaren Geräte in einem Development-Build auszutauschen.&lt;br /&gt;
&lt;br /&gt;
* Evaluierung mit Demo-App von eXept:&lt;br /&gt;
:Gerne stellen wir Ihnen eine Demo-App zur Verfügung, die als Development-Build vorliegt und die wir für Ihr Gerät signieren können. Senden Sie dazu bitte Ihrem eXept-Ansprechpartner die UDID Ihres Gerätes zu. Wie Sie die UDID Ihres Gerätes ermitteln können, ist im folgenden Abschnitt beschrieben.&lt;br /&gt;
&lt;br /&gt;
* Eigene App für Ihr Testgerät verwenden:&lt;br /&gt;
:Wenn Sie von den App-Entwicklern einen Development-Build (IPA-Datei) erhalten, der für Ihr Testgerät zugelassen ist, können Sie diesen direkt verwenden. Dazu müssen Sie den Entwicklern die UDID Ihres Geräts mitteilen, damit sie diese eintragen können. &#039;&#039;&#039;Sie können die UDID eines Gerätes mithilfe von Xcode auslesen&#039;&#039;&#039;. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &#039;&#039;Window&#039;&#039; den Eintrag &#039;&#039;Devices&#039;&#039;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wählen Sie Ihr Gerät aus und suchen Sie in Eigenschaften den Eintrag &#039;&#039;Identifier&#039;&#039;. Die UDID ist eine 40-stellige Hexadezimalzahl.&lt;br /&gt;
&lt;br /&gt;
* Extern entwickelte App für Ihr Testgerät umsignieren:&lt;br /&gt;
:Es können auch Apps umsigniert werden, damit Sie auf anderen Geräten lauffähig sind. Dieser Vorgang ist jedoch kompliziert und setzt insbesondere einen Zugang zu einem Apple-Developer-Account voraus. Eine Dokumentation zur Vorgehensweise ist derzeit in Vorbereitung.&lt;br /&gt;
&lt;br /&gt;
:Für die Evaluierung unterstützen wir Sie gerne beim Umsignieren Ihrer App.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Melden Sie sich beim [https://developer.apple.com/ Apple-Webinterface] an. Navigieren Sie zu &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039;. Erzeugen Sie hier ggf. ein Developer-Zertifikat und ein Provisioning Profile für Ihr Gerät und laden Sie beide herunter. Sollten Sie noch keinen Developer Account haben, erstellen Sie hier einen: https://developer.apple.com/enroll/. Hierzu müssen Sie sich mit einer Apple-ID anmelden.&lt;br /&gt;
&lt;br /&gt;
# Team-ID herausfinden (&#039;&#039;Membership&#039;&#039; -&amp;gt; &#039;&#039;Team ID&#039;&#039;)&lt;br /&gt;
# Unter &#039;&#039;Certificates, IDs &amp;amp; Profiles&#039;&#039; Development-Zertifikat auswählen (unter &#039;&#039;+&#039;&#039; anlegen, falls nicht vorhanden) und herunterladen.&lt;br /&gt;
# Unter &#039;&#039;App ID&#039;&#039; Wildcard-App-ID erzeugen, falls nicht vorhanden. App-ID notieren (AppID = Prefix.ID)&lt;br /&gt;
# Gerät hinzufügen, dazu UDID (bzw. &#039;&#039;Identifier&#039;&#039;) des Geräts herausfinden (&#039;&#039;Xcode&#039;&#039; -&amp;gt; &#039;&#039;Window&#039;&#039; (oben in Menüleiste) -&amp;gt; &#039;&#039;Devices&#039;&#039;)&lt;br /&gt;
# Provisionen Profile erstellen: &#039;&#039;iOS App Development&#039;&#039; -&amp;gt; &#039;&#039;AppID&#039;&#039; auswählen -&amp;gt; Zertifikat wählen -&amp;gt; Gerät auswählen -&amp;gt; Profilname anlegen -&amp;gt; Provisioning Profile herunterladen.&lt;br /&gt;
# Das heruntergeladene Zertifikat importieren (&#039;&#039;Downloads&#039;&#039; -&amp;gt; Zertifikat (.cer)&lt;br /&gt;
# SHA1-Fingerabdruck kopieren. Dazu Rechtsklick auf Zertifikat -&amp;gt; &#039;&#039;Information&#039;&#039;, anschließend bis zum Ende der Seite scrollen).&lt;br /&gt;
# Entitlements.plist erstellen (&#039;&#039;Terminal&#039; öffnen -&amp;gt; Downloads/Mobile_Testing_Supplement/bin/gen-entitlements_plist &#039;Team-ID&#039; &#039;App ID&#039; Downloads/Mobile_Testing_Supplement/bin/re-sign-ipa &amp;lt;Pfad zum ipa (z.B. Downloads/expeccoMobileDemo.ipa)&amp;gt; \&lt;br /&gt;
&amp;quot;&amp;lt;Zertifikat (SHA1-Fingerabdruck, z.B. 76 E8 4B E8 78 D5 D7 F9 2E 09 8B D7 E8 FB CE 30 0C F5 D0 EF)&amp;gt;&amp;quot; \&lt;br /&gt;
&amp;lt;Pfad zum Provisionen Profile (z.B. /Users/exept_test/Downloads/dut.mobileprovision)&amp;gt; \&lt;br /&gt;
&amp;lt;Pfad für das Ergebnis-ipa (z.B. Downloads/expeccoMobileDemo_re-signed.ipa)&amp;gt; \&lt;br /&gt;
[Pfad zur entitlements.plist] (z.B. /Users/exept_test/entitlements.plist)&lt;br /&gt;
&lt;br /&gt;
Zum Umsignieren können Sie das entsprechende Skript aus dem Mobile Testing Supplement für Mac OS oder jedes beliebige andere Tool (z.B. isign) verwenden.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weitere Informationen zur Verwendung von iOS-Geräten finden Sie auch in der [http://appium.io/slate/en/master/?java#appium-on-real-ios-devices Dokumentation von Appium].&lt;br /&gt;
&lt;br /&gt;
=== Native iOS-Apps ===&lt;br /&gt;
Sie können auch Apps verwenden, die bereits nativ auf dem Gerät vorhanden sind. Dazu müssen Sie deren Bundle-ID kennen und diese dann in die Verbindungseinstellungen eintragen. Hier eine kleine Auswahl gängiger Apps:&lt;br /&gt;
{| style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
! App&lt;br /&gt;
!&lt;br /&gt;
! Bundle-ID&lt;br /&gt;
|-&lt;br /&gt;
| App Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.AppStore&lt;br /&gt;
|-&lt;br /&gt;
| Calculator&lt;br /&gt;
| &lt;br /&gt;
| com.apple.calculator&lt;br /&gt;
|-&lt;br /&gt;
| Calendar&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilecal&lt;br /&gt;
|-&lt;br /&gt;
| Camera&lt;br /&gt;
| &lt;br /&gt;
| com.apple.camera&lt;br /&gt;
|-&lt;br /&gt;
| Contacts&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileAddressBook&lt;br /&gt;
|-&lt;br /&gt;
| iTunes Store&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileStore&lt;br /&gt;
|-&lt;br /&gt;
| Mail&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilemail&lt;br /&gt;
|-&lt;br /&gt;
| Maps&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Maps&lt;br /&gt;
|-&lt;br /&gt;
| Messages&lt;br /&gt;
| &lt;br /&gt;
| com.apple.MobileSMS&lt;br /&gt;
|-&lt;br /&gt;
| Phone&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobilephone&lt;br /&gt;
|-&lt;br /&gt;
| Photos&lt;br /&gt;
| &lt;br /&gt;
| com.apple.mobileslideshow&lt;br /&gt;
|-&lt;br /&gt;
| Settings&lt;br /&gt;
| &lt;br /&gt;
| com.apple.Preferences&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Weitere Bundle-IDs finden Sie [https://github.com/joeblau/apple-bundle-identifiers hier].&lt;br /&gt;
&lt;br /&gt;
= Beispiele =&lt;br /&gt;
Bei den Demo-Testsuiten für expecco finden Sie auch Beispiele für Tests mit dem Mobile Testing Plugin. Wählen Sie dazu auf dem Startbildschirm die Option &amp;quot;&#039;&#039;Beispiel aus Datei&#039;&#039;&amp;quot; und öffnen Sie den Ordner &amp;quot;&#039;&#039;mobile&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;TestsuiteMobileTestingDemo&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m01_MobileTestingDemo.ets --&amp;gt;&amp;lt;/span&amp;gt; &#039;&#039;m01_MobileTestingDemo.ets&#039;&#039; ==&lt;br /&gt;
Die Testsuite enthält zwei einfache Testpläne: &amp;quot;&#039;&#039;Simple CalculatorTest&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Complex Calculator and Messaging Test&#039;&#039;&amp;quot;. Beide Tests verwenden einen Android-Emulator, den Sie vor Beginn starten müssen. Die Apps, die im Test verwendet werden, gehören zur Grundausstattung des Emulators und müssen daher nicht mehr installiert werden. Da sich die Apps unter jeder Android-Version unterscheiden können, ist es wichtig, dass Ihr Emulator unter Android 6.0 läuft. Außerdem muss die Sprache auf Englisch gestellt sein.&lt;br /&gt;
&lt;br /&gt;
; Simple CalculatorTest&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und gibt die Formel &#039;&#039;2+3&#039;&#039; ein. Das Ergebnis des Rechners wird mit dem erwarteten Wert &#039;&#039;5&#039;&#039; verglichen.&lt;br /&gt;
&lt;br /&gt;
; Complex Calculator and Messaging Test&lt;br /&gt;
: Dieser Test verbindet sich mit dem Taschenrechner und öffnet anschließend den Nachrichtendienst. Dort wartet er auf eine einkommende Nachricht von der Nummer &#039;&#039;15555215556&#039;&#039;, in der eine zu berechnende Formel gesendet wird. Die Nachricht wird zuvor über einen Socket beim Emulator erzeugt. Nach dem Eintreffen der Nachricht wird diese vom Test geöffnet und deren Inhalt gelesen. Danach wird wieder der Taschenrechner geöffnet, die erhaltene Formel eingegeben und das Ergebnis gelesen. Anschließend wechselt der Test wieder zum Nachrichtendienst und sendet das Ergebnis als Antwort.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;m02_expeccoMobileDemo.ets&#039;&#039; und &#039;&#039;m03_expeccoMobileDemoIOS.ets&#039;&#039; ==&lt;br /&gt;
Diese sind Bestandteil des Tutorials zum Mobile Testing Plugin. Der jeweils enthaltene Testfall ist unvollständig und wird im Zuge des Tutorials ergänzt. Lesen Sie dazu den Abschnitt [[#Tutorial|Tutorial]].&lt;br /&gt;
&lt;br /&gt;
= Tutorial =&lt;br /&gt;
Es gibt ein Tutorial, das das grundsätzliche Vorgehen zur Erstellung von Tests mit dem Mobile Testing Plugin beschreibt. Grundlage dafür ist ein mitgeliefertes Beispiel, bestehend aus einer einfachen App und einer expecco-Testsuite.&lt;br /&gt;
&lt;br /&gt;
Sie finden es auf der Seite [[Mobile_Testing_Tutorial|Mobile Testing Tutorial]] in zwei Versionen für Android und für iOS.&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsAndroid&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m02_expeccoMobileDemo.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_Android|Erste Schritte mit Android]]&lt;br /&gt;
* &amp;lt;span id=&amp;quot;FirstStepsIOS&amp;quot;&amp;gt;&amp;lt;!-- Referenced by m03_expeccoMobileDemoIOS.ets --&amp;gt;&amp;lt;/span&amp;gt;[[Mobile_Testing_Tutorial#Erste_Schritte_mit_iOS|Erste Schritte mit iOS]]&lt;br /&gt;
&lt;br /&gt;
= Dialoge des Mobile Testing Plugins =&lt;br /&gt;
== Verbindungseditor ==&lt;br /&gt;
Mithilfe des Verbindungseditors können Sie schnell Verbindungen definieren, ändern oder aufbauen. Je nach Aufgabe weist der Dialog kleine Unterschiede auf und wird unterschiedlich geöffnet:&lt;br /&gt;
*Um eine Verbindung aufzubauen, klicken Sie im GUI-Browser auf &amp;quot;&#039;&#039;Verbinden&#039;&amp;quot;&#039; klicken und wählen dann &amp;quot;&#039;&#039;Mobile Testing&#039;&#039;&amp;quot;.&lt;br /&gt;
*Um eine bestehende Verbindung im GUI-Browser zu ändern oder zu kopieren, wählen Sie diese aus, machen einen Rechtsklick und wählen im Kontextmenü &amp;quot;&#039;&#039;Verbindung bearbeiten&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Verbindung kopieren&#039;&#039;&amp;quot; aus.&lt;br /&gt;
*Wollen Sie Verbindungseinstellungen nicht für den GUI-Browser sondern zur Verwendung in einem Test erstellen, wählen Sie im Menü des Mobile Testing Plugins den Punkt &amp;quot;&#039;&#039;Verbindungseinstellungen erstellen...&#039;&#039;&amp;quot;. Darüber können nur die Einstellungen für eine Verbindung erstellt werden, ohne dass eine Verbindung tatsächlich angelegt wird.&lt;br /&gt;
&lt;br /&gt;
Einige der Schaltflächen sind nur beim Erstellen von Verbindungseinstellungen sichtbar:&lt;br /&gt;
[[Datei:MobileTestingVerbindungseditorMenu.png]]&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen löschen&#039;&#039;&amp;quot;: Setzt alle Einträge zurück. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Datei laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen einer gespeicherten Einstellungsdatei (*.csf). Deren Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen aus Anhang laden&#039;&#039;&amp;quot;: Erlaubt das Öffnen eines Anhangs mit Verbindungseinstellungen aus einem geöffneten Projekt. Diese Einstellungen werden in den Dialog übernommen. Bereits getätigte Eingaben ohne Konflikt bleiben dabei erhalten.&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Datei speichern&#039;&#039;&amp;quot; sowie&lt;br /&gt;
#&amp;quot;&#039;&#039;Einstellungen in Anhang speichern&#039;&#039;&amp;quot;: Hier können Sie die eingetragenen Einstellungen in eine Datei (*.csf) speichern oder als Anhang in einem geöffneten Projekt anlegen. Beide Optionen besitzen ein verzögertes Menü, in dem Sie auswählen können, nur einen bestimmten Teil der Einstellungen zu speichern. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Erweiterte Ansicht&#039;&#039;&amp;quot;: Damit können Sie in die erweiterte Ansicht wechseln, um zusätzliche Einstellungen vorzunehmen. Lesen Sie dazu mehr am Ende des Kapitels. (Nur beim Erstellen von Einstellungen sichtbar.)&lt;br /&gt;
#&amp;quot;&#039;&#039;Hilfe&#039;&#039;&amp;quot;: An der rechten Seite wird ein Hilfetext zum jeweiligen Schritt ein- oder ausgeblendet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Dialog ist in drei Schritte unterteilt. Im ersten Schritt wählen Sie das Gerät, das Sie verwenden möchten, im zweiten Schritt wählen Sie aus, welche App verwendet werden soll und im letzten Schritt erfolgen die Einstellungen zum Appium-Server.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep1&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 1: Gerät auswählen===&lt;br /&gt;
Im oberen Teil erhalten Sie eine Liste aller angeschlossenen Appium-Geräte, die erkannt werden. Mit der Checkbox darunter können Sie die Geräte ausblenden, die zwar erkannt werden, aber nicht bereit sind. Falls Sie ein Gerät eintragen wollen, das nicht angeschlossen ist, können Sie dies mit dem entsprechenden Knopf &amp;quot;&#039;&#039;Android-Gerät eingeben&#039;&#039;&amp;quot; bzw. &amp;quot;&#039;&#039;iOS-Gerät eingeben&#039;&#039;&amp;quot; anlegen. Dazu müssen Sie jedoch die benötigten Eigenschaften Ihres Geräts kennen. Das Gerät wird dann in einer zweiten Geräteliste angelegt und kann dort ausgewählt werden. Wenn keine Liste mit angeschlossenen Elementen angezeigt werden kann, werden stattdessen verschiedene Meldungen angezeigt:&lt;br /&gt;
*Keine Geräte gefunden&lt;br /&gt;
*:expecco konnte kein Android-Geräte finden.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*Keine verfügbaren Geräte gefunden&lt;br /&gt;
*:expecco konnte keine verfügbaren Android-Geräte finden. Es wurden aber nicht verfügbare gefunden, z.B. mit dem Status &amp;quot;unauthorized&amp;quot;.&lt;br /&gt;
*:Um eine Verbindung zu einem Gerät automatisch zu konfigurieren, stellen Sie sicher, dass es&lt;br /&gt;
*:*angeschlossen ist&lt;br /&gt;
*:*eingeschaltet ist&lt;br /&gt;
*:*einen passenden adb-Treiber installiert hat&lt;br /&gt;
*:*für Debugging freigeschaltet ist (siehe unten).&lt;br /&gt;
*:Um nicht verfügbare Geräte anzuzeigen, aktivieren Sie unten diese Option.&lt;br /&gt;
*Verbindung verloren&lt;br /&gt;
*:expecco hat die Verbindung zum adb-Server verloren. Versuchen Sie die Verbindung wieder herzustellen, indem Sie auf den Button klicken.&lt;br /&gt;
*Verbindung fehlgeschlagen&lt;br /&gt;
*:expecco konnte sich nicht mit dem adb-Server verbinden. Möglicherweise läuft er nicht oder der angegebene Pfad stimmt nicht.&lt;br /&gt;
*:Überprüfen Sie die adb-Konfiguration in den Einstellungen und versuchen Sie den adb-Server zu starten und eine Verbindung herzustellen indem Sie auf den Knopf klicken.&lt;br /&gt;
*Verbinden ...&lt;br /&gt;
*:expecco verbindet sich mit dem adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
*adb-Server starten ...&lt;br /&gt;
*:expecco startet den adb-Server. Dies kann einige Sekunden dauern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Bei &amp;quot;&#039;&#039;Automatisierung durch&#039;&#039;&amp;quot; können Sie angeben, welche Automation-Engine verwendet werden soll. Lassen Sie die Einstellung auf &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; wird die entsprechende Capability gar nicht gesetzt. Ansonsten stehen Appium, Selendroid und ab expecco 2.11 XCUITest zur Verfügung. In der Regel wird Selendroid nur für Android-Geräte vor Version 4.1 gebraucht.--&amp;gt;Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt. Wenn Sie Einstellungen für den GUI-Browser eingeben, ist das erst möglich, wenn ein Gerät ausgewählt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;UnlockingDeveloperOptions&amp;quot;&amp;gt;Anmerkung zum Freischalten&amp;lt;/span&amp;gt;: In jüngeren Android Versionen werden die Entwickleroptionen zunächst nicht mehr in den Einstellungen angeboten. Falls ihr Android Gerät in den Einstellungen keinen Eintrag zu &amp;quot;&#039;&#039;Entwickleroptionen&#039;&#039;&amp;quot; zeigt, wählen Sie zunächst den Eintrag &amp;quot;&#039;&#039;Telefoninfo&#039;&#039;&amp;quot;, dann &amp;quot;&#039;&#039;SoftwareVersionsInfo&#039;&#039;&amp;quot; und klicken darin mehrfach auf den Eintrag &amp;quot;&#039;&#039;BuildVersion&#039;&#039;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Chromedriver verwalten ====&lt;br /&gt;
Wenn die App, die Sie bedienen wollen, WebViews mit Chrome benutzt, benötigt Appium Zugriff auf einen passenden Chromedriver. Wenn Sie ein Gerät in der Liste auswählen, können Sie über &amp;quot;&#039;&#039;Chromedriver verwalten&#039;&#039;&amp;quot; sehen, welche Chrome-Versionen auf dem Gerät vorhanden sind und welche Chromedriver-Versionen durch expecco zur Verfügung stehen. Über diesen Dialog können Sie auch benötigte Chromedriver-Versionen herunterladen. Beachten Sie, dass auf dem Gerät verschiedene Chrome-Versionen vorhanden sein können, da die Apps in ihren WebViews nicht die gleiche Chrome-Version verwenden müssen, wie die als Browser installierte. Damit alles funktioniert, sollte der verwendete Chromedriver zur entsprechenden App passen. Sie können den Pfad zum Chromedriver auch am Ende des Verbindungsdialogs in den erstellten Capabilities ändern.&lt;br /&gt;
&lt;br /&gt;
==== WLAN-Android-Geräte verbinden ====&lt;br /&gt;
Sie können sich auch über WLAN zu Android-Geräten verbinden. Dazu muss das Gerät zunächst mit adb verbunden werden, siehe [[Mobile_Testing_Plugin#Verbindung_.C3.BCber_WLAN|Verbindung über WLAN]]. Ab expecco 22.1 bietet der Verbindungseditor hierfür einen Dialog, der Ihnen dabei hilft und den Sie anstatt der Eingabeaufforderung verwenden können. Für Geräte mit Android 11 oder höher können Sie hier das Gerät mit dem Rechner zu koppeln, indem Sie die entsprechenden Parameter angeben und anschließend die Verbindung unter Angabe von IP-Adresse und Port aufbauen. Sie können damit auch für Geräte, die über USB verbunden sind, eine WLAN-Verbindung aufbauen. Wenn Sie das entsprechende Gerät in der Liste auswählen, werden die benötigten Angaben automatisch ausgelesen.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass der Aufbau einer WLAN-Verbindung nicht Teil der Verbindungseinstellungen ist. Wenn Sie mit den erzeugten Einstellungen eine neue Verbindung aufbauen wollen, müssen Sie sicherstellen, dass das Gerät über mit der angegebenen IP-Adresse und dem Port mit adb verbunden ist, damit es gefunden wird. Die ADB-Verbindung geht verloren, wenn der ADB-Server oder das Gerät neu gestartet werden. Die Erlaubnis für das WLAN-Debugging wird beim Neustart des Geräts auch häufig zurückgesetzt und der Debug-Port kann dann wechseln. Daher muss eine WLAN-Verbindung immer manuell hergestellt werden.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep2&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 2: App auswählen===&lt;br /&gt;
Hier können Sie Angaben zur App machen, die getestet werden soll. Dabei können Sie entscheiden, ob Sie eine App verwenden wollen, die bereits auf dem Gerät installiert ist, oder ob für den Test eine App installiert werden soll. Wählen Sie oben den entsprechenden Reiter aus. Je nachdem, ob Sie im vorigen Schritt ein Android- oder ein iOS-Gerät ausgewählt haben, ändert sich die erforderte Eingabe.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Android&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Wenn Sie im ersten Schritt ein angeschlossenes Gerät ausgewählt haben, werden die Pakete aller installierten Apps automatisch abgerufen und Sie können die Auswahl aus den Drop-down-Listen treffen. Die installierten Apps sind in Fremdpakete und Systempakete unterteilt; wählen Sie die entsprechende Paketliste aus. Diese Auswahl gehört nicht zu den Einstellungen, sondern stellt nur die entsprechende Paketliste zur Verfügung. Sie können den Filter benutzen, um die Liste weiter einzuschränken und dann das gewünschte Paket auswählen. Die Activities des ausgwählten Pakets werden ebenfalls automatisch abgerufen und als Drop-down-Liste zur Verfügung gestellt. Wählen Sie die Activity aus, die gestartet werden soll. In der Regel wird automatisch eine Activity aus der Liste eingetragen. Falls Sie kein verbundenes Gerät verwenden, müssen Sie die Eingabe des Pakets und der Activity von Hand vornehmen.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Benutzen Sie einen lokalen Appium-Server, können Sie den rechten Butten benutzen, um zu der Installationsdatei der App zu navigieren und diesen Pfad einzutragen. Wenn möglich werden dabei auch das entsprechende Paket und die Activity in den Feldern darunter eingetragen. Diese Angabe ist aber nicht notwendig.&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;iOS&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;App auf dem Gerät&#039;&#039;&lt;br /&gt;
**:Geben Sie die Bundle-ID einer installierten App an. Sie können die IDs der installierten Apps bspw. mithilfe von Xcode erfahren. Starten Sie dazu Xcode und wählen Sie in der Menüleiste am oberen Bildschirmrand im Menü &amp;quot;&#039;&#039;Window&#039;&#039;&amp;quot; den Eintrag &amp;quot;&#039;&#039;Devices&#039;&#039;&amp;quot;. Es öffnet sich ein Fenster, in dem eine Liste der angeschlossenen Geräte angezeigt wird. Wenn Sie Ihr Gerät auswählen, sehen Sie in der Übersicht eine Auflistung der von Ihnen installierten Apps.&lt;br /&gt;
**&#039;&#039;App installieren&#039;&#039;&lt;br /&gt;
**:Geben Sie bei &amp;quot;&#039;&#039;App&#039;&#039;&amp;quot; den Pfad zu einer App an. Der Pfad muss für den Appium-Server gültig sein, der verwendet wird. Sie können auch eine URL angeben. Zu den Vorraussetzungen an Apps für reale Geräte lesen Sie bitte den Abschnitt [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Geräte und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
Im unteren Teil können Sie festlegen, ob die App beim Verbindungsabbau zurückgesetzt bzw. deinstalliert werden soll, und ob sie initial zurückgesetzt werden soll. Auch hier wird die entsprechende Capability gar nicht gesetzt, wenn Sie &amp;quot;&#039;&#039;(Default)&#039;&#039;&amp;quot; auswählen. Mit &amp;quot;&#039;&#039;Weiter&#039;&#039;&amp;quot; gelangen Sie zum nächsten Schritt.&lt;br /&gt;
&lt;br /&gt;
===&amp;lt;span id=&amp;quot;AppiumConnectionEditorStep3&amp;quot;&amp;gt;&amp;lt;!-- Referenced by AppiumConnectionEditor in Mobile Testing Plugin --&amp;gt;&amp;lt;/span&amp;gt;Schritt 3: Servereinstellungen===&lt;br /&gt;
Im letzten Schritt befindet sich zunächst im oberen Teil eine Liste aller Capabilities, die sich aus Ihren Angaben der vorigen Schritte ergeben. Wenn Sie sich mit Appium auskennen und noch zusätzliche Capabilities setzen möchten, die der Verbindungseditor nicht abdeckt, können Sie durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; in die erweiterte Ansicht gelangen. Lesen Sie dazu den Abschnitt weiter unten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie Einstellungen für den GUI-Browser eingeben, können Sie den &#039;&#039;Verbindungsnamen&#039;&#039; eintragen, mit dem die Verbindung angezeigt wird. Dies ist auch der Name unter dem Bausteine diese Verbindung verwenden können, wenn sie aufgebaut ist. Wenn Sie das Feld frei lassen, wird ein Name generiert. Wenn der Haken für &amp;quot;&#039;&#039;Von expecco gesteuert&#039;&#039;&amp;quot; gesetzt ist, wird expecco einen lokalen Appium-Server an einem freien Port starten, oder einen bereits gestarteten freien Server verwenden. Um einen eigenen Server zu verwenden, schalten Sie diese Funktion ab und geben Sie die entsprechende Adresse ein. Sie erhalten die lokale Standard-Adresse und bereits verwendete Adressen zur Auswahl.&lt;br /&gt;
&lt;br /&gt;
In älteren expecco-Versionen ist der Haken mit &amp;quot;&#039;&#039;Bei Bedarf starten&#039;&#039;&amp;quot; beschriftet. In diesem Fall müssen Sie auch eine Adresse angeben, wenn expecco den Server starten soll. expecco versucht dann beim Verbinden einen Appium-Server an der angegebenen Adresse zu starten, wenn dort noch keiner läuft. Dieser Server wird dann beim Beenden der Verbindung ebenfalls heruntergefahren. Dies funktioniert nur für lokale Adressen. Achten Sie darauf, nur Portnummern zu verwenden, die auch frei sind. Verwenden Sie am besten nur ungerade Portnummern ab dem Standardport 4723. Beim Verbindungsaufbau wird ebenfalls die folgende Portnummer verwendet, wodurch es sonst zu Konflikten kommen könnte. &lt;br /&gt;
&lt;br /&gt;
Je nachdem, wie Sie den Dialog geöffnet haben, gibt es nun verschiedene Schaltflächen um ihn abzuschließen. In jedem Fall haben Sie die Option zu speichern. Dabei öffnet sich ein Dialog, indem Sie entweder ein geöffnet Projekt auswählen können, um die Einstellungen dort als Anhang zu speichern, oder auswählen es in einer Datei zu speichern, die Sie anschließend angeben können. Durch das Speichern wird der Dialog nicht beendet, wodurch Sie anschließend noch eine andere Option auswählen könnten.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie den Editor zum Verbindungsaufbau geöffnet haben, können Sie abschließend auf &amp;quot;&#039;&#039;Verbinden&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;Server starten und verbinden&#039;&#039;&amp;quot; klicken, je nachdem, ob der Haken für den Serverstart gesetzt ist. Für das Ändern oder Kopieren einer Verbindung im GUI-Brower heißt diese Option &amp;quot;&#039;&#039;Übernehmen&#039;&#039;&amp;quot;, da in diesem Fall nur der Verbindungseintrag geändert bzw. neu angelegt wird, der Verbindungsaufbau aber nicht gestartet wird. Das können Sie bei Bedarf anschließend über das Kontextmenü tun. Falls Sie Capabilities einer bestehenden Verbindung geändert haben, fordert Sie anschließend ein Dialog auf zu entscheiden, ob diese Änderungen direkt übernommen werden sollen, indem die Verbindung abgebaut und mit den neuen Verbindungen aufgebaut wird, oder nicht. In diesem Fall werden die Änderungen erst wirksam, nachdem Sie die Verbindung neu aufbauen.&lt;br /&gt;
&lt;br /&gt;
Zur Verwendung des Verbindungseditors lesen Sie auch den entsprechenden Abschnitt im jeweiligen Tutorial in Schritt 1 (Android: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren|Demo ausführen]], iOS: [[Mobile_Testing_Tutorial#Schritt_1:_Demo_ausf.C3.BChren_.28iOS.29|Demo ausführen (iOS)]]).&lt;br /&gt;
&lt;br /&gt;
===Erweiterte Ansicht===&lt;br /&gt;
Die erweiterte Ansicht des Verbindungseditors erhalten Sie entweder durch Klicken auf &amp;quot;&#039;&#039;Bearbeiten&#039;&#039;&amp;quot; im dritten Schritt oder jederzeit über den entsprechenden Menüeintrag, wenn Sie den Editor über das Plugin-Menü gestartet haben. In dieser Ansicht erhalten Sie eine Liste aller eingestellten Appium-Capabilities. Zu dieser können Sie weitere hinzufügen, Einträge ändern oder entfernen. Um eine Capability hinzuzufügen, wählen Sie diese aus der Drop-down-Liste des Eingabefelds aus. In dieser befinden sich alle bekannten Capabilities sortiert in die Kategorien &#039;&#039;Common&#039;&#039;, &#039;&#039;Android&#039;&#039; und &#039;&#039;iOS&#039;&#039;. Haben Sie eine Capability ausgewählt, wird ein kurzer Informationstext dazu angezeigt. Sie können in das Feld auch von Hand eine Capability eingeben. Klicken Sie dann auf &amp;quot;&#039;&#039;Hinzufügen&#039;&#039;&amp;quot;, um die Capabilitiy in die Liste einzutragen. Dort können Sie in der rechten Spalte den Wert setzen. Um einen Entrag zu löschen, wählen Sie diesen aus und klicken Sie auf &amp;quot;&#039;&#039;Entfernen&#039;&#039;&amp;quot;. Mit &amp;quot;&#039;&#039;Zurück&#039;&#039;&amp;quot; verlassen Sie die erweiterte Ansicht.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingErweiterteAnsicht.png]]&lt;br /&gt;
&lt;br /&gt;
== Laufende Appium-Server ==&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie den Eintrag &amp;quot;&#039;&#039;Appium-Server...&#039;&#039;&amp;quot;. Mit diesem öffnen Sie ein Fenster mit einer Übersicht aller Appium-Server, die von expecco gestartet wurden und auf welchem Port diese laufen. Durch Klicken auf das Icon in der Spalte &amp;quot;&#039;&#039;Log anzeigen&#039;&#039;&amp;quot; können Sie das Logfile des entsprechenden Servers anschauen. Dieses wird beim Beenden des Servers wieder gelöscht. Mit den Icons in der Spalte &amp;quot;&#039;&#039;Beenden&#039;&#039;&amp;quot; kann der entsprechenden Server beendet werden. Allerdings wird dies verhindert, wenn expecco über diesen Server noch eine offene Verbindung hat. Für welche Verbindung ein Server verwendet wird, sehen Sie in der rechten Spalte. Steht dort &#039;&#039;&amp;lt;idle&amp;gt;&#039;&#039; wird er zur Zeit nicht von expecco verwendet.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingAppiumServer.png]]&lt;br /&gt;
&lt;br /&gt;
Beim Öffnen des Editors um eine Appium-Verbindung aufzubauen, wird direkt ein Appium-Server gestartet, um den folgenden Verbindungsaufbau zu beschleunigen. Zu diesem Zweck hält sich expecco auch immer einen freien Appium-Server offen. Weitere laufende Server, die nicht mehr verwendet werden, werden jedoch nach einiger Zeit automatisch beendet.&lt;br /&gt;
&lt;br /&gt;
Im Menü des Mobile Testing Plugins finden Sie auch den Eintrag &amp;quot;&#039;&#039;Alle Verbindungen und Server beenden&#039;&#039;&amp;quot;. Dies ist für den Fall gedacht, dass Verbindungen oder Server auf andere Weise nicht beendet werden können. Beenden Sie Verbindungen wenn möglich immer im GUI-Browser oder durch Ausführen eines entsprechenden Bausteins. Server, die Sie in der Server-Übersicht gestartet haben, beenden Sie dort; Server, die mit einer Verbindung gestartet wurden, werden automatisch mit dieser beendet.&lt;br /&gt;
&lt;br /&gt;
Beachten Sie, dass in der Übersicht nur Server aufgelistet sind, die von expecco gestartet und verwaltet werden. Mögliche andere Appium-Server, die auf andere Art gestartet wurden, werden nicht erkannt.&lt;br /&gt;
&lt;br /&gt;
== Recorder ==&lt;br /&gt;
Besteht im GUI-Browser eine Verbindung zu einem Gerät, kann der integrierte Recorder verwendet werden, um mit diesem Gerät einen Testabschnitt aufzunehmen. Sie starten den Recorder, indem Sie im GUI-Browser die entsprechende Verbindung auswählen und dann auf den Aufnahme-Knopf klicken. Für den Recorder öffnet sich ein neues Fenster. Die aufgezeichneten Aktionen werden im Arbeitsbereich des GUI-Browsers angelegt. Daher ist es möglich, das Aufgenommene parallel zu editieren.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingRecorder.png|caption|]]&lt;br /&gt;
&lt;br /&gt;
====Komponenten des Recorderfensters====&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme fortsetzen/pausieren&#039;&#039;&#039;: Über das rechte Symbol können Sie die Aufnahme pausieren. Sie sehen dann ein großes Pause-Symbol in der Anzeige. Alle Aktionen, die Sie währenddessen im Recorder machen werden zwar ausgeführt, es werden aber keine Bausteine aufgezeichnet. Über das linke Symbol können Sie dann wieder in den normalen Aufnahmemodus wechseln.&lt;br /&gt;
#&#039;&#039;&#039;Aufnahme stoppen&#039;&#039;&#039;: Stoppt die Aufnahme und schließt das Recorderfenster.&lt;br /&gt;
#&#039;&#039;&#039;Aktualisieren&#039;&#039;&#039;: Holt das aktuelle Bild und den aktuellen Elementbaum vom Gerät. Dies wird nötig, wenn das Gerät zur Ausführung einer Aktion länger braucht oder sich etwas ohne das Anstoßen durch den Recorder ändert. Seit expecco 21.2 gibt es hier zusätzlich ein Untermenü, mit dem automatisches Aktualisieren angeschaltet werden kann, indem im Hintergrund auf Änderungen geprüft wird (siehe auch &#039;&#039;Automatisches Aktualisieren&#039;&#039; weiter unten).&lt;br /&gt;
#&#039;&#039;&#039;Follow-Mouse&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird im GUI-Browser ausgewählt.&lt;br /&gt;
#&#039;&#039;&#039;Element-Highlighting&#039;&#039;&#039;: Das Element unter dem Mauszeiger wird rot umrandet.&lt;br /&gt;
#&#039;&#039;&#039;Elemente einzeichnen&#039;&#039;&#039;: Die Rahmen aller Elemente der Ansicht werden angezeigt.&lt;br /&gt;
#&#039;&#039;&#039;Werkzeuge&#039;&#039;&#039;: Auswahl, mit welchem Werkzeug aufgenommen werden soll. Die gewählte Aktion wird bei einem Klick auf die Anzeige ausgelöst. Dabei stehen folgende Aktionen zur Verfügung:&lt;br /&gt;
#*Aktionen auf Elemente:&lt;br /&gt;
#**Klicken: Kurzer Klick auf das Element, über dem der Cursor steht. Zur genaueren Bestimmung, welches Element verwendet wird, benutzen Sie die Funktion Follow-Mouse oder Element-Highlighting.&lt;br /&gt;
#**Antippen mit Dauer (Element): Ähnlich zum Klicken, nur dass zusätzlich die Dauer des Klicks aufgezeichnet wird. Dadurch sind auch längere Klicks möglich.&lt;br /&gt;
#**Antippen mit Position (Element): Ähnlich zum Klicken, aber zusätzlich wird die Position innerhalb des Elements aufgenommen. Die Position kann relativ zur Größe des Elements aufgenommen werden oder, wenn Sie dabei Strg gedrückt halten, absolut zur linken oberen Ecke des Elements.&lt;br /&gt;
#**Text setzen: Ermöglicht das Setzen eines Textes in Eingabefelder.&lt;br /&gt;
#**Text löschen: Löscht den Text eines Eingabefelds.&lt;br /&gt;
#*Aktionen auf das Gerät:&lt;br /&gt;
#**Antippen (Bildschirm): Löst einen Klick auf die Bildschirmposition aus.&lt;br /&gt;
#**Antippen mit Dauer (Bildschirm): Löst einen Klick auf die Bildschirmposition aus, bei dem auch die Dauer berücksichtigt wird.&lt;br /&gt;
#**Wischen: Wischen in einer geraden Linie vom Punkt des Drückens des Mausknopfes bis zum Loslassen. Die Dauer wird ebenfalls aufgezeichnet.&lt;br /&gt;
#:Beachten Sie bei diesen Aktionen, dass das Ergebnis sich auf verschiedenen Geräten unterscheiden kann, bspw. bei verschiedenen Bildschirmauflösungen.&lt;br /&gt;
#*Erstellen von Testablauf-Bausteinen&lt;br /&gt;
#**Attribut prüfen: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Das Ergebnis triggert den entsprechenden Ausgang.&lt;br /&gt;
#**Attribut zusichern: Vergleicht den Wert eines festgelegten Attributs des Elements mit einem vorgegebenen Wert. Bei Ungleichheit schlägt der Test fehl.&lt;br /&gt;
#**Attribut holen: Liest den aktuellen Wert eines Attributs aus.&lt;br /&gt;
#*Automatisch&lt;br /&gt;
#:Ist das Auto-Werkzeug ausgewählt, können alle Aktionen durch spezifische Eingabeweise benutzt werden: &#039;&#039;Klicken&#039;&#039;, &#039;&#039;Element antippen&#039;&#039; und &#039;&#039;Wischen&#039;&#039; funktionieren weiterhin durch Klicken, wobei sie anhand der Dauer und der Bewegung des Cursors unterschieden werden. Um ein &#039;&#039;Antippen&#039;&#039; auszulösen, halten Sie beim Klicken Strg gedrückt. Die übrigen Aktionen erhalten Sie durch einen Rechtsklick auf das Element in einem Kontextmenü.&lt;br /&gt;
#&#039;&#039;&#039;Kontext-Aktionen&#039;&#039;&#039;: Hier können Sie Aktionen aufzeichnen, die Kontexte betreffen:&lt;br /&gt;
#*Zu Kontext wechseln: Bietet eine Liste der aktuell verfügbaren Kontexte und Sie können auswählen, zu welchem gewechselt werden soll.&lt;br /&gt;
#*Aktuellen Kontext holen: Holt den Handle des aktuellen Kontexts.&lt;br /&gt;
#*Kontext-Handles holen: Holt eine Liste aller aktuell verfügbaren Kontext-Handles.&lt;br /&gt;
#&#039;&#039;&#039;Softkeys&#039;&#039;&#039;: Nur unter Android. Simuliert das Drücken der Knöpfe Zurück, Home, Fensterliste und Power.&lt;br /&gt;
#&#039;&#039;&#039;Home-Button&#039;&#039;&#039;: Nur unter iOS ab expecco 2.11. Ermöglicht das Drücken des Home-Buttons. Vor expecco 19.2 funktioniert es nur, wenn AssistiveTouch aktiviert ist und sich das Menü in der Mitte des oberen Bildschirmrands befindet. Ab expecco 19.2 verwendet die Funktion kein AssistiveTouch mehr.&lt;br /&gt;
#&#039;&#039;&#039;Hilfe&#039;&#039;&#039;: Öffnet diese Online-Dokumentation auf der allgemeinen Seite zu [[GuiBrowser_Recorder|GUI-Browser Recordern]].&lt;br /&gt;
#&#039;&#039;&#039;Anzeige&#039;&#039;&#039;: Zeigt einen Screenshot des Geräts. Aktionen werden mit der Maus je nach Werkzeug ausgelöst. Wenn eine neue Aktion eingegeben werden kann, hat das Fenster einen grünen Rahmen, sonst ist er rot.&lt;br /&gt;
#&#039;&#039;&#039;Fenster an Bild anpassen&#039;&#039;&#039;: Ändert die Größe des Fensters so, dass der Screenshot vollständig angezeigt werden kann.&lt;br /&gt;
#&#039;&#039;&#039;Bild an Fenster anpassen&#039;&#039;&#039;: Skaliert den Screenshot auf eine Größe, mit der er die volle Größe des Fensters ausnutzt.&lt;br /&gt;
#&#039;&#039;&#039;Ansicht anpassen&#039;&#039;&#039;: Öffnet einen Dialog um die Ansicht anzupassen, falls expecco das Bild nicht richtig darstellt. Sie können die Skalierung anpassen oder das Bild um 90° drehen.&lt;br /&gt;
#&#039;&#039;&#039;Ausrichtung anpassen&#039;&#039;&#039;: Korrigiert das Bild, falls dieses auf dem Kopf stehen sollte. Über den Pfeil rechts daneben kann das Bild auch um 90° gedreht werden, falls dies einmal nötig sein sollte. Ab expecco 19.1 finden Sie diese Funktion in &#039;&#039;Ansicht anpassen&#039;&#039;. Die Ausrichtung des Bildes ist für die Funktion des Recorders unerheblich, dieser arbeitet ausschließlich auf den erhaltenen Elementen.&lt;br /&gt;
#&#039;&#039;&#039;Skalierung&#039;&#039;&#039;: Ändert die Skalierung des Screenshots.&lt;br /&gt;
#&#039;&#039;&#039;Meldungen&#039;&#039;&#039;: Zeigt den Pfad des ausgewählten Elements oder andere Meldungen an. Es gibt ein Kontextmenü, um eine Liste der vorigen Meldungen zu sehen.&lt;br /&gt;
&lt;br /&gt;
====Verwendung====&lt;br /&gt;
Mit jedem Klick im Fenster wird eine Aktion ausgelöst und im Arbeitsbereich des GUI-Browsers aufgezeichnet. Dort können Sie das Aufgenommene abspielen, editieren oder daraus einen neuen Baustein erstellen.&lt;br /&gt;
Aktionen zum Auslösen von Sofkeys finden Sie direkt in der Menüleiste (s.o.). Um Aktionen auf Elemente aufzuzeichen, ändern Sie entweder die Auswahl des Werkzeugs in der Menüleiste (s.o.) und klicken dann auf das Element oder wählen Sie die entsprechende Aktion aus dem Kontextmenü durch einen Rechtsklick auf das entsprechende Element aus. Für Texteingabe ist es zudem möglich, den Cursor über dem Element zu platzieren und den Text einzugeben. Dabei öffnet sich der Eingabedialog für diese Aktion.&lt;br /&gt;
Zur Verwendung des Recorders lesen Sie auch Schritt 2 im Tutorial ([[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen|Android]] bzw. [[Mobile_Testing_Tutorial#Schritt_2:_Einen_Baustein_mit_dem_Recorder_erstellen_.28iOS.29|iOS]]).&lt;br /&gt;
&lt;br /&gt;
====Elemente verbergen====&lt;br /&gt;
Ab expecco 21.2 gibt es im Kontextmenü außerdem die Möglichkeit, das ausgewählte Element im Recorder zu verbergen. Das bedeutet, dass dieses Element fortan nicht mehr ausgewählt werden kann. Diese Funktion eignet sich dazu, Elemente zu ignorieren, die im Vordergrund liegen, um auf Elemente darunter zugreifen zu können. Um diesen Zustand wieder rückgängig zu machen, müssen Sie das entsprechende Element im Baum des GUI-Browsers finden, dort gibt es im Kontextmenü ebenfalls einen solchen Eintrag.&lt;br /&gt;
&lt;br /&gt;
====Automatisches Aktualisieren====&lt;br /&gt;
Der Recorder zeigt kein Livebild des Geräts sondern nur eine Momentaufnahme. Um mit der Anzeige auf dem Gerät übereinzustimmen muss daher nach Änderungen aktualisiert werden. Der Recorder aktualisiert sich automatisch, nachdem er eine Aktion ausgeführt hat. Ab expecco 20.2 sind zudem weitere automatische Updates möglich. Sie können Sie im Menü &#039;&#039;Fenster&#039;&#039; aktivieren.&lt;br /&gt;
&lt;br /&gt;
Zum einen kann kurze Zeit nach dem Ausführen einer Aktion überprüft werden, ob es noch Änderungen nach der ersten Aktualisierung gegeben hat, damit in diesem Fall eine zweite Aktualisierung stattfinden kann. Dies soll das Problem beheben, dass der Recorder nach einer Aktion nicht aktuell ist, weil die Aktualisierung zu früh stattgefunden hat.&lt;br /&gt;
&lt;br /&gt;
Zum anderen kann eine periodische Aktualisierung eingeschaltet werden. Nach einem einstellbaren Interval wird der Recorder automatisch aktualisiert, sollte es Änderungen geben. Dadurch ist die Anzeige im Recorder immer weitgehend aktuell, allerdings entsteht dadurch auch ein Mehraufwand was die Kommunikation mit dem Gerät betrifft.&lt;br /&gt;
&lt;br /&gt;
== AVD Manager und SDK Manager ==&lt;br /&gt;
AVD Manager und SDK Manager sind beides Anwendungen von Android. Im Menü des Mobile Testing Plugins bietet expecco die Möglichkeit, diese zu starten. Ansonsten finden Sie diese Programme bei Ihrer Android-Installation. Mit dem AVD Manager können Sie AVDs, also Konfigurationen für Emulatoren, erstellen, bearbeiten und starten. Mit dem SDK Manager erhalten Sie einen Überblick über Ihre Android-Installation und können diese bei Bedarf erweitern.&lt;br /&gt;
&lt;br /&gt;
= Hybrid-Apps und WebViews =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;!!! WICHTIGER HINWEIS - Wenn Sie Probleme haben, auf den Webview zu wechseln, geben Sie bitte unter den Android Einstellungen - Apps -Standard Apps &amp;quot;Chrome&amp;quot; als &amp;quot;Browser-App&amp;quot; an !!!&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Hybrid-Apps enthalten neben den Plattform-nativen Elementen weitere Elemente, die in einen WebView eingebunden sind. Diese Elemente können ebenfalls bedient werden, allerdings muss zuvor in den entsprechenden Kontext gewechselt werden. Mit dem Baustein &amp;quot;&#039;&#039;Get Current Context&#039;&#039;&amp;quot; erhalten Sie den aktuellen Kontext. Zu Beginn ist dies &amp;quot;&#039;&#039;NATIVE_APP&#039;&#039;&amp;quot;, also der Kontext der nativen Elemente. Mit dem Baustein &amp;quot;&#039;&#039;Get Context Handles&#039;&#039;&amp;quot; bekommen Sie eine Collection aller vorhandenen Kontexte. Gibt es einen WebView-Kontext, so heißt dieser &amp;quot;&#039;&#039;WEBVIEW_1&#039;&#039;&amp;quot; oder &amp;quot;&#039;&#039;WEBVIEW_&amp;lt;package&amp;gt;&#039;&#039;&amp;quot; mit dem Paket des WebViews. Es kann auch mehrere WebView-Kontexte geben. Zu jedem WebView-Kontext gibt es im nativen Kontext ein entsprechendes WebView-Element. Mit dem Baustein &amp;quot;&#039;&#039;Switch to Context&#039;&#039;&amp;quot; können Sie in einen solchen Kontext wechseln und haben fortan nur Zugriff auf die Elemente in diesem Kontext.&lt;br /&gt;
&lt;br /&gt;
Im GUI-Browser werden zum einen oben im Baum die vorhandenen Kontexte angezeigt, zum anderen wird der Baum eines Kontexts unterhalb des entsprechenden WebView-Elements eingefügt.&lt;br /&gt;
&lt;br /&gt;
= XPath anpassen mithilfe des GUI-Browsers =&lt;br /&gt;
Bausteine, die auf einem Gerät fehlerfrei funktionieren, tun dies auf anderen Geräten möglicherweise nicht. Auch können kleine Änderungen der App dazu führen, dass ein Baustein nicht mehr den gewünschten Effekt hat. Man sollte einen Baustein daher so robust formulieren, dass er für eine Vielzahl von Geräten verwendet werden kann und kleine Anpassungen an der App verkraftet. Dazu muss man das grundlegende Funktionsprinzip der Adressierung verstehen. Dies wird im Folgenden am Beispiel der App aus dem Tutorial erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Ansicht der App setzt sich aus einzelnen Elementen zusammen. Dazu gehören die Schaltflächen &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; und &amp;quot;&#039;&#039;Verify&#039;&#039;&amp;quot;, das Eingabefeld der Zahl &amp;quot;&#039;&#039;4006381333986&#039;&#039;&amp;quot; und das Ergebnisfeld, in dem OK erscheint, wie auch alle anderen auf der Anzeige sichtbaren Dinge. Diese sichtbaren Elemente sind in unsichtbare Strukturelemente eingebettet. Alle Elemente zusammen sind in einer zusammenhängenden Hierarchie, dem Elementbaum, organisiert.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingGUIBrowser.png | frame | left | Abb. 1: Funktionen des GUI-Browsers]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot;&amp;gt;&lt;br /&gt;
Sie können sich diesen Baum im GUI-Browser ansehen. Wechseln Sie dazu in den GUI-Browser (Abb. 1) und starten Sie eine beliebige Verbindung. Sobald die Verbindung aufgebaut ist, können Sie den gesamten Baum aufklappen (1) (Klick bei gedrückter Strg-Taste). Er enthält alle Elemente der aktuellen Seite der App.&lt;br /&gt;
&lt;br /&gt;
Ein Baustein, der nun ein bestimmtes Element verwendet, muss dieses eindeutig angeben, indem er dessen Position im Elementbaum mit einem Pfad im XPath-Format beschreibt. Dieses Format ist ein verbreiteter Web-Standard für XML-Dokumente und -Datenbanken, eignet sich aber genauso für Pfade im Elementbaum.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie ein Element im Baum auswählen, wird unten der von expecco automatisch generierte XPath (2) für das Element angezeigt, der auch beim Aufzeichnen verwendet wird. Oberhalb davon in der Mitte des Fensters befindet sich eine Liste der Eigenschaften (3) des ausgewählten Elements. Man nennt diese Eigenschaften auch Attribute. Sie beschreiben das Element näher wie beispielsweise seinen Typ, seinen Text oder andere Informationen zu seinem Zustand. Links unten können Sie zur besseren Orientierung im Baum die &#039;&#039;Vorschau&#039;&#039; (4) aktivieren, um sich den Bildausschnitt des Elements anzeigen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Der Elementbaum für gleiche Ansicht einer App kann sich je nach Gerät unterscheiden. Es sind diese Unterschiede, die verhindern, eine Aufnahme von einem Gerät unverändert auch auf allen anderen Geräten abzuspielen: Ein XPath, der im einen Elementbaum ein bestimmtes Element identifiziert, beschreibt nicht unbedingt das gleiche Element im Elementbaum auf einem anderen Gerät. Es kann stattdessen passieren, dass der XPath auf kein Element, auf ein falsches Element oder auf mehrere Elemente passt. Dann schlägt der Test fehl oder er verhält sich unerwartet.&lt;br /&gt;
&lt;br /&gt;
Man könnte natürlich für jedes Gerät einen eigenen Testfall schreiben. Das brächte aber unverhältnismäßigen Aufwand bei Testerstellung und -wartung mit sich. Das Problem lässt sich auch anders lösen, da ein jeweiliges Element nicht nur durch genau einen XPath beschrieben wird. Vielmehr erlaubt der Standard mithilfe verschiedener Merkmale unterschiedliche Beschreibungen für ein und dasselbe Element zu formulieren. Das Ziel ist daher, einen Pfad zu finden, der auf allen für den Test verwendeten Geräten funktioniert und überall eindeutig zum richtigen Element führt.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel besteht die Verbindung zur Android-App aus dem Tutorial und der Eintrag des &amp;quot;&#039;&#039;GTIN-13&#039;&#039;&amp;quot;-Buttons ist ausgewählt (5). Dessen automatisch generierter XPath (2) kann beispielsweise so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[@resource id=&#039;android:id/content&#039;]/android.widget.RelativeLayout/android.widget.Button[@resource-id=&#039;de.exept.expeccomobiledemo:id/gtin_13&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Er ist offensichtlich lang und unübersichtlich. Der sehr viel kürzere Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@text=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
führt zum selben Element.&lt;br /&gt;
&lt;br /&gt;
Für die iOS-App lautet der automatisch generierte XPath für diesen Button beispielsweise&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/XCUIElementTypeApplication/XCUIElementTypeWindow[1]/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
bzw.&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//AppiumAUT/UIAApplication/UIAWindow[1]/UIAButton[2]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und kann kürzer als&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//*[@name=&#039;GTIN-13 (EAN-13)&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Sie können den Pfad entsprechend im GUI-Browser ändern und durch &amp;quot;&#039;&#039;Pfad überprüfen&#039;&#039;&amp;quot; (6) feststellen, ob er weiterhin auf das ausgewählte Element zeigt, was expecco mit &amp;quot;&#039;&#039;Verify Path: OK&#039;&#039;&amp;quot; (7) bestätigen sollte. Der erste, sehr viel längere Pfad, beschreibt den gesamten Weg vom obersten Element des Baumes bis hin zum gesuchten Button. Der zweite Pfad hingegen wählt mit &amp;quot;*&amp;quot; zunächst sämtliche Elemente des Baumes und schränkt die Auswahl dann auf genau die Elemente ein, die ein &#039;&#039;text&#039;&#039;- bzw. &#039;&#039;name&#039;&#039;-Attribut mit dem Wert &amp;quot;&#039;&#039;GTIN-13 (EAN-13)&#039;&#039;&amp;quot; besitzen, in unserem Fall also genau der eine Button, den wir suchen.&lt;br /&gt;
&lt;br /&gt;
Im folgenden werden Android-ähnliche Pfade zur Veranschaulichung verwendet. Die Elemente in iOS-Apps heißen zwar anders, wodurch andere Pfade entstehen; das Prinzip ist jedoch das gleiche.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum1.png | frame | Abb. 2: Elementbaum einer fiktiven App]]&lt;br /&gt;
&lt;br /&gt;
Sie können solche Pfade mit Hilfe weniger Regeln selbst formulieren. Sehen Sie sich den einfachen Baum einer fiktiven Android-App in Abb. 2 an: Die Einrückungen innerhalb des Baumes geben die Hierarchie der Elemente wieder. Ein Element ist ein &#039;&#039;Kind&#039;&#039; eines anderen Elementes, wenn jenes andere Element das nächsthöhere Element mit einem um eins geringeren Einzug ist. Jenes Element ist das &#039;&#039;Elternelement&#039;&#039; des Kindes. Sind mehrere untereinander stehende Elemente gleich eingerückt, so sind sie also alle Kinder desselben Elternelements.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad durch alle Ebenen der Hierarchie zum TextView-Element ist nun:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Elemente sind mit Schrägstrichen voneinander getrennt. Es fällt auf, dass der Name des ersten Elements nicht mit dem im Baum übereinstimmt. Das oberste Element in der Hierarchie heißt immer &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; (für iOS wäre es &amp;quot;&#039;&#039;AppiumAUT&#039;&#039;&amp;quot;), expecco zeigt im Baum stattdessen den Namen der Verbindung an, damit man mehrere Verbindungen voneinander unterscheiden kann. Die weiteren Elemente tragen jeweils das Präfix &amp;quot;&#039;&#039;android.widget.&#039;&#039;&amp;quot;, das im Baum zur besseren Übersicht nicht angezeigt wird. Bei IOS gibt es kein Präfix, das durch einen Punkt abgetrennt wäre, expecco 2.11 blendet aber entsprechend &amp;quot;&#039;&#039;XCUIElementType&#039;&#039;&amp;quot; am Anfang aus. Mit jedem Schrägstrich führt der Pfad über eine Eltern-Kind-Beziehung in eine tiefere Hierarchie-Ebene, d. h. &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; ist ein Kindelement von &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot;, &amp;quot;&#039;&#039;LinearLayout&#039;&#039;&amp;quot; ist ein Kind von &amp;quot;&#039;&#039;FrameLayout&#039;&#039;&amp;quot; usw. Die in eckigen Klammern geschriebenen Wörter dienen nur als Orientierungshilfe im Baum. Sie gehören nicht zum Typ.&lt;br /&gt;
&lt;br /&gt;
Ein Pfad muss nicht beim Element &amp;quot;&#039;&#039;hierarchy&#039;&#039;&amp;quot; beginnen. Man kann den Pfad beginnend mit einem beliebigen Element des Baumes bilden. Man kann also verkürzt auch&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
schreiben. Der Pfad führt zum selben &amp;quot;&#039;&#039;TextView&#039;&#039;&amp;quot;-Element, da es nur ein Element dieses Typs gibt. Anders verhält es sich bei dem Pfad&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da es zwei Elemente vom Typ &amp;quot;&#039;&#039;Button&#039;&#039;&amp;quot; gibt, passt dieser Pfad auf zwei Elemente, nämlich den Button, der mit &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; markiert ist, und den &#039;&#039;Button&#039;&#039;, der mit &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; markiert ist. Es würde an dieser Stelle aber auch nicht helfen den langen Pfad von &#039;&#039;hierarchy&#039;&#039; aus beginnend anzugeben. Um einen mehrdeutigen Pfad weiter zu differenzieren, kann man explizit ein Element aus einer Menge wählen, indem man den numerischen Index in eckigen Klammern dahinter schreibt. Der Pfad aus dem obigen Beispiel lässt sich damit so anpassen, dass er eindeutig auf den &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; weist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[1].&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ihnen fällt sicher auf, dass der Index eine 1 ist obwohl das zweite Element gemeint ist. Das kommt daher, dass die Zählung bei 0 beginnt. Der Button mit der Markierung &amp;quot;An&amp;quot; hat also die Nummer 0 und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Nummer 1.&lt;br /&gt;
&lt;br /&gt;
Dieser Ansatz, einen expliziten Index zu verwenden, hat zwei Nachteile: Zum einen lässt sich an dem Pfad nur schwer ablesen welches Element gemeint ist, zum andern ist der Pfad sehr empfindlich schon gegenüber kleinsten Änderungen, wie zum Beispiel dem Vertauschen der beiden &#039;&#039;Button&#039;&#039;-Elemente oder dem Einfügen eines weiteren &#039;&#039;Button&#039;&#039;-Elements in der App.&lt;br /&gt;
&lt;br /&gt;
Es wäre daher wünschenswert, das gemeinte Element über eine ihm charakteristische Eigenschaft wie einen Attributwert, zu adressieren. Für Android-Apps eignet sich hierfür häufig das Attribut &amp;quot;&#039;&#039;resource-id&#039;&#039;&amp;quot;. Im Idealfall muss bei der Entwicklung der App darauf geachtet werden, dass jedes Element eine eindeutige Id erhält. Die &#039;&#039;resource-id&#039;&#039; hat den großen Vorteil, dass sie unabhängig vom Text des Elements oder der Spracheinstellung des Geräts ist. Für iOS-Apps kann entsprechend das Attribut &amp;quot;&#039;&#039;name&#039;&#039;&amp;quot; verwendet werden, wenn es von der App sinnvoll gesetzt wird. Der XPath-Standard erlaubt solche Auswahlbedingungen zu einem Element anzugeben. Angenommen, der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Aus&#039;&#039;&amp;quot; hat die Eigenschaft &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;off&#039;&#039; und der &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; hat als &#039;&#039;resource-id&#039;&#039; den Wert &#039;&#039;on&#039;&#039;, dann kann man als eindeutigen Pfad für den &amp;quot;Aus&amp;quot;-&#039;&#039;Button&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.Button[@resource-id=&#039;off&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
formulieren. Wie an dem Beispiel zu sehen werden solche Bedingungen wie ein Index in eckigen Klammern an den Elementtyp angehängt. Der Name eines Attributes wird mit einem &amp;quot;@&amp;quot; eingeleitet und der Wert mit einem &amp;quot;=&amp;quot; in Anführungszeichen angehängt. Ist der Attributwert global eindeutig, kann man den vorausgehenden Pfad sogar durch den globalen Platzhalter * ersetzen, der auf jedes Element passt. Das obige Beispiel mit dem GTIN-13-&#039;&#039;Button&#039;&#039; war ein solcher Fall.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingBaum2.png | frame | Abb. 3: Elementbaum einer fiktiven App mit Erweiterungen]]&lt;br /&gt;
&lt;br /&gt;
Abb. 3 zeigt eine Erweiterung des Beispiels aus Abb. 2. Die App hat nun ein weiteres, nahezu identisches &#039;&#039;LinearLayout&#039;&#039; bekommen. Die &#039;&#039;Buttons&#039;&#039; sind in ihren Attributen jeweils ununterscheidbar. Deshalb funktioniert der vorige Ansatz nicht, einen eindeutigen Pfad nur mithilfe eines Attributwerts zu formulieren. Offensichtlich unterscheiden sich aber ihre benachbarten &#039;&#039;TextViews&#039;&#039;. Es ist möglich die jeweilige &#039;&#039;TextView&#039;&#039; in den Pfad mit aufzunehmen, um einen &#039;&#039;Button&#039;&#039; dennoch eindeutig zu adressieren. Ein Pfad zum &#039;&#039;Button&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;An&#039;&#039;&amp;quot; unterhalb der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; kann dabei wie folgt aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;//android.widget.TextView[@resource-id=&#039;push&#039;]/../android.widget.Button[@resource-id=&#039;on&#039;]&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der erste Teil beschreibt den Pfad zu der &#039;&#039;TextView&#039;&#039; mit der Markierung &amp;quot;&#039;&#039;Druckschalter&#039;&#039;&amp;quot; und der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;push&#039;&#039;. Danach folgt ein Schrägstrich gefolgt von zwei Punkten. Die zwei Punkte sind eine spezielle Elementbezeichnung, die nicht ein Kindelement benennt, sondern zum Elternelement wechselt, in diesem Fall also das &#039;&#039;LinearLayout&#039;&#039;, in dem die &#039;&#039;TextView&#039;&#039; eingebettet ist. Im Kontext dieses &#039;&#039;LinearLayout&#039;&#039; ist der restliche Pfad, nämlich der &#039;&#039;Button&#039;&#039; mit der &#039;&#039;resource-id&#039;&#039; mit dem Wert &#039;&#039;on&#039;&#039;, eindeutig.&lt;br /&gt;
&lt;br /&gt;
Der XPath-Standard bietet noch sehr viel mehr Ausdrucksmittel. Mit der hier knapp vorgestellten Auswahl ist es aber bereits möglich für die meisten praktischen Testfälle gute Pfade zu formulieren. Eine vollständige Einführung in XPath ginge über den Umfang dieser Einführung weit hinaus. Sie finden zahlreiche weiterführende Dokumentationen im Web und in Büchern.&lt;br /&gt;
&lt;br /&gt;
Eine universelle Strategie zum Erstellen guter XPaths gibt es nicht, da sie von den Testanforderungen abhängt. In der Regel ist es sinnvoll, den XPath kurz und dennoch eindeutig zu halten. Häufig lassen sich Elemente über Eigenschaften identifizieren wie beispielsweise ihren Text. Will man aber gerade den Text eines Elements auslesen, kann dieser natürlich nicht im Pfad verwendet werden, da er vorher nicht bekannt ist. Ebenso wird der Text variieren, wenn die App mit verschiedenen Sprachen gestartet wird.&lt;br /&gt;
&lt;br /&gt;
Jeder Baustein, der auf einem Element arbeitet, hat einen Eingangspin für den XPath. Im GUI-Browser finden Sie in der Mitte oben eine Liste von Bausteinen mit Aktionen, die Sie auf das ausgewählte Element anwenden können. Suchen Sie den Baustein &#039;&#039;Click&#039;&#039; (8) im Ordner Elements und wählen Sie ihn aus (Abb. 1). Er wird im rechten Teil unter &amp;quot;&#039;&#039;Test&#039;&#039;&amp;quot; eingefügt, der Pin für den XPath ist mit dem automatisch generierten Pfad des Elements vorbelegt (9). Sie können den Baustein hier auch ausführen. Die Ansicht wechselt dann auf &amp;quot;&#039;&#039;Lauf&#039;&#039;&amp;quot;. Ändert sich durch die Aktion der Zustand Ihrer App, müssen Sie den Baum anschließend aktualisieren (10).&lt;br /&gt;
&lt;br /&gt;
Wenn Sie in der unteren Liste eine Eigenschaft auswählen, wechselt die Anzeige der Bausteine zu &amp;quot;&#039;&#039;Eigenschaften&#039;&#039;&amp;quot;, wo Sie die eigenschaftsbezogenen Bausteine finden. Wie bei den Aktionen können Sie auch hier einen Baustein auswählen, der dann rechts in Test mit dem Pfad des Elements und der ausgewählten Eigenschaft eingetragen wird, sodass Sie ihn direkt ausführen können.&lt;br /&gt;
&lt;br /&gt;
== Weitere Locator-Strategien ==&lt;br /&gt;
Appium bietet neben XPath noch weitere Strategien zur Adressierung von Elementen an. Einige davon stehen Ihnen &#039;&#039;&#039;ab Version 20.1&#039;&#039;&#039; ebenfalls mit expecco zur Verfügung. Diese sind nicht ganz so mächtig wie XPath, dafür aber häufig schneller bei der Auflösung auf dem Gerät. Insbesondere bei der Verwendung mit iPhones, wo die Hierarchie bei jeder XPath-Auflösung erst aufgebaut werden muss, bieten alternative Strategien einen Vorteil für die Laufzeit.&lt;br /&gt;
&lt;br /&gt;
XPath ist weiterhin der Standard, das heißt alle Locator ohne besondere Angabe werden als XPath interpretiert. Um eine der anderen Strategien zu verwenden, schreiben Sie diese mit einem Gleichzeichen vor den gewünschten Locator. Diese Technik können Sie sowohl an den Blöcken verwenden, als auch im GUI-Browser testen.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | AccessibilityId || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Wert des Elements, der dazu dient, die App barrierefrei zu machen. Für iOS ist das das Attribut &#039;&#039;&#039;Accessibility-id&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;content-descr&#039;&#039;&#039;. &#039;&#039;Beispiel: accessibilityId=Löschen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | className || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen der Klasse des Elements. &#039;&#039;Beispiel: className=android.widget.FrameLayout&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | id || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Kennung des Elements. Für iOS ist das das Attribut &#039;&#039;&#039;name&#039;&#039;&#039;, für Android das Attribut &#039;&#039;&#039;resource-id&#039;&#039;&#039;. &#039;&#039;Beispiel: id=android:id/text1&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | iOSClassChain&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet die Hierarchie der Elemente ähnlich wie bei XPath. Eine Erklärung zum Aufbau finden Sie [https://github.com/facebookarchive/WebDriverAgent/wiki/Class-Chain-Queries-Construction-Rules hier]. &#039;&#039;Beispiel: iOSClassChain=XCUIElementTypeWindow/XCUIElementTypeButton[`label == &amp;quot;Ok&amp;quot;`]&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top; padding-right:1em&amp;quot; | iOSNsPredicateString&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet einfache Kriterien, wie Attribute, die auch kombiniert werden können. &#039;&#039;Beispiel: iOSNsPredicateString=type == &#039;XCUIElementTypeButton&#039; AND name == &#039;Weiter&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;vertical-align:top&amp;quot; | name&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; || style=&amp;quot;padding-bottom:0.5em&amp;quot; | Verwendet den Namen des Elements. &#039;&#039;Beispiel: name=Bestätigen&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt; &#039;&#039;nur für iOS&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um eine direkte Beschleunigung mit iOS zu erzielen, ohne dass Sie Ihre bisherigen Pfade anpassen müssen, wandelt expecco zudem Pfade, die nur aus einem Element mit Klasse und name-Attribut bestehen, zur Laufzeit automatisch in einen entsprechenden Locator der Strategie iOSNsPredicateString um. Wenn Sie einen Pfad explizit als XPath markieren, wird diese Anpassung nicht vorgenommen.&lt;br /&gt;
&lt;br /&gt;
=&amp;lt;span id=&amp;quot;troubleshooting&amp;quot;&amp;gt;&amp;lt;!-- Referenced by error dialog on connection error --&amp;gt;&amp;lt;/span&amp;gt;Probleme und Lösungen=&lt;br /&gt;
== Locator sind versionsabhängig oder variabel ==&lt;br /&gt;
Dann sollten Sie die Locator (xPath) entweder in einer Variablen halten oder ein Locator-Mapping in einem Screenplay Anhang definieren. Es ist auch möglich, lediglich Teile des Locators (z.B. Locator-Pfad eines Elternelements oder Attributwert) in einer Variable zu halten und im Freezevalue des Locator-Pins mit &amp;quot;&#039;&#039;$(varName)&#039;&#039;&amp;quot; einzufügen.&lt;br /&gt;
&lt;br /&gt;
==Unsichtbare UI-Elemente==&lt;br /&gt;
Beachten Sie, dass im [[#Recorder|Recorder]] auch Elemente berücksichtigt werden, die Sie auf dem Bildschirm nicht sehen. Schalten Sie daher das Element-Highlighting an oder nutzen Sie die Follow-Mouse-Funktion und den Elementbaum im GUI-Browser, um festzustellen, ob das richtige Element verwendet wird. Es kann vorkommen, dass unsichtbare Elemente vor anderen Elementen liegen und diese verdecken, so dass die gewünschten Elemente im Recorder nicht ausgewählt werden können. Lesen Sie dazu den Abschnitt [[#Elemente_verbergen|Elemente verbergen]].&lt;br /&gt;
&lt;br /&gt;
==iOS: Kabel nicht zertifiziert==&lt;br /&gt;
In manchen Fällen erscheint beim Verbinden eines iOS-Geräts über USB der Hinweis, das verwendete Kabel sei nicht zertifiziert. In diesem Fall hilft es nur, das entsprechende Kabel auszutauschen.&lt;br /&gt;
==iOS: Alerts beim Verbindungsaufbau==&lt;br /&gt;
Stellen Sie sicher, dass beim Verbindungsaufbau mit einem iOS-Gerät keine Alerts geöffnet sind. Der Aufbau schlägt sonst fehl, da die App nicht in den Vordergrund kommen kann. Siehe auch [[#iOS-Ger.C3.A4t_und_App_vorbereiten|iOS-Gerät und App vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==iOS: .ipa installieren nicht möglich==&lt;br /&gt;
Beachten Sie, dass auf iOS-Simulatoren keine &#039;&#039;.ipa&#039;&#039;-Dateien sondern nur &#039;&#039;.app&#039;&#039;-Dateien installiert werden können.&lt;br /&gt;
==Android: Gerät nicht im Verbindungsdialog==&lt;br /&gt;
Wenn ein über USB angeschlossenes Android-Gerät nicht im Verbindungsdialog auftaucht, versuchen Sie, den USB-Verbindungstyp zu ändern. In der Regel sollten MTP oder PTP funktionieren. Prüfen Sie nochmal, ob &amp;quot;USB Debugging&amp;quot; in den Entwicklereinstellungen des Geräts aktiviert ist (diese Einstellungen sind bei manchen Geräten zunächst unsichtbar, und müssen durch einen Trick zugänglich gemacht werden). Siehe auch [[#Android-Ger.C3.A4t_vorbereiten|Android-Gerät vorbereiten]].&lt;br /&gt;
&lt;br /&gt;
==Android: Abgeschnittene Elemente unten==&lt;br /&gt;
Bei Android-Geräten, die die Steuerungsleiste bzw. Softkeys automatisch ein- und ausblenden, kann es vorkommen, dass der Recorder im unteren Bereich Elemente abschneidet, die durch die Softkeys verdeckt würden, auch wenn sie zu diesem Zeitpunkt gar nicht angezeigt werden. In diesem Fall hift es, die Softkeys so einzustellen, dass sie in einer permanenten Leiste angezeigt werden.&lt;br /&gt;
&lt;br /&gt;
Bei neueren Android-Versionen gibt es eine solche Einstellung in der Regel nicht. Auch wenn die Steuerelemente permanent eingeblendet sind, liegen sie auf keiner extra Leiste, sondern vor dem Inhalt der App. Es gibt dann im unteren Teil einen Bereich, der nicht bedient werden kann, weil er nicht zum aktiven Bereich der App gezählt wird, weshalb die Elemente von Appium abgeschnitten werden. Dieser Bereich kann auch größer sein als von den Steuerungselementen beansprucht. Bekannt ist dies für Samsung-Geräte mit Android 11. Da die Information über die Größe des App-Bereichs bereits auf Android-Ebene so geliefert wird, können wir hierfür keine Lösung anbieten, sondern können nur hoffen, dass das Problem vom Hersteller behoben wird. Sie können versuchen, ob Sie mit der Einstellung von Gestensteuerung bessere Ergebnisse bekommen, allerdings gibt es hier das gleiche Problem.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;waitForIdleTimeout&amp;quot;&amp;gt;&amp;lt;!-- Referenced by expecco--&amp;gt;&amp;lt;/span&amp;gt; Android: Test hängt beim Suchen eines Elements==&lt;br /&gt;
Der Baustein &#039;&#039;Find Element by XPath&#039;&#039; und alle Element-Bausteine warten bis ein Element zum angegebenen Pfad auftaucht. Den Timeout dafür kann man entweder am Baustein direkt oder in den Umgebungsvariablen ändern. Wenn das Element aber bereits da sein sollte und es dennoch sehr lange dauert, bis der Test weitergeht, kann das am UIAutomator/UIAutomator2 liegen. Dieser wartet, bis die App in den Idle-Zustand geht, bevor er überhaupt nach Elementen sucht. Dies kann länger dauern, wenn die App z.B. im Hintergrund noch Animationen abspielt oder andere Aktionen ausführt. Auch das Holen des Page-Sources z.B. beim Aktualisieren im GUI-Browser oder im Recorder kann dadurch länger dauern. Standardmäßig gibt es hierfür einen Timeout von 10 Sekunden, nach dem nicht weiter auf den Idle-Zustand gewartet wird. Dieser Timeout lässt sich durch eine Einstellung in Appium anpassen (waitForIdleTimeout). Falls Sie einen anderen Wert für diesen Timeout setzen möchten, ist dies ab expecco 21.2 möglich, indem Sie vor dem Test den Smalltalk-Code &amp;lt;code&amp;gt;AppiumTestRunner::TestRunConnection waitForIdleTimeout:2000&amp;lt;/code&amp;gt; ausführen. Der Timeout wird in Millisekunden angegeben, das Beispiel setzt ihn also auf 2 Sekunden.&lt;br /&gt;
&lt;br /&gt;
==&amp;lt;span id=&amp;quot;startChromedriverTimeout/&amp;gt;Android: Aktualisieren des Trees oder Wechseln zum Webview-Kontext braucht zu lange==&lt;br /&gt;
Speziell mit älteren Geräten kann es vorkommen, dass neuere Chromedriver nicht initialisiert werden können. Das führt dann dazu, dass nicht in den Webview-Kontext gewechselt werden kann. Dies wird von Appium allerdings nur über einen Timeout festgestellt, der standardmäßig bei 4 Minuten liegt. Da expecco auch beim Aufbauen des Trees im GUI-Browser versucht in den Webview-Kontext zu wechseln, kann das zu sehr langen Ladezeiten führen. Da es in Appium keine Möglichkeit gibt, diesen Timeout herunter zu setzen, haben wir die Version, die wir im MobileTestingSupplement bereitstellen, um eine entsprechende Capability erweitert. Ab der Version 1.13.1.0 des [[#Windows|MobileTestingSupplements]] kann mit &#039;&#039;chromedriverStartTimeout&#039;&#039; der Timeout in Millisekunden gesetzt werden. Der Wechsel funktioniert dadurch zwar trotzdem nicht, aber expecco braucht dann nicht mehr so lange beim Aktualisieren des Trees und der Baustein zum Wechseln des Kontextes schlägt schneller fehl. Der Verbindungsdialog fügt diese Capability ab expecco 22.1 automatisch hinzu.&lt;br /&gt;
&lt;br /&gt;
==Keine Aktion bei Klick==&lt;br /&gt;
Der Baustein zum Klicken auf ein Element ist erfolgreich, aber auf dem Gerät wurde keine Aktion ausgeführt.&lt;br /&gt;
:Dies kann vorkommen, wenn das Element von einem anderen Element verdeckt ist und ein Klick auf das Element deshalb nicht möglich ist. In diesem Fall wird von Appium kein Fehler geworfen, sondern es passiert einfach nichts. Wenn Sie dennoch einen Klick an der Position des Elements machen möchten, auch wenn es verdeckt ist, benutzen Sie stattdessen den Baustein &#039;&#039;Tap&#039;&#039; und übergeben Sie diesem die Position des Elements (&#039;&#039;Get Location&#039;&#039;). Wenn Sie stattdessen vor einem Klick prüfen möchten, ob das Element zu diesem Zeitpunkt verdeckt ist, versuchen Sie, ob Ihnen die Eigenschaften &#039;&#039;Is Displayed&#039;&#039; oder &#039;&#039;Is Enabled&#039;&#039; weiterhelfen.&lt;br /&gt;
&lt;br /&gt;
==Kein Update nach Aktion==&lt;br /&gt;
Über den Recorder wurde eine Aktion ausgeführt, für die auch ein Baustein aufgezeichnet wurde, der Recorder zeigt aber immer noch das alte Bild.&lt;br /&gt;
:Der Recorder zeigt kein Livebild des Geräts, sondern immer nur eine Momentaufnahme. Nachdem eine Aktion ausgeführt wurde, aktualisiert sich der Recorder automatisch. Es kann aber vorkommen, dass das Bild schon aktualisiert wurde, bevor die Auswirkungen der Aktion auf dem Gerät vollständig abgeschlossen sind. In diesem Fall sollten Sie den Recorder von Hand aktualisieren über das Symbol mit den blauen Pfeilen. Ab expecco 20.2 können Sie für diesen Fall auch automatisches Aktualisieren einstellen. Siehe auch Beschreibung zum [[#Recorder|Recorder]].&lt;br /&gt;
&lt;br /&gt;
==&amp;quot;clickable&amp;quot; Attribut falsch==&lt;br /&gt;
Ein Element hat im &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribut/Property den Wert &amp;quot;&#039;&#039;false&#039;&#039;&amp;quot;, ist aber dennoch anklickbar.&lt;br /&gt;
:Das &amp;quot;&#039;&#039;clickable&#039;&#039;&amp;quot; Attribute muss explizit vom App-Programmierer gesetzt werden, und hat tatsächlich keine Relevanz für das tatsächliche Verhalten der App. Sie sollten dieses Attribut i.A. in Ihren Tests nicht beachten.&amp;lt;br&amp;gt;Leider existieren viele Apps, bei denen der Programmierer hier &amp;quot;lazy&amp;quot; war.&lt;br /&gt;
&lt;br /&gt;
==Verbindungsaufbau schlägt fehl==&lt;br /&gt;
Schlägt der Verbindungsaufbau mit dem Appium-Server fehl, erhalten Sie in expecco eine Fehlermeldung ähnlicher der unten abgebildeten.&lt;br /&gt;
&lt;br /&gt;
[[Datei:MobileTestingVerbindungsfehler.png]]&lt;br /&gt;
&lt;br /&gt;
Hier sehen Sie die Art des aufgetretenen Fehlers. Klicken Sie auf &amp;quot;&#039;&#039;Details&#039;&#039;&amp;quot; um nähere Informationen zu erhalten. Mögliche Fehler sind:&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.remote.UnreachableBrowserException&#039;&#039;&lt;br /&gt;
:Der angegebene Server läuft nicht oder ist nicht erreichbar. Überprüfen Sie die Serveradresse.&lt;br /&gt;
*&#039;&#039;org.openqa.selenium.WebDriverException&#039;&#039;&lt;br /&gt;
:Lesen Sie in den Details in der ersten Zeile die Meldung hinter &#039;&#039;Original Error&#039;&#039;:&lt;br /&gt;
:*&#039;&#039;Unknown device or simulator UDID&#039;&#039;&lt;br /&gt;
::Entweder ist das Gerät nicht richtig angeschlossen oder die udid stimmt nicht.&lt;br /&gt;
:*&#039;&#039;Unable to launch WebDriverAgent because of xcodebuild failure: xcodebuild failed with code 65&#039;&#039;&lt;br /&gt;
::Dieser Fehler kann verschiedene Ursachen haben. Entweder konnte tatsächlich der WebDriverAgent nicht gebaut werden, weil die Signierungseinstellungen falsch sind oder das passende Provisioning Profile fehlt. Lesen Sie dazu den Abschnitt zur [[#Signierung|Signierung]]. Es kann auch sein, dass der WebDriverAgent auf dem Gerät nicht gestartet werden kann, weil sich beispielsweise ein Alert im Vordergrund befindet oder Sie dem Entwickler nicht vertraut haben.&lt;br /&gt;
:*&#039;&#039;Could not install app: &#039;Command &#039;ios-deploy [...] exited with code 253&#039;&#039;&#039;&lt;br /&gt;
::Die angegebene App kann nicht auf dem iOS-Gerät installiert werden, weil es nicht im Provisioning Profile der App eingetragen ist.&lt;br /&gt;
:*&#039;&#039;Bad app: [...] App paths need to be absolute, or relative to the appium server install dir, or a URL to compressed file, or a special app name.&#039;&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die Datei unter dem angegebenen Pfad auf dem Mac befindet.&lt;br /&gt;
:*&#039;&#039;packageAndLaunchActivityFromManifest failed.&#039;&#039;&lt;br /&gt;
::Die angegebene &#039;&#039;apk&#039;&#039;-Datei ist vermutlich kaputt.&lt;br /&gt;
:*&#039;&#039;Could not find app apk at [...]&#039;&#039;&lt;br /&gt;
::Der Pfad zur App ist falsch. Stellen Sie sicher, dass sich die &#039;&#039;apk&#039;&#039;-Datei am angegebenen Pfad befindet.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls der Fehler nicht durch eine der oben gelisteten Ursachen bedingt ist, kann es sein, dass die auf dem Gerät befindlichen Automation-Anwendungen nicht mehr richtig funktionieren. Hier hilft es, diese vom Mobilgerät zu deinstallieren. Beim nächsten Verbindungsaufbau werden sie dann automatisch neu installiert.&lt;br /&gt;
&lt;br /&gt;
*Für iOS-Geräte ist das der WebDriverAgent, den Sie einfach vom Home-Screen deinstallieren können. Dies behebt in der Regel Probleme durch den Wechsel des verwendeten Macs oder der Xcode-Version.&lt;br /&gt;
&lt;br /&gt;
*Für Android-Geräte ist es der UIAutomator2; hier tritt auf einigen Geräten sporadisch ein Problem auf, die Ursache dafür ist uns z.Z. noch nicht bekannt. Zur Deinstallation navigieren Sie auf dem Gerät zu &amp;quot;&#039;&#039;Einstellungen&#039;&#039;&amp;quot; &amp;gt; &amp;quot;&#039;&#039;Anwendungen&#039;&#039;&amp;quot;&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt; und suchen in der Liste nach folgenden Einträgen:&lt;br /&gt;
    Appium Settings&lt;br /&gt;
    io.appium.uiautomator2.server&lt;br /&gt;
    io.appium.uiautomator2.server.test&lt;br /&gt;
:Klicken Sie auf die jeweilige Anwendung und dann auf &amp;quot;&#039;&#039;Deinstallieren&#039;&#039;&amp;quot;.&lt;br /&gt;
&amp;lt;sup&amp;gt;*&amp;lt;/sup&amp;gt;&#039;&#039;Der entsprechende Eintrag heißt auf manchen Geräten möglicherweise etwas anders.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Falls dies nicht hilft, kann eventuell die Ausgabe des Appium-Servers weiterhelfen. Für einen von expecco gestarteten Server finden Sie das Log in der Liste der [[#Laufende_Appium-Server|laufenden Appium-Server]].&lt;br /&gt;
&lt;br /&gt;
==Ich habe keinen Mac==&lt;br /&gt;
Vielleicht hilft Ihnen diese Webseite weiter: [https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10 https://www.howtogeek.com/289594/how-to-install-macos-sierra-in-virtualbox-on-windows-10]&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Timeline&amp;diff=29023</id>
		<title>Timeline</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Timeline&amp;diff=29023"/>
		<updated>2023-11-15T16:24:21Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Mauseingabe */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Einleitung =&lt;br /&gt;
[[Datei:Timeline.png|800px|thumb|Der Reiter &amp;quot;Zeitleiste&amp;quot;]]&lt;br /&gt;
Die Zeitleiste (Timeline) kann ein hilfreiches Werkzeug sein, um die zeitliche Abfolge Ihrer Testsequenzen zu verstehen, insbesondere, wenn Aktionen parallel laufen. Sie finden sie in der &#039;&#039;Lauf&#039;&#039; Anzeige entweder eines Testplans oder eines Aktionsblocks. Sie verwendet die gesammelten [[Glossary/en#Activity_Log|Logdaten]] um anzuzeigen wann und wie lange eine Aktion ausgeführt wurde.&lt;br /&gt;
&lt;br /&gt;
= Darstellung =&lt;br /&gt;
Die Zeitleiste zeigt die Unterblöcke des ausgewählten Blocks als Balken in der Farbe ihres Ausführungsstatus, wobei deren Länge und horizontale Position die Dauer und Startzeit der Ausführung widerspiegeln. Die Zeitskala oben passt sich der dargestellten Zeit an. Das aktuelle Zeitformat können Sie in der oberen rechten Ecke ablesen; z.B. bedeutet &#039;&#039;m:s&#039;&#039; eine Darstellung in Minuten und Sekunden, wobei die Sekunden noch Dezimalstellen aufweisen können, um die Millisekunden anzuzeigen.&lt;br /&gt;
&lt;br /&gt;
Anfangs wird nur die oberste Ebene der Unterblöcke des ausgewählten Blocks angezeigt. Wenn Blöcke parallel ausgeführt werden, landen sie in verschiedenen Zeilen; nacheinander ausgeführte Blocke stehen in einer Zeile. Allerdings bedeutet es für zwei Blöcke, die hintereinander stehen NICHT generell, dass der zweiten vom ersten gestartet wurde.&lt;br /&gt;
&lt;br /&gt;
Sie können Blöcke ausklappen, um deren Unterblöcke zu sehen. Ist ein Block breit genug, wird dies durch ein entsprechendes kleines Icon in der oberen linken Ecke angezeigt. Sie können Blöcke auf- und zuklappen, indem Sie auf dieses Icon klicken. Alternativ können Sie auf einen Block mit der rechten Maustaste klicken und erhalten im Kontextmenü die Möglichkeit, ihn auf- oder zuzuklappen. Die Unterblöcke werden unterhalb ihrer Eltern angezeigt, wobei sich etwaige parallele Blöcke weiter nach unten verschieben. Der Rahmen eines Blocks umfasst seine Unterblöcke um die Verschachtelung zu verdeutlichen. Sie können auch Strg gedrückt halten, um alle Kinder auszuklappen. Da die Zeitleiste nur die Informationen aus den Logdaten darstellt, werden auch nur Blöcke angezeigt, die einen Logeintrag haben. Blöcke, die im Log übersprungen wurden, werden nicht angezeigt.&lt;br /&gt;
&lt;br /&gt;
Wenn Sie einen Block in der Zeitleiste anklicken, wird er ausgewählt, was durch einen roten Rahmen dargestellt wird. Die Hauptinformationen dieses Blocks werden zum Meldungsfenster in der unteren linken Ecke des expecco-Fensters hinzugefügt. Außerdem werden Sie als Tooltip angezeigt, wenn Sie mit der Maus über den Block fahren.&lt;br /&gt;
&lt;br /&gt;
= Navigation =&lt;br /&gt;
Standardmäßig wird die gesamte Dauer des Laufs im Fenster angezeigt. Sie können aber heranzoomen, um bestimmte Abschnitte besser zu analysieren. Sie können die Menübuttons und die Maus verwenden, um sich auf der Zeitleiste zu bewegen.&lt;br /&gt;
&lt;br /&gt;
== Menüzeile ==&lt;br /&gt;
[[Datei:Timeline_Menubar.png]]&lt;br /&gt;
# Höhe der Zeilen verringern&lt;br /&gt;
# Höhe der Zeilen vergrößern&lt;br /&gt;
# Zeitleiste auf verfügbaren Breite strecken&amp;lt;br&amp;gt;Ein Umschaltknopf: wenn er aktiviert ist, wird die gesamte Laufdauer auf die Breite des Reiters gestreckt.&lt;br /&gt;
# Herauszoomen&amp;lt;br&amp;gt;Die Breite der Zeitleiste verkleinern, sodass mehr Zeit auf weniger Platz dargestellt wird&lt;br /&gt;
# Hineinzoomen&amp;lt;br&amp;gt;Die Breite der Zeitleiste vergrößern, sodass weniger Zeit auf mehr Platz dargestellt wird und besser analysiert werden kann&lt;br /&gt;
# Springe zum Start der ausgewählten Aktion&lt;br /&gt;
# Springe zum Ende der ausgewählten Aktion&lt;br /&gt;
# Relative Ausführungszeiten&amp;lt;br&amp;gt;Die Block-Informationen bspw. im Tooltip zeigen die Startzeit relativ zum Beginn des dargestellten Blocks und die Dauer falls aktiviert, ansonsten absolute Start- und Endzeiten&lt;br /&gt;
&lt;br /&gt;
== Mauseingabe ==&lt;br /&gt;
Normales Scrollen verschiebt das Diagram vertikal, bei gedrückter Shift-Taste horizontal. Durch Scrollen bei gedrückter Strg-Taste können Sie an der Cursorposition zoomen. Falls das Strecken der Zeitleiste deaktiviert ist, können Sie an einem Punkt in der Zeitskala klicken und zu einem anderen ziehen, um einen Zeitabschnitt auszuwählen. Dieser wird dabei gelb markiert. Wenn Sie die Maustaste loslassen, wird die Zeitleiste auf diesen Abschnitt herangezoomt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Timeline_Select_Time.png]]&lt;br /&gt;
&lt;br /&gt;
= Auswählen =&lt;br /&gt;
Wie bereits erwähnt, können Sie einen Block durch Klicken auswählen. Wenn Sie doppelklicken, wird der Block im Baum ausgewählt und die Zeitleiste wechselt zur Darstellung seiner Unterblöcke.&lt;br /&gt;
&lt;br /&gt;
Sie können die Zeitleiste (und gleichzeitig das Netzwerk, die Logdaten und die Ein/Ausgänge) auch auf den ausgewählten Block fixieren, indem Sie den Toggle-Button [[Datei:Timeline_Lock_Button.png]] im Menü des Baums aktivieren. Dies wird durch ein kleines Schloss-Symbol neben dem Eintrag des fixierten Blocks im Baum angezeigt. Wenn Sie nun einen anderen Block im Baum auswählen, wird er in der Zeitleiste des fixierten Blocks ausgewählt. Genauso können Sie auf einen Block in der Zeitleiste doppelklicken und sein Eintrag wird im Baum ausgewählt ohne die angezeigte Zeitleiste zu ändern.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
	<entry>
		<id>https://doc.expecco.de/index.php?title=Timeline/en&amp;diff=29022</id>
		<title>Timeline/en</title>
		<link rel="alternate" type="text/html" href="https://doc.expecco.de/index.php?title=Timeline/en&amp;diff=29022"/>
		<updated>2023-11-15T16:22:23Z</updated>

		<summary type="html">&lt;p&gt;Matilk: /* Mouse Input */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Introduction =&lt;br /&gt;
[[Datei:Timeline.png|800px|thumb|Timeline Tab]]&lt;br /&gt;
The Timeline can be a useful tool, when you want to understand the chronology of your test sequence, especially when actions are running in parallel. It can be found in the &#039;&#039;Run&#039;&#039; section of either a testplan or an action block. It uses the information collected in the [[Glossary/en#Activity_Log|Activity Log]] to show when and for how long an action was executed.&lt;br /&gt;
&lt;br /&gt;
= Representation =&lt;br /&gt;
The timeline shows the subblocks of the selected block as bars in the color of their execution state, where their length and horizontal position represents the duration and start time of their execution. The timescale at the top adapts to the presented time. You see the current time format in the top right corner, e.g. &#039;&#039;m:s&#039;&#039; means minutes and seconds separated by a colon, where the seconds may have digits after the decimal point to show the milliseconds.&lt;br /&gt;
&lt;br /&gt;
Initially only the top blocks of the selected blocks are shown. If blocks are executed in parallel, they go in different lines, consecutive blocks are in one line. However, if two blocks are one after the other in the same line, that does NOT indicate, that the first block triggered the second.&lt;br /&gt;
&lt;br /&gt;
You can expand blocks, to see its subblocks. If a block is wide enough, it shows a little expand icon in its left corner. You can expand or collapse the block by clicking on this icon. Alternatively, you can right click on a block and select expand or collapse from its context menu. The subblocks are displayed below their parent block, pushing any parallel block further down in the diagram. The frame of a block includes its subblocks, visualizing the nesting. If you hold Ctrl when expanding a block, it will expand all of its children. As the timeline only displays the information from the Activity Log, you can only see the blocks, that have an log entry. You cannot see blocks, that are skipped in the log.&lt;br /&gt;
&lt;br /&gt;
If you click on a block in the timeline it gets selected, which is indicated by a red frame. The main information of that block is added to the messages in the lower left corner of the expecco window. You also get this information as tooltip when hovering over a block.&lt;br /&gt;
&lt;br /&gt;
= Navigation =&lt;br /&gt;
As default the whole duration is displayed in the panel, but you can zoom in, to better see a certain section. You can use the buttons of the menu bar to navigate through the timeline and use the mouse.&lt;br /&gt;
&lt;br /&gt;
== Menu bar ==&lt;br /&gt;
[[Datei:Timeline_Menubar.png]]&lt;br /&gt;
# Decrease the height of lines&lt;br /&gt;
# Increase the height of lines&lt;br /&gt;
# Stretch the timeline to the available width&amp;lt;br&amp;gt;This is a toggle, if it is on, the whole run time is stretched to the width of the panel.&lt;br /&gt;
# Zoom out&amp;lt;br&amp;gt;Decrease the width of the timeline, so that more time is shown in less space.&lt;br /&gt;
# Zoom in&amp;lt;br&amp;gt;Increase the width of the timeline, so that less time is shown in more space and can be analyzed better.&lt;br /&gt;
# Jump to the start of the selected action&lt;br /&gt;
# Jump to the end of the selected action&lt;br /&gt;
# Relative execution times&amp;lt;br&amp;gt;The block information e.g. in the tooltip shows the start time relative to the start time of the displayed block and the duration if on, or the absolute start and end time if off.&lt;br /&gt;
&lt;br /&gt;
== Mouse Input ==&lt;br /&gt;
Normal scrolling moves the diagram vertically, scrolling with the Shift key held down moves it horizontally. You can zoom in and out on the cursor position by scrolling while holding down the Ctrl key. If stretch is disabled, you can click at a point in the timescale and drag to another to select a time period, which is highlighted in yellow. When you release the mouse button, the timeline zooms to that period.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Timeline_Select_Time.png]]&lt;br /&gt;
&lt;br /&gt;
= Selecting =&lt;br /&gt;
As earlier already mentioned, you can select a block by clicking on it. When double clicking on it, it gets selected in the tree and so the timeline will switch to only display the subblocks of this block.&lt;br /&gt;
&lt;br /&gt;
You can also lock the timeline (and as well the network, log and pin entries) to the block selected in the tree, by activating the toggle [[Datei:Timeline_Lock_Button.png]] in the menu of the tree. This will be indicated by a little lock icon next to the tree icon of the locked block. If you now select another block in the tree, it gets selected in the timeline of the locked block. Similar you can double click on a block in the timeline and its entry in the tree will be selected without changing the displayed timeline.&lt;/div&gt;</summary>
		<author><name>Matilk</name></author>
	</entry>
</feed>