{"id":5328,"date":"2013-09-12T14:39:42","date_gmt":"2013-09-12T11:39:42","guid":{"rendered":"http:\/\/railsware.com\/blog\/?p=5328"},"modified":"2021-08-13T16:18:39","modified_gmt":"2021-08-13T13:18:39","slug":"ios-integration-tests-with-appium","status":"publish","type":"post","link":"https:\/\/railsware.com\/blog\/ios-integration-tests-with-appium\/","title":{"rendered":"iOS Integration Tests With Appium"},"content":{"rendered":"\n<p>I came from the RoR web development and &#8211; as we all know &#8211; Rails community loves tests. Personally, I am a fan of acceptance testing and using mostly capybara for it. So, when I shifted to the iOS development, it was essential for me to find some decent acceptance testing tools like Apple&#8217;s UI Automation, Calabash and Appium. The last one appeared to be a test automation framework of iOS, Android and hybrid apps that supports Ruby among other languages. I&#8217;ve chosen it to be the first one to explore and started writing tests for my current real project. Let&#8217;s see now whether Appium stack is a good choice for the our purposes.<\/p>\n\n\n\n<p>To start with, we need 3 things to run integration tests with Appium:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Appium server<\/li><li>application package<\/li><li>test script<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Appium Installation<\/h2>\n\n\n\n<p>There are two ways to install Appium: download packaged app or install it via npm. I tried to install it via npm, but it didn&#8217;t work, so I opted for a bundled app and successfully ran couple examples. Then, however, I decided to fix my Appium npm install and managed to run it from console by completely reinstalling node and manually cleaning <i>\/usr\/local\/share\/npm<\/i>.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$: sudo npm install -g appium\n$: appium\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Make app build<\/h2>\n\n\n\n<p>Below is a simple script to create a build and place it inside the desired folder to easily access it from test whenever required.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">xcodebuild -sdk iphonesimulator6.0 \\\n  -workspace \/Users\/mishyn\/workspace\/rw\/project-ios\/Project.xcworkspace \\\n  -scheme Project \\\n  ONLY_ACTIVE_ARCH=NO \\\n  TARGETED_DEVICE_FAMILY=1 \\\n  DEPLOYMENT_LOCATION=YES \\\n  DSTROOT=`pwd`\/app\n<\/pre>\n\n\n\n<p>Don&#8217;t forget to make scheme Project shared, otherwise you might get the following error:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ld: library not found for -lPods\nclang: error: linker command failed with exit pre 1 (use -v to see invocation)\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Write spec<\/h2>\n\n\n\n<p>Here is the template, so we now need to fill in the flows.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">def absolute_app_path\n  file = File.join(File.dirname(__FILE__), 'app\/Applications\/Project.app')\n  raise \"App doesn't exist #{file}\" unless File.exist? file\n  file\nend\n\ncapabilities = {\n  'browserName' =&gt; 'iOS',\n  'platform' =&gt; 'Mac',\n  'version' =&gt; '6.0',\n  'app' =&gt; absolute_app_path\n}\n\nserver_url = \"http:\/\/127.0.0.1:4723\/wd\/hub\"\n\ndescribe \"Computation\" do\n  before :all do\n    @driver = Selenium::WebDriver.for(:remote, :desired_capabilities =&gt; capabilities, :url =&gt; server_url)\n   end\n\n  after :all do\n    @driver.quit\n  end\n\n  it \"should open search\" do\n    @driver.find_elements(:tag_name, '*')\n  end\nend\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Finding elements<\/h3>\n\n\n\n<p>Selenium operates with views similar to HTML DOM elements&#8217; and it looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@driver.find_elements(:tag_name, 'collectionCell')\n<\/pre>\n\n\n\n<p>Guess how to find tableCells? Right:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@driver.find_elements(:tag_name, 'tableCell')\n<\/pre>\n\n\n\n<p>To get all elements use<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@driver.find_elements(:tag_name, '*').map(&amp;:tag_name)\n# =&gt;\n\n<\/pre>\n\n\n\n<p>In the end, you will need only visible buttons<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@driver.find_elements(:tag_name, 'button').select(&amp;:displayed?).map(&amp;:text)\n<\/pre>\n\n\n\n<p>Looks good so far.<\/p>\n\n\n\n<p>To click on a button named &#8220;Done&#8221;, you can use:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">@driver.find_element(:name, 'Done').click\n<\/pre>\n\n\n\n<p>In the real world, however, there are too many buttons with custom images; so, in this case we have to use <i>accessibilityIdentifier<\/i>.<br>Set <i>accessibilityIdentifier<\/i> to &#8216;Done&#8217; in the code, and in the tests use<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">find_element(:name, 'Done')<\/pre>\n\n\n\n<p>More docs:<\/p>\n\n\n\n<div><a href=\"https:\/\/github.com\/appium\/appium\/wiki\">Github Wiki<\/a><\/div>\n\n\n\n<div><a href=\"https:\/\/github.com\/appium\/appium\/wiki\/Finding-and-interacting-with-elements\">Finding-and-interacting-with-elements<\/a><\/div>\n\n\n\n<p>Examples:<\/p>\n\n\n\n<div>examples\/ruby\/u_i_catalog.rb<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Tips and tricks<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Debugger<\/h3>\n\n\n\n<p>I use <i>byebug<\/i> for Ruby 2.0 as it allows me easily play with UI elements.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Networking<\/h2>\n\n\n\n<p>Finally, almost every real application communicates to remote server and this is also something that we want to test. So, as we test our app from outside, we mock webserver outside as well. To run server with mocked api, I use sinatra rb.<\/p>\n\n\n\n<p>Final flow.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#run appium\n#run sinatra mock\n#build app\n#run spec\n<\/pre>\n\n\n\n<p>I&#8217;ve personally found Appium very useful, especially taking into account that it doesn&#8217;t require any code inside the application.<br>On the other hand, it requires a lot of prep work to run tests. So, In order to make start with Appium easier, I&#8217;ve created a simple gem :<br><a href=\"https:\/\/github.com\/amishyn\/appium-rspec-bootstrap\">appium-rspec-bootstrap<\/a><\/p>\n\n\n\n<p>Hope you&#8217;ll find it handy too. Any comments and suggestions are very welcome.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I came from the RoR web development and &#8211; as we all know &#8211; Rails community loves tests. Personally, I am a fan of acceptance testing and using mostly capybara for it. So, when I shifted to the iOS development, it was essential for me to find some decent acceptance testing tools like Apple&#8217;s UI&#8230;<\/p>\n","protected":false},"author":27,"featured_media":9459,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[],"coauthors":["Alex Mishyn"],"class_list":["post-5328","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"aioseo_notices":[],"categories_data":[{"name":"Engineering","link":"https:\/\/railsware.com\/blog?category=development"}],"post_thumbnails":"https:\/\/railsware.com\/blog\/wp-content\/themes\/railsware\/vendors\/images\/article-thumbnail-default.jpg","amp_enabled":true,"_links":{"self":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/5328","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/users\/27"}],"replies":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/comments?post=5328"}],"version-history":[{"count":66,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/5328\/revisions"}],"predecessor-version":[{"id":14054,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/posts\/5328\/revisions\/14054"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media\/9459"}],"wp:attachment":[{"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/media?parent=5328"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/categories?post=5328"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/tags?post=5328"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/railsware.com\/blog\/wp-json\/wp\/v2\/coauthors?post=5328"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}