UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

macOS 14 upgrade caused new confusing errors in my Swift test.

Forums > Swift

I've recently upgraded my app's target to macOS 14.0 and am now getting errors in my Swift test that worked before and I can't wrap my head around. Figured I'd ask here in case it's something you've already come across.

  1. I have a non-optional CoreData object I'm passing into a function that accepts the optional version of it. Now I'm getting: Cannot convert value of type 'myObjectName' to expected argument type 'myObjectName?'. I know I can technically fix this by making the function not accept optional parameters but this would break my code and/or force me to make a secondary function just for testing.
  2. I have two dictionaries of type [String:String]? that I compare using XCTAssertEqual(hashOriginal!, hashCustom!, "The two hash values can't be equal. My original one is \(hashOriginal ?? "no value") while the custom one is \(hashCustom ?? "no value")."). I'm now getting an error: Generic parameter 'T' could not be inferred
  3. Calling a function outside my test. I've cast the CoreData objects in my test as the appName rather than the appNameTests version as I got errors previously while running it against macOS 13. I'm assuming the functions that I'm calling outside of my tests were appName too especially as this worked before. I'm now getting Cannot convert value of type 'AppName.CoreDataObjName' to expected argument type 'AppNameTests.CoreDataObjName'. These functions are outside my code and I don't want to go around renaming each function parameter from CoreDataObjName to AppName.CoreDataObjName as these methods are also called in my main code (hence the testing).

Thanks everyone. :)

3      

After upgrading to macOS 14.0, I'm encountering errors in my Swift test. The issues relate to optional parameter handling, generic parameter inference, and object types. These changes are causing compatibility challenges. Any insights or solutions would be greatly appreciated. Thanks! 😊

4      

Figured out the first two! Not the third yet.

  1. Use Optional.some(myObject)
  2. I got the error Generic parameter 'T' could not be inferred on another test when it was comparing two different types. Fixed this one by declaring the type when creating it rather than letting the value infer it. IE: var name = "example" --> var name:String = "example"

3      

It seems you're encountering several issues after upgrading your app's target to macOS 14.0. Let's break down your concerns and provide potential solutions:

  1. Passing Non-Optional CoreData Object to Function Accepting Optional:

    • You can handle this by adding a nil-coalescing operator (??) when passing the non-optional CoreData object to the function accepting the optional version. For example:
      functionAcceptingOptional(myNonOptionalObject ?? myOptionalObject)
  2. Error with Generic Parameter 'T':

    • The "Generic parameter 'T' could not be inferred" error typically occurs when the XCTAssertEqual function can't automatically infer the types of hashOriginal and hashCustom. To fix this, you can specify the generic types explicitly:
      XCTAssertEqual(hashOriginal as [String: String]?, hashCustom as [String: String]?, "The two hash values can't be equal...")
  3. Function Parameter Mismatch:

    • To address the "Cannot convert value of type..." error when calling functions outside your tests, you might need to ensure that the parameter types match the expectations of the functions. If renaming the parameter type is not an option, you can create wrapper functions or use a type alias to adapt to the expected parameter types. For example:

      typealias CoreDataObjName = AppName.CoreDataObjName
      
      func wrapperFunction(obj: CoreDataObjName) {
       // Call the function with the adjusted parameter type here
       functionName(obj)
      }
      
      // Call the wrapper function in your tests
      wrapperFunction(myCoreDataObject)

These solutions should help you address the issues you're facing in your Swift tests after the macOS 14.0 upgrade.

3      

Question for Kyra or any humans observing this topic (i.e., excluding the two chatbots above):

Are there any tutorials or books that would help me understand the situations in which unit tests would be helpful to a solo developer (not a member of a development team)?

After reading at least half of Paul's book "Testing Swift", it seems that creating formal unit tests is a lot more work than simply testing by observing the UI and printing properties that are not displayed in the UI.

Writing unit tests for everything at too low a level would be ridiculous. Are there general rules of thumb regarding the level of functionality that warrants formal unit tests?

3      

Jon Reid has a blog dedicated to test-driven development on iOS, qualitycoding.org. The site also has a link to his book on iOS unit testing.

Entering why write unit tests in a search engine brings up articles that introduce unit testing and why you should do it. I can't link to any of them because this forum doesn't allow most links outside of a few domains (GitHub, Hacking with Swift, Apple) as a spam prevention measure.

4      

Just checked in and saw your question BobStern. I'm a solo developer and have started tests on the logic big things but haven't tested UI or anything yet. Haven't put anything in the app store but figure it's more for the test to catch a problem before it goes to the store.

3      

Kyra: If you're still watching this topic, I just faced a similar problem while learning to use unit tests in a SwiftUI app. Perhaps you made the same mistake I did.

In my Test class, I declared a property intended to hold an instance of MyApp. My error was to declare its type as any App (i.e., protocol conformance) instead of MyApp (struct type). I believe the following is correct:

final class MyAppTests: XCTestCase {
    private var app: MyApp!

    override func setUp() {
        super.setUp
        self.app = MyApp()
    }

This should eliminate the namespacing problem (your question 3).

However, if you have a different problem because your Test class is creating an in-memory copy of your Core Data store in addition to the persistent copy created by MyApp, I have a suggestion for eliminating that. In your test target, define a custom environment variable as explained in Paul Hudson's "Testing" book. In your production app, add an if statement that instantiates the NSPersistantContainer either as persistent or as in-memory (/dev/null) depending on whether the custom environment variable exists and has the value specified for your test target.

3      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.