I'm trying to set the language and the region of my UI Testing target, and unfortunately it doesn't seem to work.
I've tried both ways, first:
Product | Scheme | Edit Scheme
Run | Options
Application Language: French
Application Region: France
Test | Arguments
Use the Run action's arguments and environment variables: Checked
And I try this other way:
Product | Scheme | Edit Scheme
Test | Arguments
Use the Run action's arguments and environment variables: Unchecked
Arguments passed at launch:
-AppleLanguages (French)
-AppleLocale fr_FR
Each way resulting in the UI Testing still happening in English. Moreover, when I hit the record button, it runs in French...
So if I do something wrong, I would be happy to know!
Thanks in advance!
I have figured it out. I set the locale settings in the launchArguments for testing temporary in Xcode.
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
app = XCUIApplication()
app.launchArguments = [
"-inUITest",
"-AppleLanguages",
"(de)",
"-AppleLocale",
"de_DE"
]
For CI I use fastlane from Felix Krause and get localized screenshots with snapshot.
Try changing the specs on the simulator. It worked for me every time.
On Simulator:
Settings > General > Language & Region > iPhone Language --> change here
Related
Objective
Running simple unit-test for an iOS app.
Setup
Xcode (Version 14.1)
Sample Test:
import XCTest
#testable import SDKTestAppSwift
class SDKTestAppSwiftTests: XCTestCase {
func testExample() throws {
print("Test: testExample")
// This is an example of a functional test case.
let base = "asdfghjkl123"
XCTAssert(base == "asdfghjkl123")
}
}
Next to the ..
func testExample() throws {
.. Xcode provides a nice little 'start single test'-button.
I used to klick it to start the test, locally (Xcode IDE on mac).
This used to work properly.
Problem
Klicking the 'start single test'-button, an overlay appears:
For the sake of this question to be machine-readable:
There is no scheme and/or test plan that contains every test you are trying to run.
Create a new scheme and/or test plan containing the tests you want to run.
To close the overlay an 'OK'-Button is delivered only.
Misleading solution (?!)
Just before there was no such scheme needed.
I wonder why would that changes 'suddenly'.
From my point ov view Scheme/Testplans are executed 'on startup' of the device-emulator (or likewise), which is not my objective in the first place.
However - creating a TestPlan via:
File > New > File... > TestPlan
Adding the SDKTestAppSwiftTests-class using the +-Button.
... no success ... :-/
Several other attempts
It seems my system is not the only one facing likewise issues.
Problems with naming of test plans
xcodebuild: Tests cannot be run because the test plan “Scheme” could not be read
No matter if there is a 'test-plan' and whatever name I assigned it - this is no solution.
Default test plan
https://developer.apple.com/forums/thread/133495
I seriously do not know how to create a 'default test plan' if it was not the way decribed before.
Quit Xcode and delete 'old configurations'
Xcode: No Scheme
xcodebuild says does not contain scheme
Something about files with old configurations which have to be deleted
In this case I am not sure which file and where to find it exactly.
Conclusion
Even though one of the obove may help you, for me the issue is not solved, yet.
Anyways
Thanks for reading & sharing - any help is appreciated :)
For me I fixed this through my scheme → Edit Scheme → Test → Plus Sign (Add Test Target) and then adding my unit test target.
There is another solution ...
First - Manage Schemes
Second - Create new Scheme
Third -> Celebrate, it's done .. :)
I need to do the pre-test config, one time setup before I run XCUITest (automation test) cases,
Example of pre-test setup: (This needs to be done once for test cycle, the output of below APIs is used in all test cases)
Fetching qTest access token
Fetching the qTest URLs from remote config file.
From docs I found that testBundleWillStart method of XCTestObservation protocol is ideal place to do pre-test setup.
But
-testBundleWillStart method is not getting called or executed,
all below listed methods of XCTestObservation are getting executed correctly.
testSuiteWillStart
testCaseWillStart
testCaseDidFinish
testSuiteDidFinish
I tried setting Principal Class in UITest info.plist but no luck, it shows following error
Test bundle Info.plist at /var/containers/Bundle/Application/BEAFB0C2-43D5-4C90-B50F-B1FF1A16BC23/MyAppUITests-Runner.app/PlugIns/MyAppUITests.xctest/Info.plist specified MyAppUItests.TestObserver for NSPrincipalClass, but no class matching that name was found.
How can I get the method testBundleWillStart executed?
Any help would be appreciated.
Found the issue,
My project name had a space, so replacing the space with _ worked.
Info about my project:
My project name: My App
My project test bundle name: My-AppUITests
Working Solution: (Replacing space with _ character)
<key>NSPrincipalClass</key>
<string>My_AppUITests.SOTestObserver</string>
Let me also share the things that seem right but still don't work:
Non-working #1: (Replacing space with - character)
<key>NSPrincipalClass</key>
<string>My-AppUITests.SOTestObserver</string> //Didn't work
Non-working #2: (Replacing project name with $(PRODUCT_NAME) environment variable)
<key>NSPrincipalClass</key>
<string>$(PRODUCT_NAME).SOTestObserver</string> //Didn't work
I have created UITesting like this. I need to run those 3 file in sequence and I need to name like this. I think it is quite bad. I want to name more logically (instead of Test1,etc). Is it possible to rename and run in sequence?
Another one is I need to name my method alphabetically. I want to name randomly and run in sequence. How shall I do?
- (void)test2CreatePost
- (void)test3ClickLikeInNewsfeed
Functions nesting is fine for running UI tests from XCode instantly only. But when tests are running from command line, they are running by the alphabetic sequence. I've read that this issue was fixed for unit tests in XCode 8, but it seems not for UI tests.
For instance, now I have the following UI tests hierarchy:
UITests
TestCaseB
TestCaseA
When I run them from XCode 8.2.1 they are executed in the same sequence as they are described, i.e.:
TestCaseB
TestCaseA
But when I run them from command line using xcodebuild test TEST_TARGET_NAME=<TargetName> -scheme <UITestsSchemeName> destination 'platform=iOS Simulator,name=iPhone 7' they are running in another sequence:
TestCaseA
TestCaseB
Be careful.
You could achieve this by nesting your functions.
// Note that this function contains tests but does not follow the 'testXXX' naming convention
func login() {
// Implement your test here
}
func newsfeed() {
// Implement your test here
}
func moreTab() {
// Implement your test here
}
// Here is the test method that will run the tests in a user-specified order
func testSomething() {
login()
newsfeed()
moreTab()
}
You can use the procedure explained in this answer to achieve this.
Running individual XCTest (UI, Unit) test cases for iOS apps from the command line
Basically you need to override testInvocations present in XCTestCase, then you have control over the order of test case execution.
If you need more information on how to achieve this add a comment.
I have a Swift SpriteKit project with about 25 smallish files. The time to compile this project is 30-45 seconds! It's pure Swift with no ObjC.
I've watched the compile in the Report Navigator to try to find a single file that's taking the time. But, it's not really a single file. It's always the last file in the list that seems to take all the time. But that file can be different between compiles and still takes all the time.
The step right after the last file is Merge xxx.swiftmodule, which happens quickly, but I'm not sure if because it comes right after the slowness it might be related.
I've searched and tried various approaches to find the culprit. I read this post: Why is Swift compile time so slow? and tried those approaches. I've done a command line build using CTRL-\, but that does not show any useful information about the slowness.
I've gone through my project looking for places where type inference might be getting tripped up, but haven't found much (and really, if that was the case, I'd expect a single file to be the culprit).
Does anyone have any other suggestions for tracking this down? Coming from an Objective-C project that compiles nearly instantly, this is driving me crazy.
EDIT
I worked on this a bit more and am including a screen shot of the build output, noting where the slowness happens. The thing is, if I comment out the code in the slow file, then the file before it in the list becomes the slow one (where it was fine before). If I comment that code out, then the one before that becomes the slow one, etc.
After more digging and debugging, I found the problem. It turns out it actually is type inference, as other posts have suggested. Part of the problem is that I did not notice that the build output in the Report Navigator shows an arrow for files still compiling and a checkmark for those that are done (my color blindness played a role). So I thought they were all finished compiling when one was not.
In any case, I read the article here: GM release of Xcode 6 compile and did a command line build of the entire project, which showed me the file that was the issue. Then, using the CTRL-\ approach noted above, I found the culprit.
It turns out that this line was the issue:
ourWindowCopy.position = CGPoint(x: ((26.5 + theXOffset) * self.multiplierWidth) + (4.0 * CGFloat(randomRow) * 2.0 * self.multiplierWidth), y: ((41.0 + theYOffset) * self.multiplierHeight) + (5.75 * CGFloat(randomColumn) * 2.0 * self.multiplierHeight))
I know it seems a mess - I was playing around with a bunch of different options early on and hadn't yet gone back to simplify. I replaced it with this (and will of course replace the literals as well as simply further):
let floatRandomRow = CGFloat(randomRow)
let floatRandomCol = CGFloat(randomColumn)
let pointX: CGFloat = ((26.5 + theXOffset) * self.multiplierWidth) + (4.0 * floatRandomRow * 2.0 * self.multiplierWidth)
let pointY: CGFloat = ((41.0 + theYOffset) * self.multiplierHeight) + (5.75 * floatRandomCol * 2.0 * self.multiplierHeight)
ourWindowCopy.position = CGPoint(x: pointX, y: pointY)
Now the compile speed is very fast!
I'm not sure there's really any new information here, but wanted to close this out with a solution in case someone runs across it.
There is a hidden option in Swift compiler that prints out the exact time intervals that compiler takes to compile every single function: -Xfrontend -debug-time-function-bodies.
Simple run the following in terminal and analyze results:
xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt
Awesome Brian Irace wrote brilliant article about it Profiling your Swift compilation times.
Building on other answers, the following commands are helpful...
To see a sorted list of functions by build time:
xcodebuild -workspace [Your Workspace Name].xcworkspace -scheme [Your Build Scheme Name] clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep .[0-9]ms | grep -v ^0.[0-9]ms | sort -nr > culprits.txt
To see a sorted list of functions that take over 1s to build:
xcodebuild -workspace [Your Workspace Name].xcworkspace -scheme [Your Build Scheme Name] clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt
You can get a list of scheme names like so (this command runs a clean first):
xcodebuild -workspace [Your Workspace Name].xcworkspace -list
Helpful Articles about why your build times may be long:
https://medium.com/#RobertGummesson/regarding-swift-build-time-optimizations-fc92cdd91e31
https://medium.com/swift-programming/swift-build-time-optimizations-part-2-37b0a7514cbe
https://medium.com/compileswift/swift-build-time-reanalysis-optimisations-a875a4168f7a
Swift time compilation
Swift Compiler Performance
Measure and Tools
You should clean and build your project to have a better results for comparing.
Xcode Build time output.
//Terminal command
defaults write com.apple.dt.Xcode ShowBuildOperationDuration YES
Output:
Build With Timing Summary.
//Xcode
Product -> Perform Action -> Build With Timing Summary
Output:
Report Navigator -> <build> -> Recent
Type check warnings
Trigger a warning in Xcode for any function/expressions which is more than a user-defined limit to type-check
Build Settings -> Other Swift Flags(OTHER_SWIFT_FLAGS)
-Xfrontend -warn-long-function-bodies=200
-Xfrontend -warn-long-expression-type-checking=200
Output:
Instance method 'foo()' took 200ms to type-check (limit: 200ms)
Record a time which is taken to compile every function/expression
Build Settings -> Other Swift Flags(OTHER_SWIFT_FLAGS)
-Xfrontend -debug-time-function-bodies
-Xfrontend -debug-time-expression-type-checking
Output:
Report Navigator -> <build> -> Expand All Transcripts
-Xfrontend -debug-time-function-bodies
-Xfrontend -debug-time-expression-type-checking
BuildTimeAnalyzer-for-Xcode is based on this flag. Also it has interesting column which is called Occurrences - how many times compiler is type checking it(e.g. lazy properties, closures)
XCLogParser analize logs
xclogparser parse --project Experiments2 --reporter html --rootOutput "/Users/User/Desktop/temp"
You are able to open Xcodelog with .xcactivitylog extension by changing to .zip and unzip it. After it you can open it as a text file
/Users/User/Library/Developer/Xcode/DerivedData/Experiments2-fejelsaznlrfewdtvyfyhhbgxlwl/Logs/Build/00D3B76E-B61B-4FB8-AE0B-1FAD5AF3F452.xcactivitylog
XCMetrics(by Spotify) as a next step of collecting log data
Notes:
-debug-time-compilation was removed
Experiments were made on Xcode v13.3.1. Do not forget to clean project before measure
You are able to set flag for specyfic target(e.g. in modularized project)
This script (source code) can be perfectly executed in the production mode.
void main() {
int greeting = "Hello world!";
print(greeting);
}
This is a traditional hello world example that works fine in Dart.
The result is "Hello world!".
This script is self enough because not required other functionality and it works as expected.
Now I have small questions:
Can I consider that this script is valid and correct source code in Dart language becuase it works as expected?
If this script is valid source code in Dart language then why it cannot be executed in non-production mode?
If some code that can be perfectly executed in the production mode but cannot be executed in other mode then which mode in Dart more correct (production mode or other mode)?
P.S.
As a programmer, I am interesting not in theory and practice but I have interest only in answers in my small questions based on real example (even if it are very small).
If my questions are not so correct then I would like to know why?
Because they are directly related to programming in Dart language.
It is valid because types are ignored in production mode.
In checked mode (intended for development only) types are checked and you get an exception.
Types in Dart are not for runtime but for development time to make tools able to reason about the code and show possible bugs.
This means it doesn't matter if you type String or var. You cannot omit it completely because this violates the syntax.
It can be executed in production mode
# ~/dart/playground/bin/dart_valid
$ dart main.dart
Hello world!
It fails in checked mode (development mode)
# ~/dart/playground/bin/dart_valid
$ dart -c main.dart
Unhandled exception:
type 'String' is not a subtype of type 'int' of 'greeting'.
#0 main (file:///home/zoechi/source/my/dart/playground/bin/dart_valid/main.dart:2:18)
#1 _startIsolate.isolateStartHandler (dart:isolate-patch/isolate_patch.dart:216)
#2 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:115)
pub build fails because it uses the analyzer which utilizes type annotations like in checked mode and throws.