Posts Tagged ‘mobile app’
Functional Testing is system level , end-to-end testing of your app from a user's perspective. Automating the process of functional testing of your app offers several benefits – it saves time and effort, it's repeatable, simplifies regression testing, enables testing with large data sets and it can be tied into your Continuous Integration process. UI Automations is an automated functional test framework from Apple. Here, user interactions are driven by test scripts are written in JavaScript and executed using the Instruments Automation tool.
While there are several other automated functional test tools available including Calabash, KIF, Frank and Fone Monkey, UI Automations has the benefit that it is very simple to use, needs minimal or no changes to your existing app and since it's from Apple, it is (fairly) well supported and maintained.
I recently gave a talk on automated functional testing of iOS apps using UI Automations. You can download the presentation from this link. There is also a sample demo application with a corresponding set of UI Automation test scripts.
1 2 3 |
NSString *jsForTextSize = [[NSString alloc] initWithFormat:@"document.getElementsByTagName('body')[0].style. webkitTextSizeAdjust= '%d%%'", updatedFontSize*100/DEFAULTWEBVIEWFONTSIZE]; [self.myWebView stringByEvaluatingJavaScriptFromString:jsForTextSize]; |
In the JS above, DEFAULTWEBVIEWFONTSIZE refers to the default font size of the text content presented within the web view and updatedFontSize refers to the desired font size. So for example, if DEFAULTWEBVIEWFONTSIZE is 18 and updatedFontSize is 9, then updatedFontSize*100/DEFAULTWEBVIEWFONTSIZE evaluates to 50.
• Next step is to adjust the frame height of the web view so the scaled text content is visible. The simplest way to do this is to have the UIWebView as a subview of a scrollable view (UIScrollView or its subclass ). That way, you can adjust the web view frame height and correspondingly, the content size of the scroll view that encompasses it. Adjusting the web view height is a bit tricky as described below.
The sizeThatFits method on web view returns a size that best fits the content. The problem with this is that when you scale up, the method returns the updated size but if the web view is large enough to display the specified content, then scaling down will not update the frame size but instead, the current frame size is returned.
So first , reset the current frame height of the web view to a small value like 1.
1 2 3 |
CGRectadjustedFrame = self.myWebView.frame; adjustedFrame.size.height= 1; self.myWebView.frame= adjustedFrame; |
Now, obtain the frame size that would best fit the content. Since the current frame size is 1, we are scaling up. Update the frame size of the web view with the new frame size.
1 2 3 |
<span style="font-size: 14px;"><code> CGSizeframeSize = [self.myWebViewsizeThatFits:CGSizeZero]; adjustedFrame.size.height= frameSize.height; self.myWebView.frame= adjustedFrame;</code></span> |
Finally, update the content size of the UIScrollView containing the web view to accommodate the scaled content.
1 2 3 4 |
<span style="font-size: 14px;"> <code> CGSizescrollViewSize = self.myScrollView.contentSize; scrollViewSize.height= adjustedFrame.size.height+ self.myWebView.frame.origin.y; self.myScrollView.contentSize= scrollViewSize; </code> </span> |
You can download a sample project that scales the text content of web view from here. Shown below are some screenshots of the app.
Xcode and Zombie Processes
The Problem…
If you have been using Xcode (the latest version as of writing this post is Xcode 4.6.2 ) for an extended period of time, testing your app on the iOS simulator, you may eventually encounter a “Resource temporarily Unavailable” build error . There are no build errors associated with your source code but the system is unable to successfully build your app and launch the simulator to run it . You would observe something like this in your build output.
So what’s going on?
The reason this occurs is because every time you launch the iOS simulator through Xcode to run your app and then quit /stop running the app, Xcode leaves behind a Zombie process. If you are not familiar with Zombie processes in Unix, essentially, it is a process that has completed execution but whose entry remains in the process table. It is the responsibility of the parent process to eventually clear these processes. The zombies don’t use any of the computer resources so you won’t observe a depletion of resources , but the problem is that in this “undead” state, they hold on the PID or Process Identifier. The implication of this is that eventually, your system will run out of PIDs to assign to new processes, thereby resulting in a failure to spawn or launch a new process.
You can confirm this behavior by running your iOS app through Xcode a few times and then running the “ps” command on the terminal window. You will observe a bunch of zombie processes listed for your app. The “Z” in the “S” (or “STAT” ) column indicates that “symbolic state” of the process is a “Zombie“.
1 |
Priya-Mac-01:$ ps -aelf</code> <code>UID PID PPID F CPU PRI NI SZ RSS WCHAN S ADDR TTY TIME CMD STIME</code> <code>…….</code> <code> 501 928 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Fri11AM</code> <code> 501 1072 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Fri11AM</code> <code> 501 9473 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Fri05PM</code> <code> 501 11380 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon09AM</code> <code> 501 11599 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon09AM</code> <code> 501 11614 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 11758 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 12412 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 12564 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 13245 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 13407 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon11AM</code> <code> 501 13590 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 13725 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) 19Jun13</code> <code> 501 14545 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon12PM</code> <code> 501 14646 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon12PM</code> <code> 501 14761 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon12PM</code> <code> 501 14835 233 6000 0 0 0 0 0 - Z 0 ?? 0:00.00 (MyApp) Mon12PM</code> <code>-------- |
1 2 3 |
Priya-Mac-01:$ ps -aelf | grep "MyApp"|wc -l 272 |
In my case, there were 272 zombie processes associated with my app that Xcode didn’t reclaim. So in case of the Xcode, you will eventually notice that you are no longer able to build the app and launch the simulator to run it. In fact, you probably won’t be able to launch any new application. Yep- not a good place to be.
So what are your options?
Reboot:
The simplest and safest method is to reboot your system. This will get rid of the zombie processes
Re-initializing/Killing the Parent Process:
Generally , killing the parent process corresponding to the Zombie processes should take care of it but unfortunately, in the case of Xcode, the parent process is the system launchd process. The launchd is a core system process that handles the launching of many of the other processes. Issuing a “kill” command to the launchd process can result in undesirable results and can even make your system unresponsive. So DO NOT kill the launchd process. You could try to re-initialize the process using the kill with HUP (“Hang Up”) option but you are probably better off rebooting your Mac.
If you are curious, you can follow the steps below to determine the parent process of the Zombie Xcode process
1) You can identify the PID (“ppid”) of the parent process corresponding to the zombie process using the command
1 |
Priya-Mac-01:$ps -p <PID of MyApp Zombie Process> -O ppid |
This will output the ppid of the parent process corresponding to the Zombie process,
2) You can get details of the parent process using the following command
1 2 3 4 5 |
Priya-Mac-01:ps -p <PID of Parent Process> PID TTY TIME CMD 236 ?? 0:00.75 /sbin/launchd |
The output of the above command indicates that the launchd process is parent process.
You can find more details on Zombie processes at you can check out the details in http://en.wikipedia.org/wiki/Zombie_process.