How can I disable "All exceptions" in XCTestCase - ios

I usually have "All exceptions" ON in my Xcode Project.
This is one unit test in XCTestCase
- (void)testInitNotAllowed
{
XCTAssertThrowsSpecificNamed([[PON_GameStatistics alloc] init], NSException, #"Singleton");
XCTAssertNoThrowSpecificNamed([[PON_GameStatistics alloc] init], NSException, #"Singleton1");
}
First line is testing if exception is throw and I am expecting that it will be thrown.
So every time when I run this unit test, what mean every time when I run all unit test per project or per this file. Unit test stop because I have "All exceptions" ON.
So what I end up doing is following.
Set "All exceptions" OFF when running unit test and there setting it back ON when I am coding or doing manual test on simulator.
Question
Is there way to have "All exceptions" ON but somehow to tell Xcode not to stop on "All exceptions" ON inside this test case ?
This would save me lot of time.

Probably you can do that with conditional breakpoints.
Add a new breakpoint at the beginning of the snippet.
Introspect it and choose Debugger Command for Action.
Enter the debugger command:
breakpoint disable
Check Autmatically continue …
This will automatically turn breakpoints off. Of course you can turn them on after the snippet.

Related

XCTests canceling prematurely

I am running a few unit tests inside Xcode with XCTests. When I run them, all the tests either pass and fail and show the little green check or red cross. The main issue seems to be that my tests are prematurely canceling and they are not being run properly.
Here's some more information:
When the tests are run, there is no console output whatsoever which was not happening before. By that I mean I did have the expected console output before, now I don't.
When the tests are run, it does not require me to unlock my iPhone so that the app can run. Moreover, even if my iPhone is unlocked, it doesn't run the application which it would do before.
When running my tests, it finishes compiling and then very quickly says "Canceling..." in the information bar in Xcode (the top and centered bar that shows warnings and "Building " when you build your project).
I am using the .xcworkspace file (becasue I am using Pods)
I have one build scheme which is the project.
I had these same issues plus the issues of the green checks and red crosses not showing up on my tests after they ran and the sometimes my tests not showing up at all in the testing tab. I fixed these issues by deleting the Podfile.lock file, Pods directory, and the .xcworkspace directory and then running Pod install. After doing this, I had the same issues, except those two issues.
I tried running new tests on a different branch, same issues.
Before running into any of these issues, I was just writing tests and trying different methods of writing tests. I've reverted all those changes and I still get these errors.
I have also found the same issues when running the tests no the simulator.
When I compile and run the app from Xcode, it runs fine.
Any advice on how to solve this would be great! Please ask for more details if needed.
Here's a video of me running my tests. I set up a new project and new unit test target to show what's going on. Note: There's an empty test in there and a test that should always pass:
As you can see, the issue is the tests are not running properly. The green and red crosses are not showing up anymore, the test that's supposed to always pass is failing, there is no console output, and in the top information bar it's saying "canceling..." almost immediately. Any advice on why this canceling is happening would be great!
Here are some screenshots of how the code is set up:
Here's the code as well (it's just the basic code after creating a new unit test, except I added in one assert that should always pass):
import XCTest
#testable import example
class exampleTests: XCTestCase {
override func setUp() {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
XCTAssertTrue(true)
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}
Edit:
So, as per #CPR's suggestion, I tried it again on the simulator and the errors were basically all gone. I tried it again on the physical device, but the errors persisted. Note: I had tried it before on the simulator and got the same errors. I didn't change anything since then so I am unsure of why it worked now. Here's the console output from running the tests on the sim (not sure if that will help, but I'll add it anyway):
Test Suite 'All tests' started at 2018-12-06 03:59:53.045
Test Suite 'exampleTests.xctest' started at 2018-12-06 03:59:53.046
Test Suite 'exampleTests' started at 2018-12-06 03:59:53.046
Test Case '-[exampleTests.exampleTests testExample]' started.
Test Case '-[exampleTests.exampleTests testExample]' passed (0.001 seconds).
Test Case '-[exampleTests.exampleTests testPerformanceExample]' started.
/Users/akashkundu/Documents/example/exampleTests/exampleTests.swift:30: Test Case '-[exampleTests.exampleTests testPerformanceExample]' measured [Time, seconds] average: 0.000, relative standard deviation: 115.251%, values: [0.000004, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100
Test Case '-[exampleTests.exampleTests testPerformanceExample]' passed (0.348 seconds).
Test Suite 'exampleTests' passed at 2018-12-06 03:59:53.396.
Executed 2 tests, with 0 failures (0 unexpected) in 0.348 (0.350) seconds
Test Suite 'exampleTests.xctest' passed at 2018-12-06 03:59:53.396.
Executed 2 tests, with 0 failures (0 unexpected) in 0.348 (0.350) seconds
Test Suite 'All tests' passed at 2018-12-06 03:59:53.397.
Executed 2 tests, with 0 failures (0 unexpected) in 0.348 (0.351) seconds
Can anyone shed some light on why running the tests on the physical device causes these errors?
Edit:
Here's the error/log message from the "Messages" tab in Xcode found by #CPR:
Here's the error/log code in text:
example.app encountered an error (Failed to establish communication with the test runner. (Underlying error: Unable to connect to test manager on 8b441d96d063b3b6abf55b06115441d160e85e67. (Underlying error: kAMDMuxConnectError: Could not connect to the device.)))
-----------------------------------------------------------------------
Solution:
Thanks to #CPR, the solution is to simply restart the device. Another lesson learned is to use the "Messages" tab to see logs and errors which is the right most tab next to the "Breakpoint" tab.
His full answer here.
Problem resolved in comments. For future readers, here are some good things to check if you encounter similar issues:
Check Xcode messages tab to look for build errors.
Restart device/simulator as appropriate. This fixed the problem in this case.
Uninstall/reinstall app on device/simulator.
Are certs/provisioning profiles valid? Try generating new ones and re-running.
Does it work on the simulator? If yes, this is likely an issue with the device itself.
Are breakpoints hit when you run the code? If yes, then this is a test failure. If no, the problem is happening before the tests are even run (as was the case here).

XCode not stopping on breakpoint in method called from LLDB

XCode 7.2.1
iPad Retina iOS 9.2 Simulator
I have several breakpoints set in a particular class in an XCode project.
Everything I discuss below takes place in this one class file.
I set the breakpoints on -(int16_t)areaNbr by clicking in the gutter, and set no conditions or anything on them. I confirmed they existed as far as LLDB is concerned by running breakpoint list from the LLDB prompt.
The project scheme is set to build for debugging, not release.
I run the project in the simulator, and stop at a breakpoint in a different method than the one in question, at which time I want to go to the LLDB prompt and call po [self areaNbr] and step through areaNbr.
Please note, as this may be quite relevant, I have NO code in the project itself that calls
-(int16_t)areaNbr
Now, I CAN get this to stop at my breakpoints on -(int16_t)areaNbr if I add some code to the project that calls the method.
For example, if I add something like NSLog(#"... %d", [self areaNbr])
I know the issue has nothing to do with compiling away the method simply because nothing calls it, because if that were true, then my call to po [self areaNbr] wouldn't be spitting out the result to the debugger window as pictured below. So the method is being compiled, and certainly recognized as existing by the debugger for execution purposes... just not for stepping purposes.
FYI, [self area] is returning "Area01"
Calling breakpoint list in LLDB returns the following
By default, lldb does not stop at breakpoints in hand-called code. The majority of folks use expr & expr -O -- i.e. po to print values & objects and were annoyed if they stopped at breakpoints they had set for other purposes.
However, it is easy to control this behavior, just use:
(lldb) expr -i 0 -- [self areaNbr]
Then you will stop at your breakpoint.
In this example, I left out the -O which is the object printing part, since if you just want to call this method, you likely don't care about calling description on the result after the expression is evaluated.
You can see all the options for expression evaluation by doing:
(lldb) help expr

how to stop Xcode iOS unit tests if a fatalerror is hit?

How can I stop Xcode iOS unit tests if a fatalerror is hit?
That is in case I have 10 unit tests, but it happens that the code it calls for unit test number 5 has a coding problem (** coding issue in this case is in the test case and setup code **) and is throwing a fatalError. So in this case the unit testing stops there and does not continue to other test cases in that test class.
(not sure if this is the intended operational / process for good unit testing or not? )
Try
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
continueAfterFailure = false
}
A related problem I had was stopping the unit test with a breakpoint when it fails, so that I can see the issue, without having to click or scroll through tons of test output.
Making a unit test failure breakpoint is simple, but wasn't easy to find.
Xcode 8+ there is a new breakpoint that you can add called a "Test Failure Breakpoint".
Click on Breakpoints (Left Panel ... Command + 7)
Click on + (Bottom left corner)
Click on "Test Failure Breakpoint"
References
Debugging Tests with Xcode
There is no easy fix for this. In case of an uncaught (objc) exception or a failed assert the process that runs the unit tests did receive either a mach exception or a unix signal.
Matt Gallagher has a nice solution for this, which he presents in this blog post.
It is good practice to write safe code everywhere, including your unit tests.
Regarding your problem, as Oleg Danu replied, you should set continueAfterFailure = false.
The next step is to add following before your test can crash.
var optionalVariable: Int?
XCTAssertNotNil(optionalVariable)
I recommend to add it into setUp()
In this way your test will stop before crashing Xcode, and you don't need to set any breakpoints.

Breakpoint Debug proper usage iOS?

I put breakpoint. I used command ⌥⌘-click on breakpoint.
It showed me following options.
How can I use these options.
1. AppleScript
2. Capture GPU Frame
3. Debugger Command
4. Log Message
5. Shell Command
6. Sound
There are other options
1. Condition
2. Ignore
3. Action
4. Options
What are these options. How are they working?
You can read this detailed tutorial on breakpoints options: https://www.bignerdranch.com/blog/xcode-breakpoint-wizardry/
Short summary:
Condition: if condition evaluated to true, breakpoint is triggered.
Ignore is self explaining. Like "ignore first 2 passes".
Action: what to do if breakpoint is triggered.
Options: set if you do not want to stop on this breakpoint in XCode
For action field you can choose what to do when breakpoint is triggered. Possible values is:
AppleScript: execute entered AppleScript code
Capture GPU frame: capture OpenGL frame contents
Debugger Command: execute entered GDB command
Log Message: log entered message to console
Shell Command: execute entered shell command
Sound: play a sound file
These options may be used to perform additional actions once the debugger hits this breakpoint.
The "Log Message", for example, can be very useful as it lets you print automatically collected data like the hit count for this breakpoint, the name of the method it's in, values of variables and other expressions.
Using the same principal, you can have the debugger run an Apple script, execute shell commands, etc.
You can also check the "Automatically continue after evaluating actions" so the debugger won't actually break while hitting it - but the action will still be executed.
There are even more advanced options you can utilize like performing the action only when a certain condition is met, ignore the breakpoint unless it has a certain minimum of hits, and even chaining several operations (+ and - buttons).

How to know which line is causing exception?

I am new to XCode and Objective C. I have intentionally make a mistake to assign number to NSString*.
NSString* s = #1;
[s uppercaseString];
Though XCode gives me warning, this code will compile. But at runtime I get exception. Now I see in logs, (Sorry for image, I was not able to paste is as text properly due to formatting)
In this log, how I find exact place of error. How this log tells me which code to change.
So it looks like you are running the Release build (debug symbols stripped) and if you got that crash log in a production environment you would need to symbolicate it in order to find the line.
This Apple TN gives some details of Symbolication.
In a development environment you would simply add an exception breakpoint and run it from Xcode, as the debug symbols would not be stripped.
To understand what line causes the problem, you usually need to add exception breakpoint to your project as explained in this document;
In the bottom-left corner of the breakpoints navigator, click the
Add button.
Choose Add Exception Breakpoint.
In the Exception pop-up menu, choose the type of exception on which
you want execution to stop:
All. Stops on all exceptions.
Objective-C. Stops on Objective-C exceptions.
C++. Stops on C++ exceptions. To stop on a particular C++ exception, specify the exception name.
Choose the phase of the exception handling process at which you want program execution to stop.
Click Done.
line 5 Sam : [BIDViewController viewDidLoad] + 143 , if this is a release build , you need to resolve with symbols the memory address of the function , this is called "symbolize" the crash dump...
In the log look for your project name and you will come to know.
e.g.
line 5 Sam : [BIDViewController viewDidLoad] + 143
If you want to produce real crash without warning, try following code it will produce index out of bound exception and will crash
NSArray *array = #[#"1",#"2"];
NSLog(#"Item not accessible->%#",(NSString*)array[2]);
set Exception breaking point or enable NSZombie object
or
NSZombie
From the menu bar, choose Project > Scheme > Edit Scheme

Resources