XCTestCase - how to assert on a NSTextView containing String? - swift

I have a macOS project that I'm creating UI tests for.
While it's relatively easy to find staticText, buttons, etc. by their text value. Using a subscript lookup on .textViews doesn't (seem to) work.
I've managed to get a reference to the NSTextView I want to inspect using .textViews.firstMatch but I can't figure out how to assert on it's string value.
I'm looking for something that works like this.
XCTAssertEqual(prefs.textViews.firstMatch.stringValue, "Enter text below")

Simply value should do.
It's available on XCUIElementAttributes and is of type Any? that varies based on the type of the element.
XCTAssertEqual(prefs.textViews.firstMatch.value as! String,
"Enter text below")
Ref:
https://developer.apple.com/documentation/xctest/xcuielementattributes

If you print out the debugDescription of the element, you should see which parameter holds the value you want to assert equality on. Likely it will be .value which you can simply coerce into a String for your purposes. Strings adhere to == equality checks, making it trivial to compare two strings with just a simple XCTAssert(originalTextViewValue == "String I want to value check against")

Related

swift argument labels and keywords

I am trying to learn Swift and came across the argument labels and an online example as follows:
func setAge(for person: String, to value: Int) {
print("\(person) is now \(value)")
}
This can be then called as:
setAge(for: "Paul", to: 40)
My question is that isn't for a Swift keyword? I am wondering whether this use of for has some hidden meaning that I am missing or just that these keywords can also be used as argument labels?
or just that these keywords can also be used as argument labels?
Exactly. This is introduced in SE-0001 Allow (most) keywords as argument labels. The motivation is that:
Sometimes, the most natural label for an argument coincides with a language keyword, such as in, repeat, or defer. Such keywords should be allowed as argument labels, allowing better expression of these interfaces.
Though in SE-0001 it is said that inout, var and let are not allowed to be argument labels (back then they are used to describe the mutability of the parameter). This restriction was later relaxed. Now, only inout is not allowed as an argument label, and you get a warning if you use var or let as an argument label.
Yes this keyword can also be used as argument label.
Swift gives you flexibility to use any keyword except inout as argument label as it increases readability.

SwiftUi - How to concatenate a String value to an Integer in SwiftUi

I have a json with key and value as
"average_cost_for_two": 20
When I want to show this in UI, I was show as Avg Cost for two: 20
However I cannot convert the value to String to append "Avg Cost for two" since the value in the Json is an Int.
Basically I want to do append to the published var like this
for i in fetch.nearby_restaurants{
DispatchQueue.main.async {
self.datas.append(datatype(id: i.restaurant.id, name: i.restaurant.name, image: i.restaurant.thumb, rating: "Rating: " + i.restaurant.user_rating.aggregate_rating, cost_for_two: "I want to add my string to show in View here " + i.restaurant.average_cost_for_two, webUrl: i.restaurant.url))
}
}
nearby_restaurants has key as "average_cost_for_two": Int
Any help would be greatly appreciated. Thanks!!
The question is not related to SwiftUI at all.
Basically there are two ways:
Type Conversion: String(i.restaurant.average_cost_for_two)
cost_for_two: "I want to add my string to show in View here " + String(i.restaurant.average_cost_for_two)
String Interpolaction: "\(i.restaurant.average_cost_for_two)"
cost_for_two: "I want to add my string to show in View here \(i.restaurant.average_cost_for_two)"
For more information about String Interpolation please read the Language Guide
EDIT: looking at Swift questions elsewhere, this may not be the best approach, from what I found there's a built in method toString allowing for casting to string. (source: https://stackoverflow.com/a/28203312/2932298) it also seems to vary between versions. Some reference a description property after the int: let x = 10.description, although this is getting language-specific.
Coming from someone who has NO experience with Swift, I'm unsure if I'm able to correctly answer this question or not.
However, as a basic principle most (if not all) languages support int -> string conversion, most data types can be converted to a String very simply.
An idea would be something like: String(average_cost_for_two), converting the int value into a String allowing you to concatenate the values.
I believe the technical term would be type casting a most languages have support for this. Again, especially with X -> string conversions.
Again, no Swift experience, just basic programming principles from the different languages I've developed in.

Why are null checks bad / why would I want an optional to succeed if it's null?

