Testing fatalError and friends

Indeed, I don't think the framework can do anything productive in that case, but that's kind of my point. fatalError is like an escape hatch of last resort, and error condition that was unexpected and unrecoverable. Except we want it to be sort of recoverable, for detecting that condition in a test fixture.

Kind of. You can do preflight checks that minimize the chance of failure in the delegate method itself, but the use of a force unwrap or fatalError remains basically unavoidable. Let me illustrate with an example:

Pretty much every implementation of tableView(_:viewFor:row:) will call NSTableView.makeView(withIdentifier:owner:) to reuse an existing view, or create a new one if none are available. It returns an optional, since of course there's a chance that at the time of look-up, there's no registered view's with the given identifier.

We can minimize the risk by doing a preflight check earlier in the code that constructs our NSTableView, to validate that every identifier we're going to eventually use is registered, but that has some caveats/limitations:

  1. Notice that the force unwrap continues to be necessary in the tableView(_:viewFor:row:) method. We can be more confident it'll never trip, but it'll still have to be ther, to satisfy the type system.
  2. You have to be careful to keep your preflight checks and tableView(_:viewFor:row:) implementation in sync. If you start using a new cell identifier in the delegate method, but forget to pre-check it, then you're susceptible to nil errors.
  3. "Move the error check elsewhere" doesn't scale well. Imagine if this use of NSTableViewDelegate was part of a UI framework that wraps AppKit. It would be rather tricky to design your API in a way that allows for you to the do the correct pre-checking on your client's behalf, and then accessing the makeView function without a risk of erroring.

At bottom, it still seems to me like a preferable solution be to have a fatalError right in the delegate method, with a friendly/informative message, and a test which validates that attempts to make views with unknown identifiers leads to those fatalError messages.

1 Like