<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Andrea Tino’s Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/antino/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/antino/feed.xml</link>
    <description>Blogging about Microsoft Technology for the Web, HTML, CSS, Javascript, C#, Typescript and Internet</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:21:27 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Testing with Appium - Exchange data between your tests and your app</title>
      <link>https://docs.microsoft.com/archive/blogs/antino/testing-with-appium-exchange-data-between-your-tests-and-your-app</link>
      <pubDate>Wed, 18 Mar 2015 16:22:00 GMT</pubDate>
      <dc:creator><![CDATA[Andrea Tino]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/antino/2015/03/18/testing-with-appium-exchange-data-between-your-tests-and-your-app/</guid>
      <description><![CDATA[In my previous post:&nbsp;Q&amp;A on Appium - Should I use it? I focused on some scenarios where...]]></description>
      <content:encoded><![CDATA[<p>In my previous post:&nbsp;<a href="/b/antino/archive/2014/11/30/q-amp-a-on-appium-should-i-use-it.aspx" title="Q&amp;amp;A on Appium - Should I use it?" target="_blank">Q&amp;A on Appium - Should I use it?</a> I focused on some scenarios where <a href="http://appium.io">Appium</a> might not be the perfect choice; one of those scenarios is <em>data exchanging</em>. I know I might sound redundant, but let me repeat myself again: data exchange is not an <em>issue</em> in Appium or <a href="https://code.google.com/p/selenium/">Selenium</a>; it is a scenario which is simply not supported by the specification, thus it is difficult to achieve. So do not complain with Appium nor with Selenium if you cannot send and receive information to and from your app while testing.</p>
<h3>Selenium API at a glimpse</h3>
<p>If we take a look at all commands available in most common Appium&#39;s drivers, we will probably not find anything suitable for data exchange. Let us consider for example the <a target="_blank" title="Javascript Driver" href="https://www.npmjs.com/package/wd">Javascript Driver</a> and all <a target="_blank" title="Commands" href="https://github.com/admc/wd/blob/master/lib/commands.js">commands</a> exposed there: there is nothing that specifically focuses on exchanging information. Just automation. The same goes for the other drivers, there is no specific method that enables data exchange between the test and the app being tested. So what do we do? We try to achieve that result by ourselves.</p>
<h2>One method to exchange data</h2>
<p>There is only one method in Selenium which I did not mention in the previous section, which is actually the solution to our problem here:</p>
<div class="at-codebox">
<pre><code>executeScript(script, args)
executeAsyncScript(script, args)
</code></pre>
</div>
<p>The ones above are the names of the methods available in the <a href="https://w3c.github.io/webdriver/webdriver-spec.htm">WebDriver</a>&#39;s <a target="_blank" title="W3C specification" href="https://dvcs.w3.org/hg/webdriver/raw-file/default/webdriver-spec.html#executing-javascript">W3C specification</a>. Those two commands allow the test to execute some <a href="http://en.wikipedia.org/wiki/JavaScript">Javascript</a> code in the (webview-based) app. It might not sound so promising but there is one very important thing about those two guys: they can return stuff!</p>
<h3>Returned value</h3>
<p>There is some complexity behind how those 2 functions are implemented in whatever <span class="at-codeline">WebDriver</span>, however the <a href="http://www.w3.org/">W3C</a> defines the basics of their business logic as well as the protocol to use to successfully return a value to the caller. The W3C specification is very generic, so here I will try to make things a bit easier. According to the specification, when <span class="at-codeline">executeScript</span> is invoked (the same goes for <span class="at-codeline">executeAsyncScript</span>), the following must happen:</p>
<ol>
<li>The caller must provide the script in a string.</li>
<li>The string is parsed when reaching the browser&#39;s <span class="at-codeline">window</span> object (in a webview-based app, remember that we have a browser) and set as the body of a Javascript function object acting on the global context and taking as input the arguments passed to <span class="at-codeline">executeScript</span>.</li>
<li>The function is executed in a safe block where its return value is captured or any exception can be caught as well.</li>
<li>In case of exception, the error is set as the response status.</li>
<li>In case a value is returned, it is parsed and sent back in the response&#39;s value field. Response&#39;s status field is set to success.</li>
</ol>
<p>Also, when a value is to be returned by the function, the following must happen:</p>
<ol>
<li>If the value is undefined or null, null is returned.</li>
<li>If value is a number or a string, then no further operation is done and the value is returned as it is.</li>
<li>If value is a DOM element, then the corresponding <span class="at-codeline">WebElement</span> is constructed and returned.</li>
<li>If value is an array, then return an array whose elements are built by following these algorithm for each element.</li>
<li>If value is an object consisting of custom properties, then return the same object by applying this algorithm to each property in it.</li>
</ol>
<p>So as you can see, we can return something from our tests. By invoking a script which returns some interesting information, we can actually send requests and have data in return. However things are not so easy.</p>
<h4>No everybody implements the full specification</h4>
<p>The problem is that not every driver implements the algorithms I just mentioned 100%, this is especially true when it comes to the algorithm used to build the returned value. Basing on my experience, so far it is safe to return numbers or strings. When it comes to whole objects or DOM elements, sorry to say, it is not certain that what we get back from the device is exactly what we were expecting. For this reason, for the sake of test stability ad reliability, it is better to always keep in mind the following:</p>
<p class="at-importantbox">Always return simple types only, this will always ensure successful data exchange.</p>
<h2>Returning complex data: JSON serialization</h2>
<p>So, how can we exchange complex data if we can only return strings or numbers from our app? Actually we do not really care about returning numbers, strings are just fine! The answer to our question is the following:</p>
<p class="at-importantbox">To enable data exchange, it is possible to send and receive objects as string via JSON serialization.</p>
<p>The following picture will probably provide a better description of the basic idea.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/jsexchange.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/jsexchange.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/jsexchange.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/jsexchange.png" alt=" " style="display:block;margin-left:auto;margin-right:auto;" border="0" /></a></p>
<p>We can make Javascript queries to send via <span class="at-codeline">executeScript</span>, and get a JSON string back. When our query is executed, we must take care of <a target="_blank" title="Javascript function 'stringify()'" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringifying</a> the returned value and return it instead of the JSON object. Once we get the string in our test, we can use one of the many JSON parsing libraries available on the web to convert it into a dynamic structure or an hash table (dictionary).</p>
<h3>Possible scenarios</h3>
<p>If the idea is clear, then we can move on picturing some possible scenarios. Where might we ever need to exchange data? Consider the following examples:</p>
<ul>
<li>Getting the possible values that a user can select from a combo box.</li>
<li>Getting the chosen value from a list of possible options when we are not using form controls in our page, but some HTML or jQuery complex control.</li>
<li>Getting the value typed by the user in an editable div of one page of your hybrid app.</li>
<li>Checking return value of an <a href="http://en.wikipedia.org/wiki/Ajax_%28programming%29">AJAX</a> call to the server.</li>
</ul>
<p>Keeping on listing possible scenarios would be meaningless, you will sure find a situation when data exchange comes into need believe me, especially if your tests are a bit more complicated than usual automation and your apps have articulated user stories.</p>
<h2>An example: values in a list</h2>
<p>Let&#39;s consider a real case and see data exchange in action. Our app deals with restaurants and is able to locate the most famous ones close to where the user is. In a page of our app, after the user issues the search command, we are able to see the list of possible restaurants in a radius of 200 meters. We want to test that some restaurants are displayed when the user is located in a specific area. In our page, the list of restaurants will look like the following:</p>
<div class="at-codebox">
<pre><code>&lt;ol id=&quot;item_selection&quot;&gt;
  &lt;li class=&quot;item&quot; data-id=&quot;i0463&quot;&gt;Item 1&lt;/li&gt;
  &lt;li class=&quot;item&quot; data-id=&quot;i3957&quot;&gt;Item 2&lt;/li&gt;
  &lt;li class=&quot;item&quot; data-id=&quot;i9248&quot;&gt;Item 3&lt;/li&gt;
  &lt;li class=&quot;item  data-id=&quot;i3451&quot; data-selected&quot;&gt;Item 4&lt;/li&gt;
&lt;/ol&gt;
</code></pre>
</div>
<p>Remember that our app is an hybrid app, so it relies on HTML. Here we could have used a simple combo box, however my point is proving that we can exchange data coming from every part of your <a href="http://www.w3.org/DOM/">DOM</a>, not just form controls.</p>
<h3>Serializing with Javascript</h3>
<p>In our test we need to get access to the list, in particular we want the ID (available as a <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes" title="Data Attributes" target="_blank">data attribute</a>) of the restaurant which is selected. How can we do this? In our test we can have the following code.</p>
<div class="at-codebox at-box-big">
<pre><code>[TestMethod]
public void TestSelection() {
  AppiumDriver driver = this.Driver; // The test class will host the driver (assuming connected)

  // Retrieving from device
  object ret = driver.ExecuteJavascript(@&quot;
    // Javascript executed in an anonymous function on the webview
    var ret = {};

    var ol = document.getElementById(&quot;item_selection&quot;);
    if (ol == null) {
      ret.status = -1; // List not found
      ret.message = &quot;Could not find list&quot;;
      ret.value = null;
      return JSON.strigify(ret);
    }

    // The ol element could be found
    var lis = ol.getElementsByTagName(&quot;li&quot;);
    if (lis == null) {
      ret.status = 0; // No items
      ret.message = &quot;No items in list&quot;;
      ret.value = null;
      return JSON.strigify(ret);
    }

    // We have the list, need to locate selected one
    ret.status = 1
    ret.message = null;
    ret.value = {};
    ret.value.id = null;
    ret.value.text = null;
    for (var i = 0; i &lt; lis.length; i++) {
      if (lis[i].dataset.selected != null) {
        ret.value.id = lis[i].dataset.id;
        ret.value.text = lis[i].textContext; /* Use innerText on IE */
      }
    }

    return JSON.strigify(ret);
  &quot;);

  if (ret == null) {
    throw new InvalidOperationException(&quot;Appium had problems executing script&quot;);
  }

  // If we can get to here, then serialized javascript object should be here
  string json = (string)ret;

  // Getting the object, this function will be implemented later 
  // and the type returned will be specified as well
  var obj = this.ParseJSON(json);
  // Code will continue later on...  
}
</code></pre>
</div>
<p>As you can see, in our invocation, we pass a Javascript function which will be executed on the device by Appium. Serialization is performed by means of <span class="at-codeline">JSON.stringify</span>, which is an API introduced not so long ago in <a href="http://en.wikipedia.org/wiki/ECMAScript">ECMAScript</a>.</p>
<h3>Deserializing with every other language, e.g. C#</h3>
<p>How do we parse JSON in our test? The nice thing of JSON is that all programming languages have at least one API to parse it. C# is no difference and it provides something called <span class="at-codeline">JavascriptSerializer</span> in the <span class="at-codeline">System.Web.Script.Serialization</span> namespace. This class however gets a bit tricky to use when just deserializing a JSON string which was not serialized from a concrete type using the same class (which is exactly our case). For this reason we are going to rely on .NET&#39;s <a href="https://msdn.microsoft.com/en-us/library/ms731082%28v=vs.110%29.aspx">WCF</a> and use the <span class="at-codeline">DataContractJsonSerializer</span> which implies a bit more code to be written, but your tests will have a better and more consistent shape.</p>
<p>The first thing we need is a C# representation of the object we will use to exchange data. In WCF we achieve this by means of <a href="https://msdn.microsoft.com/en-us/library/ms733127%28v=vs.110%29.aspx" title="WCF Data Contracts" target="_blank">Data Contracts</a> which are a WCF-specific concept describing the information being sent between two endpoints. The following code will actually describe the <span class="at-codeline">ret</span> structure we used in the previous Javascript chunk.</p>
<div class="at-codebox at-box-big">
<pre><code>[DataContract]
public class SelectedItemReturnStruct {
  private int status;
  private string message;
  private SelectedItemValue value;

  /// Data member&#39;s Name must match Javascript object ret&#39;s property
  [DataMember(Name = &quot;status&quot;, IsRequired = true)]
  public int Status { 
    get { return this.status; } 
    set { this.status = value; } 
  }

  /// Data member&#39;s Name must match Javascript object ret&#39;s property
  [DataMember(Name = &quot;message&quot;, IsRequired = true)]
  public string Message { 
    get { return this.message; } 
    set { this.message = value; } 
  }

  /// Data member&#39;s Name must match Javascript object ret&#39;s property
  [DataMember(Name = &quot;value&quot;, IsRequired = true)]
  public SelectedItemValue Value { 
    get { return this.value; } 
    set { this.value = value; } 
  }
}

[DataContract]
public class SelectedItemValue {
  private string id;
  private string text;

  /// Data member&#39;s Name must match Javascript object ret&#39;s property
  [DataMember(Name = &quot;id&quot;, IsRequired = true)]
  public string Id { 
    get { return this.id; } 
    set { this.id = value; } 
  }

  /// Data member&#39;s Name must match Javascript object ret&#39;s property
  [DataMember(Name = &quot;text&quot;, IsRequired = true)]
  public string Text { 
    get { return this.text; } 
    set { this.text = value; } 
  }
}
</code></pre>
</div>
<p>You will also need to include <span class="at-codeline">System.Runtime.Serialization</span> namespace for getting access to <span class="at-codeline">DataContract</span> and <span class="at-codeline">DataMember</span> attributes.</p>
<p>The key on data contracts is that they provide a mapping between objects of different types. the <span class="at-codeline">DataContract</span> attribute tells the framework that an instance of a class can be created as long as the other entity sends an object of a class implementing the same contract. In this case, we will receive a JSON string describing an object with some properties. The serializer will use the contract to associate each Javascript property to a property of our class. The framework will look for matching names, that is why we must ensure that the properties we use in the Javascript object will match those in <span class="at-codeline">DataMember</span>s in our classes.</p>
<p>We are now ready to perform deserialization by implementing method <span class="at-codeline">ParseJSON</span> introduced in the previous code.</p>
<div class="at-codebox at-box-big">
<pre><code>public SelectedItemReturnStruct ParseJSON(string json) {
  DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(SelectedItemReturnStruct));
  MemoryStream ms = new MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(json));

  SelectedItemReturnStruct ret = (SelectedItemReturnStruct)js.ReadObject(ms);
  ms.Close();
  
  return ret;
}
</code></pre>
</div>
<p>The previous code assumes that you included in your test project the assembly <span class="at-codeline">System.Runtime.Serialization</span> and that you included the following namespace in your file: <span class="at-codeline">include System.Runtime.Serialization.Json;</span>. Namespace <span class="at-codeline">System.IO</span> will also be needed.</p>
<p>We can now complete our test method we left incomplete before.</p>
<div class="at-codebox at-box-big">
<pre><code>[TestMethod]
public void TestSelection() {
  // We were here...
  var obj = this.ParseJSON(json);
  
  if (obj.Status == -1) {
    // No list
    throw new InvalidOperationException(&quot;List could not be found!&quot;);
  }
  if (obj.Status == 0) {
    // No items
    Assert.Inconclusive();
  }

  // A list could be found and items as well
  if (obj.Value == null) {
    // No item marked as selected ==&gt; Nothing to test
    return;
  }

  string id = obj.Value.Id;
  string text = obj.Value.Text;
  // Test whatever you want from now on...
}
</code></pre>
</div>
<p>It was not that difficult and this pattern can be implemented for whatever type of objects you need to exchange.</p>
<p class="at-endlinebox">The views and opinions expressed in this blog are those of the authors and do not necessarily reflect the official policy or position of any other agency, organization, employer or company.</p>]]></content:encoded>
    </item>
    <item>
      <title>Q&amp;A on Appium - Should I use it?</title>
      <link>https://docs.microsoft.com/archive/blogs/antino/qa-on-appium-should-i-use-it</link>
      <pubDate>Sun, 30 Nov 2014 12:50:00 GMT</pubDate>
      <dc:creator><![CDATA[Andrea Tino]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/antino/2014/11/30/qa-on-appium-should-i-use-it/</guid>
      <description><![CDATA[So here we are; after 3 months of using and struggling with it a little, I finally have some...]]></description>
      <content:encoded><![CDATA[<p>So here we are; after 3 months of using and struggling with it a little, I finally have some experience with <a href="http://appium.io">Appium</a> in order to start posting some feedback on this technology. I will assume, throughout this post, that you all are more or less familiar with what Appium is and what it does; so that I can focus on why you should use it or not.</p>
<p>This post is for developers who actually knows about Appium but never approached to it. Whatever the reason for which you never gave it a try, I am gonna spend few lines about what you should expect from Appium. Do you need it? Is it going to be any good for you? Let&#39;s discover it together.</p>
<p>Also keep in mind that this is not a final verdict on Appium, this post is an early evaluation from the point of view of a developer who has been using it, intensively, for a short time until now; thus every answer I will provide is implicitly preceded by an <a href="http://en.wiktionary.org/wiki/IMHO">IMHO</a>!</p>
<p>We will go through 21 different questions you can find down below.</p>
<ol start="0">
<li><a href="#q0"><a href="http://appium.io">Appium</a>, <a href="https://w3c.github.io/webdriver/webdriver-spec.htm">WebDriver</a>, <a href="https://code.google.com/p/selenium/">Selenium</a>, Appium drivers and <a href="http://cordova.apache.org/">Cordova</a>... What are they?</a></li>
<li><a href="#q1">Do I need Appium?</a></li>
<li><a href="#q2">How difficult is it to set up a working environment?</a></li>
<li><a href="#q3">What is Appium&#39;s strongest point?</a></li>
<li><a href="#q4">What is Appium&#39;s weakest point?</a></li>
<li><a href="#q5">Which language should I use to write my tests?</a></li>
<li><a href="#q6">What types of tests are suitable for Appium?</a><ol>
<li><a href="#q6a">Can Appium be used for all my tests?</a></li>
<li><a href="#q6b">I am writing my tests and it is getting very difficult... When should I give up?</a></li>
<li><a href="#q6c">What does a typical Appium test look like?</a></li>
</ol></li>
<li><a href="#q7">What is Appium&#39;s most considerable limitation?</a></li>
<li><a href="#q8">How active is Appium?</a></li>
<li><a href="#q9">How about performance?</a></li>
<li><a href="#q10">Which approach is the best? Testing on real devices or real simulators/emulators?</a></li>
<li><a href="#q11">What platforms are supported?</a></li>
<li><a href="#q12">Do I need a server machine to run tests on Appium?</a></li>
<li><a href="#q13">I already have platform-specific tests for my app, what should I do to migrate to Appium?</a><ol>
<li><a href="#q13a">How much time does it take to write a test in Appium?</a></li>
<li><a href="#q13b">Any tips or tricks to speed up my test writing activity or my migration process?</a></li>
</ol></li>
<li><a href="#q14">What test frameworks are supported by Appium?</a></li>
<li><a href="#q15">Can I interact with my apps using Javascript while I am testing with Appium?</a></li>
<li><a href="#q16">How can I exchange data between my test and the app I am testing?</a></li>
<li><a href="#q17">What are the most difficult scenarios to test with Appium?</a></li>
<li><a href="#q18">I don&#39;t want to set up a whole infrastructure for my tests and I don&#39;t want to spend money on HW. Can Appium help me?</a></li>
<li><a href="#q19">I need to debug Appium, is it difficult?</a></li>
<li><a href="#q20">I build my apps with <a href="http://cordova.apache.org/">Cordova</a>, is it supported by Appium?</a></li>
<li><a href="#q21">What are the basic commands that I can use in the <a href="https://code.google.com/p/selenium/">Selenium</a> protocol?</a></li>
<li><a href="#q22">I want to run my tests in a multithreaded environment, any problems with that?</a></li>
</ol>
<h2><a id="q0"></a>Q0 - <a href="http://appium.io">Appium</a>, <a href="https://w3c.github.io/webdriver/webdriver-spec.htm">WebDriver</a>, <a href="https://code.google.com/p/selenium/">Selenium</a>, Appium drivers and <a href="http://cordova.apache.org/">Cordova</a>... What are they?</h2>
<p>I like calling this <em>Question 0</em> because it is like a general summary of what I am going to deal with in this Q&amp;A session. If you are familiar with all these names, just jump to <a href="#q1">Question 1</a>.</p>
<p>These 5 guys are sort of the most important building blocks when it comes to app development and testing with Appium (Appium does not cover the development phase). Since I want to keep this short and straightforward, I am going to explain what they are and how they relate to each other in a simple diagram.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7534.appium.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7534.appium.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7534.appium.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7534.appium.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>As you can see the whole thing is not so immediate, but the figure above provides a good picture of how pieces are to be assembled together.</p>
<h2><a id="q1"></a>Q1 - Do I need Appium?</h2>
<p>The answer to such a question is always: &quot;It depends on what you need!&quot;. So the actual question becomes: &quot;Which conditions make Appium suitable for me?&quot;. The most important assumption is that you are developing apps (pretty obvious I know). If you are developing an app for a specific platform (and have no intention of supporting others in future), Appium is not really required and this is basically the answer you are looking for. Appium becomes meaningful only when you have apps targeting more than one platform (Windows, Android or iOS to cite some). Appium becomes essential if you have a webview-based app (necessarily) targeting many platforms out there.</p>
<h2><a id="q2"></a>Q2 - How difficult is it to set up a working environment?</h2>
<p>The assumption is that Appium comes with a not-so-tiny documentation, so users are not really left alone. However it is not so straightforward to set up Appium to work on a Windows or Mac machine (did not try on Unix so far). In my experience, instead of installing the GUI-based application, it is much better to install the command-line application (which is released more often). Also beware [sudo], as Appium will surely bite you back late in time if you installed it as a [superuser] (this is probably the clearest point in the documentation).</p>
<h2><a id="q3"></a>Q3 - What is Appium&#39;s strongest point?</h2>
<p>Appium is based on <a href="https://code.google.com/p/selenium/">Selenium</a> which is an HTTP protocol by Google designed to automate browsers. The idea is actually very nice as automating an app (especially a webview-based one) is not so different (in terms of required APIs) from automating a browser. Appium is also designed to encourage a 2-tier architecture: a machine runs the test written in one language ([csharp], [ruby], [javascript] are only a few among the many supported ones) and another one (the test server) actually executes it. Furthermore the WebDriver protocol targets scalability (because based on <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a>), this makes Appium very scalable as well; remember that you will need to <strong>write your test once</strong>, Appium will be in charge of executing it on more platforms.</p>
<h2><a id="q4"></a>Q4 - What is Appium&#39;s weakest point?</h2>
<p>Open source software is great, however it naturally comes with some downsides which nobody is to be blamed for: <strong>unreliability&nbsp;</strong>is probably one of the most undeniable. My test suites need to run many tests every day and those tests must be stable (it means they should fail only when the product, or the test has a defect). However it took me much time to build layers on top of Appium to make my tests stable. This is especially true when it comes to synchronizing your tests with the automation: your test issues a command which translates into an automation command by Appium causing an interaction on the device; a command returns when after it has been issued, not when the interaction is actually over! For this reason you will probably find yourself adding delays to your tests (if you are doing things in the wrong/most-straightforward way) or developing synchronization layers on top of your test APIs (the good approach).</p>
<h2><a id="q5"></a>Q5 - Which language should I use to write my tests?</h2>
<p>This is probably the best thing about Appium: you can write your tests in <strong>any language</strong>. Since Appium is nothing more than an HTTP server, a test which needs to be interfaced with Appium can simply use HTTP libraries to create HTTP sessions. You just need to know the Selenium protocol in order to compose the right commands and that&#39;s it!</p>
<h3>Do not reinvent the wheel</h3>
<p>However, as you can imagine, there are already some libraries doing this for the most common languages and development frameworks out there: C#, [dotnet], [java], Ruby, [python] and Javascript are just few examples; and they all are open source projects. So far I have been using C# thanks to the <a href="https://github.com/appium/appium-dotnet-driver" title=".NET Appium Driver" target="_blank">.NET Appium Driver</a> and had no problems to interface with Appium (I actually had different problems).</p>
<h2><a id="q6"></a>Q6 - What type of tests are suitable for Appium?</h2>
<p>When it comes to testing, especially webview-based apps, there are a lot of scenarios that can be tested also depending on the feature coverage you want to ensure. Appium is pretty handy for testing scenarios that users will go through when using your app. But if you need to test more than UX simple interactions, then Appium will become a limitation. Think about features like keyboarding. It is not so easy when complex touch/keyboard mixed scenarios are involved, the probability of a false failure is high; do not misunderstand me on this: I am not saying it is impossible to do, just not so easy as you might think!</p>
<p>Another little nightmare with Appium is <strong>exchanging data</strong>. When your test needs to exchange data with your app (especially in the incoming direction), you will need to play some tricks. So always consider that sending and receiving information is not that straightforward. It is not Appium&#39;s fault, the WebDriver specification was designed for automating stuff, not exchanging data! You can get more info in <a href="#q16">Question 16</a>.</p>
<h3><a id="q6a"></a>Q6A - Can Appium be used for all my tests?</h3>
<p>This is an implied question in this question. The answer is <strong>No</strong> (in general). As I said before Appium is not suitable for all types of tests you might want to write (this depends on the functionalities you need to cover). There are some scenarios that can be difficult to test and some of them are so platform specific that you will need to write some suites just for Android or iOS for example. Remember that you can always get to do something no matter how hard it is, so you can test all your difficult scenarios using Appium, but always keep in mind one question: is it worth the time and the pain? Having Appium testing some scenarios leaving a few tests to other approaches is fine too! World is not black and white!</p>
<h3><a id="q6b"></a>Q6B - I am writing my tests and it is getting very difficult... When should I give up?</h3>
<p>There are a few clear symptoms which will let you know things are getting weird and wrong when writing your tests in Appium; when you meet one of the following conditions, stop and consider not using Appium for those tests.&nbsp;</p>
<ul>
<li>You realize that some tests must be run just for a specific platform, or you are putting many conditionals to execute part of a test depending on the platform.</li>
<li>The functionality you want to cover in your test is available only when your app is deployed on a specific platform.</li>
<li>Your test must cover a fix for a specific platform.</li>
<li>The test is difficult to write because you need a lot of interaction with the app.</li>
<li>A simple interaction needs more than 10 commands.</li>
</ul>
<h3><a id="q6c"></a>Q6C - What does a typical Appium test look like?</h3>
<p>When you start writing tests for Appium, if your suites do not require data exchange with your app or other not so common features, you will probably end up with something like the code shown below.</p>
<div class="at-codebox at-box-big">
<pre><code>namespace AppiumTest {
// The app should show an error message when login is performed with non valid credentials.
[TestMethod]
public void LogInWithInvalidCredentials() {
    string usernameTextboxId = &quot;un&quot;;
    string passwordTextboxId = &quot;pw&quot;;
    string submitButtonId = &quot;submit&quot;;
    string errorMsgboxId = &quot;errBox&quot;;

    string address = &quot;http://localhost/appium-srv:4723/wd/hub&quot;;
    DesiredCapabilities capabilities = new DesiredCapabilities();

    try {
        AppiumDriver appiumDriver = new AppiumDriver(address, capabilities, 60);

        // Locate the username textbox
        IWebElement usernameElement = appiumDriver.FindElementById(usernameTextboxId);
        Assert.IsNotNull(usernameElement, &quot;Element could not be found but supposed to be there&quot;);
        usernameElement.Clear();
        usernameElement.SendKeys(&quot;Invalid user&quot;);

        // Locate the password textbox
        IWebElement passwordElement = appiumDriver.FindElementById(passwordTextboxId);
        Assert.IsNotNull(passwordElement, &quot;Element could not be found but supposed to be there&quot;);
        passwordElement.Clear();
        passwordElement.SendKeys(&quot;Invalid password&quot;);

        // Locate the submit button
        IWebElement submitElement = appiumDriver.FindElementById(submitButtonId);
        Assert.IsNotNull(submitElement, &quot;Element could not be found but supposed to be there&quot;);
        submitElement.Click();

        // Wait because the app must contact the security server for logging in
        Thread.Sleep(5000);

        // Check the error message
        IWebElement errorMsgElement = appiumDriver.FindElementById(errorMsgboxId);
        Assert.IsNotNull(errorMsgboxId, &quot;The error message should be shown&quot;);
    } catch (Exception e) {
        throw new Exception(&quot;An error occurred with Appium&quot;, e);
    }
}
</code></pre>
</div>
<p>This code shows a test for a webview-based app going through a login scenario with invalid credentials. For this example I considered [csharp] and the <a href="https://github.com/appium/appium-dotnet-driver" title=".NET Appium Driver" target="_blank">.NET Appium Driver</a> developed by the Appium team.</p>
<h2><a id="q7"></a>Q7 - What is Appium&#39;s most considerable limitation?</h2>
<p>Hand down my chin starting thinking and mumbling. If I had to provide one single thing you should be aware of about Appium before starting using it, it would surely be: <strong>multiple session handling</strong>. Since Appium is a server, it serves HTTP requests; you might have two different computers running a test each against the same Appium server: what happens? As for now, Appium does not support this scenario and the second test will be aborted. This is a considerable limitation, because no queuing system comes with Appium. If you need to support multiple sessions, you will need to implement this feature by yourself.</p>
<h2><a id="q8"></a>Q8 - How active is Appium?</h2>
<p>Appium is available on <a href="https://github.com/">GitHub</a> and there you can find all you need. The Appium team is responsible for developing many different subsystems revolving around Appium (like APIs for different languages), thus I can tell you that this product is alive and very active. The team is also pretty well responsive and once you open an issue you will find a reply after no more than 36 hours (this ETA comes by my personal experience). The community around Appium is also pretty large and growing every month.</p>
<h2><a id="q9"></a>Q9 - What about performance?</h2>
<p>Appium is not a huge application and <strong>requires very little memory</strong>. Its architecture is actually pretty simple and light as Appium acts like a proxy between your test machine and each platform automation toolkit. Once up and running, Appium will listen to HTTP requests from your tests; when a new session is created, a component in Appium&#39;s <a href="http://nodejs.org/">Node.js</a> code called _proxy_ will forward these Selenium commands to active platform drivers. In the case of Android for example, Appium will forward incoming commands to the [chromedriver] (90% of cases, Appium will not even change commands while routing them), this happens because ChromeDriver supports WebDriver and Selenium. For this reason Appium will not allocate much memory itself, you will see a lot of memory being allocated by other processes like [adb], ChromeDriver or the iOS automation toolkit (called by Appium while testing and automating).</p>
<h2><a id="q10"></a>Q10 - Which approach is the best? Testing on real devices or simulators/emulators?</h2>
<p>This is a tough question because both options offer different levels of testability and flexibility when testing. There are also many problems associated with each. So my answer will be again: &quot;It depends on your needs!&quot;.</p>
<h3>Tests on real devices</h3>
<p>Running test on a device is, always in my opinion, the best solution because it offers a testing environment completely aligned with the running environment: tests run on those devices where your apps will be used &nbsp;once published on stores. However devices must be connected to the Appium server via USB at least, and this is not always a very nice thing. ADB has a known issue for which a device disconnects after a while (even though it remained plugged all the time): because of this your tests might fail after a while and Appium will report that a device could not be found! I had to write a component which resets ADB after some time so that devices will not disconnect.</p>
<h3>Tests on emulators or simulators</h3>
<p>On the other hand emulators/simulators will never disconnect from Appium. They also offer nice options like the ability of choosing the orientation or other hardware-related configurations. However your tests will run much slower (sadly, my tests ran 3 times slower) and do expect some crazy behavior from the Android emulator which sometimes shuts down unexpectedly. Another problem is that emulators tend to allocate a lot of memory.</p>
<h2><a id="q11"></a>Q11 - What platforms are supported?</h2>
<p>Appium currently supports <strong>Android</strong> and <strong>iOS</strong>, no support for Windows unfortunately.</p>
<h2><a id="q12"></a>Q12 - Do I need a server machine to run tests on Appium?</h2>
<p><strong>No</strong>! Appium promotes a 2-tier architecture where a test machine connects to a test server running Appium and automating the whole thing. However this configuration is not mandatory, you can have Appium running on the same machine where your test runs. Instead of connecting to a remote host, your test will connect to Appium using the loopback address.</p>
<h2><a id="q13"></a>Q13 - I already have platform-specific tests for my app, what should I do to migrate to Appium?</h2>
<p>Unfortunately there is not a magic formula to translate your tests into Selenium tests. If you developed a test framework on different layers and observed good programming principles, you should be able to act on some components in your tests in order to migrate your suites to Appium. Your current tests are going to be easy to migrate if they are already using an automation framework or something close to a command-based interaction. Truth being told, you will probably need to write your tests from the beginning, what you can do is actually reusing your existing components.</p>
<h3><a id="q13a"></a>Q13A - How much time does it take to write a test in Appium?</h3>
<p>Of course it depends by the test. If your test simply runs a scenario, it will take as many commands as the number of interactions needed to be performed (thus very few lines). If you are trying to exchange data, then your test will take more time for sure and the test will also become difficult to read.</p>
<h3><a id="q13b"></a>Q13B - Any tips or tricks to speed up my test writing activity or my migration process?</h3>
<p>Here is <strong>one piece of advice</strong>. Since your tests will mostly consist in automation tasks (if this condition is not met, you might want to reconsider using Appium), make interactions reusable! Do not write the same sub-scenarios twice in your tests, make a diagram of what your scenarios are and split them in sub activities; you will get a graph where some nodes are reachable from more than one node. So make those tasks parametric and call them in your tests! This will make your test writing experience better even when you need to migrate from existing tests (hopefully you already did this activity for your existing suites).</p>
<h2><a id="q14"></a>Q14 - What test frameworks are supported by Appium?</h2>
<p>Appium does not support test frameworks because there is no need to support them! You can use Appium with <strong>all test frameworks</strong> you want. <a href="http://www.nunit.org/">NUnit</a> and <a href="http://msdn.microsoft.com/en-us/library/dd264975.aspx">.NET Unit Test Framework</a> are just a few examples; you will write your tests using one of the drivers for Appium; thus your tests will interface with Appium just in terms of an external dependency. Use whatever test framework you want!</p>
<h2><a id="q15"></a>Q15 - Can I interact with my apps using Javascript while I am testing with Appium?</h2>
<p><strong>Yes</strong>! Selenium has commands to execute Javascript instructions on your app from your tests. Basically you can send a JS script from your test to your app; when the commands runs on Appium, the server will send the script to your app wrapped into an anonymous function to be executed.</p>
<h3>Returning values</h3>
<p>However your Javascript interaction can get more advanced as your script can return a value which will be delivered to your test when the HTTP response is sent back by Appium once your Javascript has finished running. However this scenario comes with a limitation: your Javascript can send back only primitive types (integers, strings), not complex objects. The limitation can be overtaken by passing objects as JSON strings or by modifying Appium&#39;s or Selenium&#39;s code to support specific objects.</p>
<h2><a id="q16"></a>Q16 - How can I exchange data between my test and the app I am testing?</h2>
<p>Appium, actually the WebDriver specification, is not made for exchanging data with your app, it is made to automate it. For this reason, you will probably be surprised in finding data exchange not so easy. Actually it is not impossible to exchange data with your app , however it will require you to build more layers of testability.</p>
<h3>What data exchange is</h3>
<p>When I say &quot;data exchange&quot; I am not referring to scenarios like getting or setting the value of a textbox. I am also not referring to getting or setting the value of an element&#39;s attribute. All these things are easy to achieve in Appium as Selenium provides commands just for those. By &quot;data exchange&quot; I mean exchanging information hosted by complex objects stored in different parts of your webview-based app like the <span class="at-codeline">window</span> object. Consider when you dispatch and capture events, your app can possibly do many things and the ways data flows can be handled are many. Some objects might also have a state and the state machine behind some scenarios in your app can be large and articulated. For all these reasons you might experience problems when testing.</p>
<h3>Testability layers</h3>
<p>In order to make things better, as a developer, what you can do is adding testability layers to your app. The logic behind this approach is simply having some test-related objects in your app which are activated only when your tests run. I learned about this strategy from one of my colleagues <em>Lukasz</em> and such a technique can be really powerful. Enable your testability layers when testing in order to make data exchange easy.&nbsp;</p>
<h3>Exchanging data through Javascript</h3>
<p>Selenium provides commands do execute Javascript on the app, it is also possible to execute functions and have them return data (only basic types). If you exchange JSON strings it should be fine as <span class="at-codeline">JSON.stringify(str)</span> will turn your <a href="http://json.org">JSON</a> string into an object on the app side, while on the test side (depending on the language you are using), you can rely on hundreds of libraries to parse the string you receive.</p>
<h2><a id="q17"></a>Q17 - What are the most difficult scenarios to test with Appium?</h2>
<p>As I already mentioned in <a href="#q6">Question 6</a>&nbsp;and <a href="#q16">Question 16</a>, Appium is not suitable for all types of tests. There is a particular scenario that will make your tests more difficult to write: <strong>data exchange</strong>. I already said it but I will repeat the same thing because it is very important: Appium and WebDriver are designed to automate stuff... not to exchange data with them. So what if we need to exchange information with our app during tests? Should we give up on Appium and write our tests manually for each platform? I am not saying this, but there are cases where you should consider this option (not nice I know, but if the effort of writing tests for Appium is higher than the benefits, than just throw Appium away).</p>
<p>Appium is very nice because it will let you write tests once for all platofrms instead of writing as many tests as the numbers of platforms you need to support. So if you need to exchange data with your app while testing it and this data flow is the same for all platforms, then you should probably keep on using Appium and find a way to write a layer on top of it to handle data. Depending on your needs this might take time, but, in my experience, it is really worth it.</p>
<h2><a id="q18"></a>Q18 - I don&#39;t want to set up a whole infrastructure for my tests and I don&#39;t want to spend money on HW. Can Appium help me?</h2>
<p>If you think about it, what really is required from you is writing tests. Then the fact that you must deploy an Appium server somewhere is something more. If you want to skip this part, you can rely on some web services that already deployed a whole architecture of Appium servers for your tests. Most of them are online labs and they support Selenium and Appium. Among the most famous you can find: <a href="https://saucelabs.com/" title="SauceLabs" target="_blank">SauceLabs</a>.</p>
<h2><a id="q19"></a>Q19 - I need to debug Appium, is it difficult?</h2>
<p><strong>No really</strong>! Appium is a <a href="http://nodejs.org/">Node.js</a> application, so it is Javascript in the essence. The code is available on <a href="https://github.com/">GitHub</a> and can be downloaded in few seconds as it is small and not so complex. Depending on what you have to debug, you will probably need to go deeper in your debugging experience, however there are some key points where setting a breakpoint is always worth: the <em>proxy</em> component is worth a mention. In <span class="at-codeline">appium/lib/server/proxy.js</span> you can set a breakpoint in function <span class="at-codeline">doProxy(req,res)</span>, that will be hit everytime commands are sent to platform-specific components to be translated into automation commands.</p>
<h2><a id="q20"></a>Q20 - I build my apps with <a href="http://cordova.apache.org/">Cordova</a>, is it supported by Appium?</h2>
<p><a href="http://cordova.apache.org/">Cordova</a> is a very famous system that enables you to develop webview-based apps for all platforms in short time. Appium does not explicitely say that Cordova is supported, even though they do it implicitely as some examples using apps built with Cordova are provided on Appium&#39;s website. So the answer is that <strong>Cordova should not be a problem</strong>. Why am I being so shy about it? Because anything can happen and it actually happened to me!</p>
<p>Cordova and Appium are two different projects that are growing up separately and independently, of course a mutual acknowledgement is present, but both teams do not really talk to each other when pushing features. So problems can occur (I am currently dealing with a problem concerning Cordova&#39;s new version which is causing my tests to fail).</p>
<h2><a id="q21"></a>Q21 - What are the basic commands that I can use in the <a href="https://code.google.com/p/selenium/">Selenium</a> protocol?</h2>
<p>Google&#39;s <a href="https://code.google.com/p/selenium/">Selenium</a> provides a collection of commands to automate your app. With those commands you can basically do the following:</p>
<ul>
<li>Locate web elements in your webview-based app&#39;s pages by using their ids or class names.</li>
<li>Raise events on located elements like <span class="at-codeline">Click()</span>.</li>
<li>Type inside textboxes.</li>
<li>Get or set located element&#39;s attributes.</li>
<li>Execute some Javascript code.</li>
<li>Change the context in order to test the native part of your app, or the webview. If your app uses more webviews, you can switch the context to the webview you desire. If your webview has frames or iframes inside, you can change context to one of them.</li>
<li>Detect alert boxes and dismiss or accept them. Be careful about this functionality, I experienced some problems.</li>
</ul>
<h2><a id="q22"></a>Q22 - I want to run my tests in a multithreaded environment, any problems with that?</h2>
<p><strong>Yes</strong>! You need some special care when using Appium in a multithreaded environment. The problem does not really rely on the fact of using threads in your tests: you can use them but you must ensure that no more than one test runs at the same time against the same Appium server. As I mentioned, Appium does not support multiple sessions, and unless you implemented an additional layer on top of it to handle this case, some tests might fail.</p>
<h3>No problems if i&#39;s the same sessions!</h3>
<p>If, in the context of the same test, you run multiple threads issuing different commands at the same time, some problems might occur but they relate to the state of your app, Appium should not really have problems with that because those commands are received from the same test session!&nbsp;</p>
<h2>So... Is Appium worth a try?</h2>
<p>Definitely <strong>yes</strong>! Actually, I think that Appium is worth the choice. Today many developers started using it and a lot of test frameworks are relying on this technology. I think Appium will grow even more next months, so my suggestion is to keep an eye on it, WebDriver and Selenium as they will probably become a de-facto standard in web-application testing.</p>
<h3>Enterprise level</h3>
<p>That being said, let me also tell you that Appium, <a href="http://en.wiktionary.org/wiki/IMHO">IMHO</a>, is still not so mature for testing complex features in your apps. I said it already: exchanging data is not easy and Appium is not to be blamed because based on Selenium; however I have a good feeling about this; exchanging information with apps while testing is important and this necessity will probably lead the community to create layers on top of Appium or, who knows, Appium might solve this itself.&nbsp;</p>
<h3>Please keep in mind...</h3>
<p>Before leaving you, just one more thing. All my feedback and experience I shared here today relates to technologies at their current versions (or those I have been using so far). As things change, I will publish more posts, but everything I assessed so far relates to <a href="http://appium.io">Appium</a> 1.2.4 and <a href="http://cordova.apache.org/">Cordova</a> 3.6.3.</p>
<p class="at-endlinebox">The views and opinions expressed in this blog are those of the authors and do not necessarily reflect the official policy or position of any other agency, organization, employer or company.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to set up a basic working Appium test environment</title>
      <link>https://docs.microsoft.com/archive/blogs/antino/how-to-set-up-a-basic-working-appium-test-environment</link>
      <pubDate>Mon, 22 Sep 2014 07:49:00 GMT</pubDate>
      <dc:creator><![CDATA[Andrea Tino]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/antino/2014/09/22/how-to-set-up-a-basic-working-appium-test-environment/</guid>
      <description><![CDATA[Appium is a test framework targeting devices; although it is very handy and powerful, it is not so...]]></description>
      <content:encoded><![CDATA[<p><a href="http://appium.io">Appium</a> is a test framework targeting devices; although it is very handy and powerful, it is not so straightforward and easy to install. Furthermore, the documentation (<a href="http://en.wiktionary.org/wiki/IMHO">IMHO</a>) does not provide a good tutorial to get things working as fast as possible. In this post, I am going to provide all that needs to set up Appium for running a basic test scenario written in <a href="http://msdn.microsoft.com/en-us/library/kx37x362.aspx">C#</a>.</p>
<h2>What is Appium?</h2>
<p>Appium is used to automate tests on devices with the main objective of allowing users to write tests once, and run them on different platforms and devices with no further effort. The main idea behind Appium can be easily grasped by looking at the following figure.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appiumovw.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appiumovw.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appiumovw.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appiumovw.png" alt=" " style="display:block;margin-left:auto;margin-right:auto;" border="0" /></a></p>
<p>The basic workflow to test with Appium is the following:</p>
<ol>
<li>Tests are written using different languages (Appium supports many of them: <a href="https://www.ruby-lang.org">Ruby</a>, <a href="http://msdn.microsoft.com/en-us/library/kx37x362.aspx">C#</a> and <a href="https://www.oracle.com/java">Java</a> to list some).</li>
<li>A server running Appium (the <em>test server</em>) is configured and made available on a certain network location.</li>
<li>Devices, or their corresponding simulators, are connected to the test server.</li>
<li>Tests are run from the <em>test machine</em>.</li>
</ol>
<p>Please note that in the last point I said: &quot;tests are run <strong>from</strong>...&quot;; this is our point of entry to understand how Appium works. The client/server pattern helps Appium achieve multi-platform testability, once a test is written it is executed in the client/test station. Thanks to Google&#39;s <a href="http://json.org">JSON</a> [seleniumwebdriver], Appium is able to have tests send commands to devices through the test server.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appiumwork.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appiumwork.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appiumwork.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appiumwork.png" alt=" " style="display:block;margin-left:auto;margin-right:auto;" border="0" /></a></p>
<p>When writing Appium tests, the code will simply perform <a href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a> calls to the server which will translate those meta-commands into device-specific actions sent to the device to test. Commands are essentially user interactions with the app like clicking an interface component, swiping on the screen, scrolling onto a particular area or performing a specific gesture. Appium also supports execution both on real devices and simulators.</p>
<h3>A little problem with naming</h3>
<p>So if somebody asked us: &quot;Where does my test run on?&quot; we would probably find some uneasiness when replying. In fact we launch our tests from a client machine, but they actually run on our devices (or their simulators). So how to put things in order? The solution is in how we describe the process. The following statement can help:</p>
<p class="at-importantbox">Tests are actually <span style="font-weight:bold;">run from</span> a test client and they are <span style="font-weight:bold;">executed on</span> a device or its simulator <span style="font-weight:bold;">via</span> the test server.</p>
<h2>Writing your first test in C#<a id="write_test"></a></h2>
<p>In Appium&#39;s philosophy, a test for an app should be written only once, then it is supposed to run on different platforms with no further work.</p>
<p>The first thing we take care of is locating all configuration settings needed to pass to the server in order to run our tests. Appium&#39;s API consists of some important classes, one of these is <span class="at-codeline">DesiredCapabilities</span>. This class defines the most important parameters to have the server run tests in the correct testing environment; in order to keep track of these settings, let&#39;s create a wrapper that we can reuse.</p>
<div class="at-codebox">
<pre><code>public sealed class TestCapabilities { 
  /// Tracking platforms  
  public enum DevicePlatform {
    Undefined,
    Windows,
    IOS,
    Android
  }

  public string BrowserName      { get; set; }
  public string FwkVersion       { get; set; }
  public DevicePlatform Platform { get; set; }
  public string PlatformVersion  { get; set; }
  public string DeviceName       { get; set; }
  public string App              { get; set; }
  public bool   AutoWebView      { get; set; }
  public string AutomationName   { get; set; }

  public TestCapabilities() {
    this.BrowserName     = String.Empty;
    this.FwkVersion      = String.Empty;
    this.Platform        = DevicePlatform.Undefined;
    this.PlatformVersion = String.Empty;
    this.DeviceName      = String.Empty;
    this.App             = String.Empty;
    this.AutoWebView     = false;
    this.AutomationName  = String.Empty;
  }

  public void AssignAppiumCapabilities(ref DesiredCapabilities appiumCapabilities) {
    appiumCapabilities.SetCapability(&quot;browserName&quot;,     this.BrowserName);
    appiumCapabilities.SetCapability(&quot;appium-version&quot;,  this.FwkVersion);
    appiumCapabilities.SetCapability(&quot;platformName&quot;,    this.Platform2String(this.Platform));
    appiumCapabilities.SetCapability(&quot;platformVersion&quot;, this.PlatformVersion);
    appiumCapabilities.SetCapability(&quot;deviceName&quot;,      this.DeviceName);
    appiumCapabilities.SetCapability(&quot;autoWebview&quot;,     this.AutoWebView);

    // App push (will be covered later)
    if (this.App != String.Empty)
      appiumCapabilities.SetCapability(&quot;app&quot;, this.App);
  }

  /// Converting to string the platform (for Appium)
  private string Platform2String(DevicePlatform value) {
    switch (value) {
    case DevicePlatform.Windows:
      return &quot;win&quot;; /* TODO: Need to write your own extension of Appium for this */
    case DevicePlatform.IOS:
      return &quot;iOS&quot;;
    case DevicePlatform.Android:
      return &quot;Android&quot;;
    default:
      return &quot;&quot;;
    }
  }
}
</code></pre>
</div>
<p>In the most simplistic scenario, you will run your tests against the same server. However in a more enterprise-level context, you might need to deploy more test servers depending on the tests you have. It is good practice to keep track of your servers.</p>
<div class="at-codebox">
<pre><code>public static class TestServers {        
  public static string Server1 { get { return &quot;http://192.168.2.23:3445/wd/hub&quot;; } }
  public static string Server2 { get { return &quot;http://192.168.2.24:3446/wd/hub&quot;; } }
  public static string Server3 { get { return &quot;http://192.168.2.36:3432/wd/hub&quot;; } }
  public static string Server4 { get { return &quot;http://192.168.2.36:3436/wd/hub&quot;; } }
  public static string Server5 { get { return &quot;http://192.168.2.38:3445/wd/hub&quot;; } }
  public static string Server6 { get { return &quot;http://192.168.2.39:3445/wd/hub&quot;; } }
}
</code></pre>
</div>
<p><strong>First step done!</strong></p>
<h3>Your first test suite and all dependencies you need</h3>
<p>Our final test is ready to be crafted now. Before writing it, however, we need to download the <a href="http://docs.seleniumhq.org/download/" title="Selenium WebDriver for C#" target="_blank">Selenium WebDriver</a> for C# so that we can send commands to the Appium server using C#.</p>
<ol>
<li>Go to <a href="http://docs.seleniumhq.org/download/" title="Selenium WebDriver for C#" target="_blank">Selenium WebDriver</a> download page and download the driver for C#.</li>
<li>Unzip the folder and show its content.</li>
<li>Locate the .NET version you need and copy that folder into your test project&#39;s dependency directory.</li>
<li>Reference all assemblies in your project.</li>
</ol>
<p>One more thing we need is the <a href="https://github.com/appium/appium-dotnet-driver" title="Appium Dot Net Driver" target="_blank">Appium Dot Net Driver</a> in order to get some more tools.</p>
<ol>
<li>Go to <a href="https://github.com/appium/appium-dotnet-driver" title="Appium Dot Net Driver" target="_blank">Appium Dot Net Drive&#39;</a>s page on GitHub and download it in your test client (where your test solution is located).</li>
<li>Unzip the content and navigate to the &quot;appium-net-driver&quot; project folder.</li>
<li>Open the project in Visual Studio and build it.</li>
<li>Locate output assemblies (a &quot;bin&quot; folder should be created) and copy them into your test&#39;s project.</li>
<li>Add references to these assemblies in your test solution.</li>
</ol>
<p>Now we can get to the test suite. The code below provides a basic template to have an Appium test ready to run. Here I am not providing a specific unit test implementation, read Appium&#39;s API in order to learn how to use automation tools for that.</p>
<div class="at-codebox at-box-big">
<pre><code>namespace AppiumTests
{
  using System;
  using Microsoft.VisualStudio.TestTools.UnitTesting; /* We use .NET UnitTest Fwk, but any unit test fwk can be used */
  using AppiumTests.Helpers;
  using AppiumTest.Framework;
  using OpenQA.Selenium; /* Appium is based on Selenium, we need to include it */
  using OpenQA.Selenium.Appium; /* This is Appium */
  using OpenQA.Selenium.Appium.Interfaces; /* Not needed for commands shown here. It might be needed in single tests for automation */
  using OpenQA.Selenium.Appium.MultiTouch; /* Not needed for commands shown here. It might be needed in single tests for automation */
  using OpenQA.Selenium.Interactions; /* Not needed for commands shown here. It might be needed in single tests for automation */
  using OpenQA.Selenium.Remote;

  [TestClass]
  public class AppiumTestSuite
  {
    private AppiumDriver driver;

    private static Uri testServerAddress = new Uri(TestServers.Server1);
    private static TimeSpan INIT_TIMEOUT_SEC = TimeSpan.FromSeconds(180); /* Change this to a more reasonable value */
    private static TimeSpan IMPLICIT_TIMEOUT_SEC = TimeSpan.FromSeconds(10); /* Change this to a more reasonable value */

    [TestInitialize]
    public void BeforeAll()
    {
      DesiredCapabilities capabilities = new DesiredCapabilities();
      TestCapabilities testCapabilities = new TestCapabilities();

      testCapabilities.App = &quot;&quot;;
      testCapabilities.AutoWebView = true;
      testCapabilities.AutomationName = &quot;&quot;;
      testCapabilities.BrowserName = String.Empty; // Leave empty otherwise you test on browsers
      testCapabilities.DeviceName = &quot;Needed if testing on IOS on a specific device. This will be the UDID&quot;;
      testCapabilities.FwkVersion = &quot;1.0&quot;; // Not really needed
      testCapabilities.Platform = TestCapabilities.DevicePlatform.Android; // Or IOS
      testCapabilities.PlatformVersion = String.Empty; // Not really needed

      testCapabilities.AssignAppiumCapabilities(ref capabilities);
      driver = new AppiumDriver(testServerAddress, capabilities, INIT_TIMEOUT_SEC);
      driver.Manage().Timeouts().ImplicitlyWait(IMPLICIT_TIMEOUT_SEC);
    }

    [TestCleanup]
    public void AfterAll()
    {
      driver.Quit(); // Always quit, if you don&#39;t, next test session will fail
    }

    /// 
    /// Just a simple test to heck out Appium environment.
    /// 
    [TestMethod]
    public void CheckTestEnvironment()
    {
      var context = driver.GetContext();
      Assert.IsNotNull(context);
    }
  }
}
</code></pre>
</div>
<p><strong>Done!</strong> The test suite is ready to be run. As you can see I am using <a href="http://www.nunit.org/">NUnit</a> as unit test framework, however you can use whatever test framework you like; Appium is not affected by this and will work as expected.</p>
<h2>Setting up an Appium test server</h2>
<p>In the first part of this article I described the client/server nature of Appium; however this does not mean that you need two computers for testing your app, a standalone deployment is possible and consists of having the Appium test server installed and running on the same machine where tests will run from. Since I want to cover a generic scenario, this tutorial will consider the following architecture:</p>
<ul>
<li>A Windows test client.</li>
<li>A Mac test server.</li>
<li>One Android and one Apple tablet.</li>
</ul>
<p>The network configuration is depicted by the following figure.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appium.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appium.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/appium.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/appium.png" alt=" " style="display:block;margin-left:auto;margin-right:auto;" border="0" /></a></p>
<p>The first thing we need to do is installing the Appium server, then we will take care of devices.</p>
<h3>Installing the Appium server</h3>
<p>Our scenario covers Appium server on Mac, but the installation process is quite the same for Windows and Unix as well. However please take care of one important thing: the server needs to be connected to devices or run their simulators, for all platforms (Windows, iOS and Android) vendors provide different SDKs; however not all SDKs are available for all OSs, so your testing options will be limited as per the following matrix.</p>
<table class="at-table"><caption>SDK availability across server deployments</caption>
<thead>
<tr>
<td>Appium srv deployed on</td>
<td class="at-textalign-center">Windows SDK(*)</td>
<td class="at-textalign-center">iOS SDK</td>
<td class="at-textalign-center">Android SDK</td>
</tr>
</thead>
<tbody>
<tr>
<td>Windows</td>
<td class="at-textalign-center">Yes</td>
<td class="at-textalign-center">No</td>
<td class="at-textalign-center">Yes</td>
</tr>
<tr>
<td>Mac OS</td>
<td class="at-textalign-center">No</td>
<td class="at-textalign-center">Yes</td>
<td class="at-textalign-center">Yes</td>
</tr>
<tr>
<td>Unix/Linux</td>
<td class="at-textalign-center">No</td>
<td class="at-textalign-center">No</td>
<td class="at-textalign-center">Yes</td>
</tr>
</tbody>
</table>
<p>(*) Appium still does not support tests on Windows: it means that tests cannot be run on Windows simulator and on Windows mobile devices; just reporting for future possible extensions.</p>
<p>As it is possible to see, a single server will never be able to allow tests on all possible device platforms. Another important thing to know about Appium is that it can be installed on all OSs reported in the matrix above.</p>
<p>To install Appium, follow these steps:</p>
<ol>
<li>Go to the <a href="http://appium.io" title="Appium.io" target="_blank">Appium website</a>.</li>
<li>Download the latest version of the software according to your OS.</li>
<li>Run the installer and complete all steps (almost no configuration).</li>
<li>Once done, launch Appium and click on the gear icon on the top-left side of the screen.</li>
<li>Make sure that the &quot;Server Address&quot; field is set to the local address &quot;0.0.0.0&quot; and the &quot;Port&quot; field next to it is st to &quot;4723&quot; (or set it to another valid non-used port).</li>
</ol>
<p><strong>And done!</strong> There is no further configuration to perform. Next step is configuring devices or their simulators. Here as well it is important to understand an important concept: either you are going to test on a real device or on its simulator, you will need that device SDK. Appium will take advantage of the SDK to connect to the simulator or the real device connected via USB. Also please be aware that I will not enter in detail for installing SDKs (off topic in this article).</p>
<h3>Testing on iOS</h3>
<p>Since you will run on the iOS simulator, you need to have it running before running your tests (it is not always necessary though).</p>
<ol>
<li>Launch <em>XCode</em> from your machine and open your app&#39;s project.</li>
<li>Navigate to <span class="at-codeline">XCode -&gt; Open Developer Tool -&gt; iOS Simulator</span> and bring up the simulator.</li>
</ol>
<p>To run tests on the iOS simulator, follow these steps in the Appium server:</p>
<ol>
<li>On the top-left corner, click on the radio button below the Apple icon to activate Appium for Apple devices.</li>
<li>Click on the Apple icon (top-left) and bring up the &quot;iOS Settings&quot; window.</li>
<li>Check &quot;App Path&quot; if unchecked and enable the textbox next to it.</li>
<li>Locate field &quot;App Path&quot; and type the absolute path to the .app file of your app. Everytime you compile your XCode project, in the &quot;build&quot; folder, a file called <span class="at-codeline">&lt;project-name&gt;.app</span> is generated; you need to get that file&#39;s path.</li>
<li>Be sure that field &quot;BundleID&quot; is unchecked.</li>
<li>Since we are testing on a tablet, be sure to select &quot;iPad&quot; in field &quot;Force Device&quot;. If you want to test on a different device, choose the most appropriate one for your needs.</li>
<li>Be sure field &quot;UDID&quot; is unchecked.</li>
</ol>
<p><strong>You did it!</strong> The server is ready to accept incoming requests from your tests. Run your server by clicking on the top-right button &quot;Launch&quot;. After that, switch to your test client and run your tests; as soon as they execute you will see, on the server, the iOS simulator coming up and perform all tasks.</p>
<h4>Testing on real device</h4>
<p>To test on a real Apple device (iPad or iPhone), do not touch the configuration you used to test on the simulator and do the following on the test server:</p>
<ol>
<li>Connect your device to the server machine via USB.</li>
<li>Be sure to set up correct provisioning profiles for your devices. Follow <a href="https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/MaintainingProfiles/MaintainingProfiles.html" title="Apple's documentation about provisioning profiles" target="_blank">Apple&#39;s documentation about provisioning profiles</a>.</li>
<li>On your app&#39;s XCode project, navigate to <span class="at-codeline">Windows -&gt; Organizer</span> and bring up the &quot;Organizer&quot; window.</li>
<li>On the left side, locate your device under &quot;Devices&quot; group and select it.</li>
<li>Your device details are shown. Locate field &quot;Identifier&quot; and copy &amp; paste it on a note file, you will need it later.</li>
<li>On the left pane, expand your device to show more options. Locate &quot;Applications&quot; and click on it.</li>
<li>In the &quot;Applications&quot; window for your device, locate your app and copy &amp; paste its BundleID for later. The BundleID is the name reported below (small font) your app&#39;s name.&nbsp;</li>
<li>On Appium, stop the server if it&#39;s still running and&nbsp;click on the Apple icon (top-left) and bring up the &quot;iOS Settings&quot; window.</li>
<li>Check the &quot;BundleID&quot; field and paste there the text you just saved in step 7.</li>
<li>Check the &quot;UDID&quot; field and paste there the 160bit hex value you saved on step 5.</li>
</ol>
<p><strong>You&#39;re ready to go!</strong> Start the server and run you tests; this time you will see your app being deployed and running on the device.</p>
<h3>Testing on Android</h3>
<p>The Android SDK has a very strict virtual environment for simulating; the user must correctly install all needed libraries according to the API level and the Android system version on which the app is supposed to run. The latter is very important in those cases where your apps have a minimum requirement in terms of OS support; thus be sure, in such scenarios, to choose the correct version. Follow these steps to correctly set your <a href="https://developer.android.com/tools/devices/index.">AVD</a> (Android Virtual Device):</p>
<ol>
<li>Open your Eclipse environment on your project.</li>
<li>Refer to the <a href="https://developer.android.com/tools/devices/index.html" title="Android documentation to set up you AVDs" target="_blank">Android documentation to set up you AVDs</a>.</li>
</ol>
<p>To run tests on the Android simulator, follow these steps on the Appium server:</p>
<ol>
<li>On the top-left corner, click on the radio button below the Android icon to activate Appium for Android devices.</li>
<li>Click on the Android icon (top-left) and bring up the &quot;Android Settings&quot; window.</li>
<li>Check &quot;App Path&quot; if unchecked and enable the textbox next to it.</li>
<li>Locate field &quot;App Path&quot; and type the absolute path to the .apk file of your app. Everytime you compile your Eclipse project, in the &quot;bin&quot; folder, a file called&nbsp;<span class="at-codeline">&lt;project-name&gt;.apk</span>&nbsp;is generated; you need to get that file&#39;s path.</li>
<li>Be sure that fields &quot;Package&quot;, &quot;Use Browser&quot; and &quot;Device Name&quot; are unchecked.</li>
<li>Select the correct version for field &quot;Platform Version&quot; according to your Android API version.&nbsp;</li>
</ol>
<p><strong>You&#39;re done!</strong> Run the server by clicking on the top-right button &quot;Launch&quot;. After that, switch to your test client and run your tests; as soon as they execute you will see, on the server, the Android simulator coming up and perform all tasks.</p>
<h4>Testing on real device</h4>
<p>To test on a real Android device, leave your configuration as it was when you set up Appium to work with the simulator and proceed as follows:</p>
<ol>
<li>Connect your device to the server machine via USB.</li>
<li>Click on the top-left button displaying the Android icon and bring up the &quot;Android Settings&quot; window.</li>
<li>Uncheck field &quot;Launch AVD&quot;.</li>
<li>Check field &quot;Device Name&quot;.</li>
<li>Close the Android simulator if it is still running.</li>
</ol>
<p><strong>This is it!</strong> When you run your tests, you will now see your app being deployed and running on your Android device.</p>
<h2>App push from the test client</h2>
<p>One concept is important to understand about Appium when it is configured as we did so far:</p>
<p class="at-importantbox">A test is bound to a single app per each server.</p>
<p>It means that it is not possible to set up an Appium server for testing two different apps. So: &quot;Where is the problem?&quot;, some of you might ask; actually the problem is when we want to create a real infrastructure for testing apps in the context of real enterprise. In such a context it would be nice to set up a server for testing more than one app, however we cannot do this if we need to set the app to test at server side. Appium, however, allows developers to set the app to test from tests; it means that we can transmit the path (on the server) to the app file that should be used to deploy the app itself; only one more capability is needed: <span class="at-codeline">&quot;app&quot;</span>.</p>
<ol>
<li>Get back to the test suite we just wrote <a href="#write_test" title="Write test in C#">before</a>, locate method <span class="at-codeline">GetCapabilities</span>.</li>
<li>Add one more capability as shown below.</li>
</ol>
<div class="at-codebox">
<pre><code>private DesiredCapabilities GetCapabilities() {
  // Other settings...
  capabilities.App = &quot;&lt;absolute-path-to-app&gt;&quot;; /* App-Push */<br />
  return capabilities;
}
</code></pre>
</div>
<ol start="3">
<li>Switch to the server and stop it.</li>
<li>Open your device configuration (click on the top-left Apple or Android icon).</li>
<li>Uncheck field &quot;App Path&quot;.</li>
<li>Start the server again.</li>
</ol>
<p>With this simple but powerful capability, we are now able to write tests covering common base functionalities across different versions of the same app. It is also possible to use the same server to run different tests for different apps. Remember that you need to pass the absolute path to your app file (the file type changes according to the device platform) in your <strong>test server machine&#39;s filesystem</strong>, not the client.</p>
<h3>App push + upload</h3>
<p>I know some of you think that it would be also nice to have tests physically send the app file to the server. Appium does not support this, however nothing can stop you from using <a href="http://en.wikipedia.org/wiki/Secure_Shell">SSH</a> or other remote connection tool to upload your app file to the server machine before running tests.</p>
<p class="at-endlinebox">The views and opinions expressed in this blog are those of the authors and do not necessarily reflect the official policy or position of any other agency, organization, employer or company.</p>
<p><a href="https://onedrive.live.com/redir?resid=28F0C4E5A0596D8%2143506">https://onedrive.live.com/redir?resid=28F0C4E5A0596D8%2143506</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The art of proxying</title>
      <link>https://docs.microsoft.com/archive/blogs/antino/the-art-of-proxying</link>
      <pubDate>Mon, 01 Sep 2014 11:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Andrea Tino]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/antino/2014/09/01/the-art-of-proxying/</guid>
      <description><![CDATA[In a web developer&#39;s life proxying is a technique that sooner or later will become important, in...]]></description>
      <content:encoded><![CDATA[<p>In a web developer&#39;s life <em>proxying</em> is a technique that sooner or later will become important, in some cases even necessary depending on project&#39;s scale and complexity. In this article I will cover basic theoretical aspects about proxies, and illustrate how they work and what applications they have in real life.</p>
<h2>Basics on proxies</h2>
<p>A proxy is a generic entity used to act as a (possibly transparent) third party component in the context of a whatever interaction. However, when using the term <em>proxy</em>, people usually refer to <em>web proxies</em>. A web proxy basically is a web server which intermediates in HTTP communications between different hosts. The basic idea behind a proxy is having host A communicate to host B through a server (the proxy): this architecture enables several scenarios, useful for developers, that I am going to illustrate.</p>
<p>There are basically two possible ways a proxy can be configured, but it is good to start from the basic scenario when no proxy is involved.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/proxy.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/proxy.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/proxy.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x137/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/proxy.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>A normal HTTP session involves a requestor and a web server. An HTTP request is sent to the web server (the requestor needs to know the address of the web server), which replies back with an HTTP response. In this model, a proxy can be placed in different locations: this will determine the type of proxying strategy being used.</p>
<h3>Reverse proxy</h3>
<p>A reverse proxy is an Internet-facing device acting as an intermediary on our side of the LAN, handling requests and dispatching them to one of our hosts in the same network. This scenario is illustrated below.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/revproxy2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/revproxy2.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/revproxy2.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/revproxy2.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>As you can see, the proxy is placed right after the LAN gateway and dispatches messages to the server. This is the most common configuration for a proxy due to the as well very common scenario it supports: <strong>hiding resources</strong>. A reverse proxy in such a configuration can be an interface for the world outside. When a client requests a web page or something else through HTTP (this is also valid for other application protocols), it will not use the IP address of our web server, but the IP address of our proxy; we can then protect our important servers in the LAN giving them private addresses as our proxy will dispatch messages to them. The final result is that our servers will not be exposed to the Internet, only the proxy will, but a proxy usually stores no significant data (differently from our servers), thus if it is successfully hacked, no data leakage will occur and our information will still be safe and not corrupted.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7651.dispatcher.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7651.dispatcher.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7651.dispatcher.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7651.dispatcher.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>The image above shows one of the real usages of a reverse proxy: not only can it hide resources, it is also able to act as a <strong>dispatcher</strong> to many servers in our LAN. In this case the dispatching can be performed based on the URL provided in the HTTP request; consider you are developing a web application to download and stream music: <span style="font-family:&#39;courier new&#39;, courier;">www.listentomusic.com</span>. We do not want our music files to be publicly exposed on the network, so we use a reverse proxy as shown in the picture. However we also provide music information other than the music itself, so when the user accesses our web site it will typically download pages from our web application server, however when he wants to listen to music, addresses will have the following format: <span style="font-family:&#39;courier new&#39;, courier;">www.listentomusic.com/listen/&lt;song-name&gt;</span>. Our proxy will then make a request to the media streaming server providing, in the HTTP header, all security parameters needed to get access to music files. When the user wants to access music info, he can type <span style="font-family:&#39;courier new&#39;, courier;">www.listentomusic.com/artist/&lt;name-of-artist&gt;</span> or <span style="font-family:&#39;courier new&#39;, courier;">www.listentomusic.com/song/&lt;name-of-song&gt;</span>, this will have the proxy redirect the request to the data center server instead.</p>
<h3>Load balancing</h3>
<p>Another very common strategy in networking involving reverse proxies is&nbsp;<strong>load balancing</strong>; a reverse proxy can be really handy in this case. Consider the situation depicted in the picture below: our service is expected to provide responses to a very high number of requests, in this case chances are that a single server is not enough, since we are a small business company, we cannot really afford a high-level performance server, however we can always rely on the&nbsp;<a href="http://en.wikipedia.org/wiki/Divide_and_rule" title="Dividi et Impera" target="_blank">Dividi et Impera</a>&nbsp;approach: we can buy more average-performance servers and have the proxy balance the load.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/loadbal.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/loadbal.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/loadbal.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/loadbal.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>A reverse proxy improves <strong>security</strong>, resource protection and <strong>maintenance</strong> as well. Say for example that you need to migrate your server to a different system, your server will probably be down for 12 hours at least. No problem, you can create a cloned low-performance server for one day and redirect traffic there while you are migrating your real server: you will keep you service alive without users noticing as the proxy will redirect traffic on a different location while serving requests to the same public address.</p>
<h3>Forward proxy</h3>
<p>A forward proxy can be considered as the opposite of a reverse proxy: it is an Internet-facing device which redirects our requests to specific sources.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/forwproxy.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/forwproxy.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/forwproxy.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/forwproxy.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>The purpose of such an architecture is having client&#39;s requests redirected (transparently to the client) to another location from the original one. Why? There are possible rationales.</p>
<ul>
<li><strong>Anonymity</strong> This represents the 95% of reasons for which one would use a forward proxy and, sadly speaking, seeking for anonymity generally means that someone is willing to perform not so nice actions on the web. A forward proxy, in fact, will not let the server know who really is looking for a specific resource as the proxy will be seen as the requestor. Think of a forward proxy like a trader, it will protect your identity acting as an intermediate unit between you and the server.</li>
<li><strong>Source selection</strong> This application is not so common and is meaningful if you are a developer or a tester. If we were developing a distributed system, we could use a proxy as a traffic router to direct all requests to a specific source. This can be good when performing stress tests for example.</li>
</ul>
<h4>Open proxies</h4>
<p>Forward proxies became very famous on the web when private subjects or companies started offering free <strong>forward-proxying service</strong>. Not so much time ago, network administrators used to block users&#39; access to social networks, like Facebook, Google+ or Twitter, in corporate or university campus LANs. Usually this common practice was meant to improve bandwidth and prevent employees or students from taking too much leisure time on blogging or socializing during work/study time.</p>
<p>Achieving this block is easy: firewalls would not let in or out packets whose source/destination IP address is part of a blacklist. Well, we all know people are very smart especially when it comes to breaking the rules, in fact a solution to this problem (if we want to call it so) came very fast: using a forward proxy to access social networks.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/tunnel.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/tunnel.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/tunnel.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/tunnel.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>The figure above shows how it is possible to deceive the university firewall when getting access to our social network by relying on a <strong>tunneling proxy</strong>. An open proxy is in fact a tunneling proxy: it takes all requests and simply forwards them to a specific destination without changing them (only the source address will be changed). If we use a proxy, our request will not be directed to the social network&#39;s server, but to the proxy; the firewall will not block our request because it is not part of the blacklist. Also, when we receive the reply, we will receive it form the same exact proxy, this time as well the firewall will let the pack go through.</p>
<p>Few years ago there were many proxies available on the web to let people connect to social networks, however network administrators got a little smarter and firewalls today are also able to inspect the HTTP content of TCP/IP packets. Instead of relying on addresses, firewalls inspect the content of packets, thus they can access the HTML header in order to find traces of social networks. But it&#39;s not like this little war is over, more techniques have been implemented to work around these blocking systems. By the way, today employers prefer not to prevent their employees from accessing social networks, the same goes for students in universities: it is way cheaper to let everybody have their leisure time instead!</p>
<h2>Proxy design and implementation</h2>
<p>Designing a proxy is not so difficult, in this section I am going to describe the most common principles to follow when developing a proxy so that it works as expected.</p>
<h3>Handling communications</h3>
<p>A web proxy must ensure transparency and allow a communications between two hosts to take place when it is actually acting as a <a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">Man In The Middle</a>. The figure below illustrates how a proxy should handle requests and responses.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7455.proxydsg.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7455.proxydsg.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/7455.proxydsg.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/7455.proxydsg.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>When a proxy receives a request it must hold it and, in the meantime, fire a new request to the real destination. After host A sends a request to the proxy (we are not covering a Man In The Middle attack, so host A is perfectly aware of the existence of a proxy), the proxy will take some time to hold the request and create a new HTTP request to host B. Host B will replies after a while (time necessary to retrieve the requested resource) and then the HTTP response lands on proxy, which will change the source address with its own and forward it to host A.</p>
<h3>Ensuring association</h3>
<p>The other thing a proxy should take care of are associations between requests and responses. Since a proxy is a server, it will process more than a request; for this reason a proxy must be able to correctly manage all session couples (hostA-Proxy and Proxy-hostB). In the figure shown before, we can see that a proxy handles two different sessions both sharing an address: the proxy; once a request is handled in the first session, it must be saved until the session with destination host terminates. It is important not to mix up sessions and keeping all couples consistent. Other than a communication problem this is a security issue as well.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/multiproxy1.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/multiproxy1.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/multiproxy1.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/multiproxy1.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>The figure above shows a proxy serving request using a <strong>queuing system</strong>. This can be quite a naive approach but it works: all requests are saved in a queue as they arrive. Whenever ready to process a new request, after terminating processing a full session, the proxy will take care of the next one. As all queues, it is important to know well the expected throughput so that queues can be sized correctly, otherwise the probability of data loss due to full queues can become very high.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/2860.multiproxy2.png" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/2860.multiproxy2.png"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/03/22/2860.multiproxy2.png" original-url="http://blogs.technet.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-03-22/2860.multiproxy2.png" border="0" alt=" " style="display:block;margin-left:auto;margin-right:auto;" /></a></p>
<p>The approach shown in the picture above is now the opposite: <strong>multi-threaded proxy</strong>. Dispatching threads as requests arrive is a good idea; however there is a limit in threading due to shared resources. Modern proxies use thread pools in order to handle thread creation. It means that a new thread is not created every time a new requests arrives, modern algorithms evaluate the machine status and decide whether new threads should be created or reused.</p>
<p class="at-endlinebox">The views and opinions expressed in this blog are those of the authors and do not necessarily reflect the official policy or position of any other agency, organization, employer or company.</p>]]></content:encoded>
    </item>
  </channel>
</rss>