I've read more than a few answers to similar questions as well as a few tutorials, but none address my main confusion. I'm a native Java coder, but I've programmed in Swift as well.
Why would I ever want to use optionals instead of nulls?
I've read that it's so there are less null checks and errors, but these are necessary or easily avoided with clean programming.
I've also read it's so all references succeed (https://softwareengineering.stackexchange.com/a/309137/227611 and val length = text?.length). But I'd argue this is a bad thing or a misnomer. If I call the length function, I expect it to contain a length. If it doesn't, the code should deal with it right there, not continue on.
What am I missing?
Optionals provide clarity of type. An Int stores an actual value - always, whereas an Optional Int (i.e. Int?) stores either the value of an Int or a nil. This explicit "dual" type, so to speak, allows you to craft a simple function that can clearly declare what it will accept and return. If your function is to simply accept an actual Int and return an actual Int, then great.
func foo(x: Int) -> Int
But if your function wants to allow the return value to be nil, and the parameter to be nil, it must do so by explicitly making them optional:
func foo(x: Int?) -> Int?
In other languages such as Objective-C, objects can always be nil instead. Pointers in C++ can be nil, too. And so any object you receive in Obj-C or any pointer you receive in C++ ought to be checked for nil, just in case it's not what your code was expecting (a real object or pointer).
In Swift, the point is that you can declare object types that are non-optional, and thus whatever code you hand those objects to don't need to do any checks. They can just safely just use those objects and know they are non-null. That's part of the power of Swift optionals. And if you receive an optional, you must explicitly unpack it to its value when you need to access its value. Those who code in Swift try to always make their functions and properties non-optional whenever they can, unless they truly have a reason for making them optional.
The other beautiful thing about Swift optionals is all the built-in language constructs for dealing with optionals to make the code faster to write, cleaner to read, more compact... taking a lot of the hassle out of having to check and unpack an optional and the equivalent of that you'd have to do in other languages.
The nil-coalescing operator (??) is a great example, as are if-let and guard and many others.
In summary, optionals encourage and enforce more explicit type-checking in your code - type-checking that's done by by the compiler rather than at runtime. Sure you can write "clean" code in any language, but it's just a lot simpler and more automatic to do so in Swift, thanks in big part to its optionals (and its non-optionals too!).
Avoids error at compile time. So that you don't pass unintentionally nulls.
In Java, any variable can be null. So it becomes a ritual to check for null before using it. While in swift, only optional can be null. So you have to check only optional for a possible null value.
You don't always have to check an optional. You can work equally well on optionals without unwrapping them. Sending a method to optional with null value does not break the code.
There can be more but those are the ones that help a lot.
TL/DR: The null checks that you say can be avoided with clean programming can also be avoided in a much more rigorous way by the compiler. And the null checks that you say are necessary can be enforced in a much more rigorous way by the compiler. Optionals are the type construct that make that possible.
var length = text?.length
This is actually a good example of one way that optionals are useful. If text doesn't have a value, then it can't have a length either. In Objective-C, if text is nil, then any message you send it does nothing and returns 0. That fact was sometimes useful and it made it possible to skip a lot of nil checking, but it could also lead to subtle errors.
On the other hand, many other languages point out the fact that you've sent a message to a nil pointer by helpfully crashing immediately when that code executes. That makes it a little easier to pinpoint the problem during development, but run time errors aren't so great when they happen to users.
Swift takes a different approach: if text doesn't point to something that has a length, then there is no length. An optional isn't a pointer, it's a kind of type that either has a value or doesn't have a value. You might assume that the variable length is an Int, but it's actually an Int?, which is a completely different type.
If I call the length function, I expect it to contain a length. If it doesn't, the code should deal with it right there, not continue on.
If text is nil then there is no object to send the length message to, so length never even gets called and the result is nil. Sometimes that's fine — it makes sense that if there's no text, there can't be a length either. You may not care about that — if you were preparing to draw the characters in text, then the fact that there's no length won't bother you because there's nothing to draw anyway. The optional status of both text and length forces you to deal with the fact that those variables don't have values at the point where you need the values.
Let's look at a slightly more concrete version:
var text : String? = "foo"
var length : Int? = text?.count
Here, text has a value, so length also gets a value, but length is still an optional, so at some point in the future you'll have to check that a value exists before you use it.
var text : String? = nil
var length : Int? = text?.count
In the example above, text is nil, so length also gets nil. Again, you have to deal with the fact that both text and length might not have values before you try to use those values.
var text : String? = "foo"
var length : Int = text.count
Guess what happens here? The compiler says Oh no you don't! because text is an optional, which means that any value you get from it must also be optional. But the code specifies length as a non-optional Int. Having the compiler point out this mistake at compile time is so much nicer than having a user point it out much later.
var text : String? = "foo"
var length : Int = text!.count
Here, the ! tells the compiler that you think you know what you're doing. After all, you just assigned an actual value to text, so it's pretty safe to assume that text is not nil. You might write code like this because you want to allow for the fact that text might later become nil. Don't force-unwrap optionals if you don't know for certain, because...
var text : String? = nil
var length : Int = text!.count
...if text is nil, then you've betrayed the compiler's trust, and you deserve the run time error that you (and your users) get:
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
Now, if text is not optional, then life is pretty simple:
var text : String = "foo"
var length : Int = text.count
In this case, you know that text and length are both safe to use without any checking because they cannot possibly be nil. You don't have to be careful to be "clean" -- you literally can't assign anything that's not a valid String to text, and every String has a count, so length will get a value.
Why would I ever want to use optionals instead of nulls?
Back in the old days of Objective-C, we used to manage memory manually. There was a small number of simple rules, and if you followed the rules rigorously, then Objective-C's retain counting system worked very well. But even the best of us would occasionally slip up, and sometimes complex situations arose in which it was hard to know exactly what to do. A huge portion of Objective-C questions on StackOverflow and other forums related to the memory management rules. Then Apple introduced ARC (automatic retain counting), in which the compiler took over responsibility for retaining and releasing objects, and memory management became much simpler. I'll bet fewer than 1% of Objective-C and Swift questions here on SO relate to memory management now.
Optionals are like that: they shift responsibility for keeping track of whether a variable has, doesn't have, or can't possibly not have a value from the programmer to the compiler.

difference between var someVar:[String] = [] and var someVar =[String]() [duplicate]

Is there any difference between the following?
var array1_OfStrings = [String]()
var array2_OfStrings: [String] = []
var array3_OfStrings: [String]
Testing in Playground shows that 1 and 2 are the same but 3 behaves differently.
Can someone explain me the difference please? And also what will be the preferred way to declare an empty array of String?
First two have the same effect.
declare a variable array1_OfStrings, let it choose the type itself. When it sees [String](), it smartly knows that's type array of string.
You set the variable array2_OfStrings as type array of string, then you say it's empty by []
This is different because you just tell you want array3_OfStrings to be type array of string, but not given it an initial value.
I think the first one is recommended as The Swift Programming Language uses it more often.
While I might be late to the party, there is one thing that needs to be said.
First option set array1_OfStrings to array of Strings
The other option tells that array1_OfStrings is array of Strings and then set it empty.
While this might be a really small difference, you will notice it while compiling. For the first option compiler will automatically try to find out what is the type of array1_OfStrings. Second option won't do that, you will let compiler know that this actually is array of Strings and done deal.
Why is this important? Take a look at the following link:
https://thatthinginswift.com/debug-long-compile-times-swift/
As you can see, if you don't declare type of your variable that might impact build performance A LOT.

string option to string conversion

How do I convert the string option data type to string in Ocaml?
let function1 data =
match data with
None -> ""
| Some str -> str
Is my implementation error free? Here 'data' has a value of type string option.
To answer your question, yes.
For this simple function, you can easily find it in Option module. For example, Option.default totally fits your purpose:
let get_string data =
Option.default "" data
There are many other useful functions for working with option types in that module, you should check them out to avoid redefine unnecessary functions.
Another point is that the compiler would tell you if there's something wrong. If the compiler doesn't complain, you know that the types all make sense and that you have covered every case in your match expression. The OCaml type system is exceptionally good at finding problems while staying out of your way. Note that you haven't had to define any types yourself in this small example--the compiler will infer that the type of data is string option.
A lot of the problems the compiler can't detect are ones that we can't detect either. We can't tell whether mapping None to the empty string is what you really wanted to do, though it seems very sensible.