How can I test a private or fileprivate function in project - ios

I want to write some unit testing code for a manager class, the function I would write for is using some small private functions. I will prepare a lot if I testing the public function, so I want to test those private functions. But in test target I can't call the private function directly.
So I wanna ask, is there's a way to test them without change them from private to internal or public?

So I wanna ask, is there's a way to test them without change them from private to internal or public?
Add an internal function that does nothing but call the private function. Probably it's best to do it in an extension:
class Foo
{
fileprivate func myPrivateFunction(p: Int) { ... }
}
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
You can probably find a way of using conditional compilation to omit the extension for release builds e.g.
#if DEBUG
extension Foo
{
internal func testMyPrivateFunction(p: Int)
{
myPrivateFunc(p: p)
}
}
#endif
Not tested the conditional thing to see if it works, it's borrowed from here https://ericasadun.com/2018/04/18/forcing-compiler-errors-in-swift/

Sadly no. There isn't a "VisibleForTesting" tag in Swift as there is in java.
However you can define a protocol which your manager class then implements including only the methods you want to test.
For example if your manager has a function called createViewModel that calls several private methods testing that the viewModel created matches that of what we expect we have implicitly tested the private methods work. You can set up your manager with different initial conditions to test all varieties and edge cases

I think you are looking for #testable imports. From Apple's documentation:
When you add the #testable attribute to an import statement for a
module compiled with testing enabled, you activate the elevated access
for that module in that scope. Classes and class members marked as
internal or public behave as if they were marked open. Other entities
marked as internal act as if they were declared public.

Interfaces are the solution.
This solution is a bit more complicated than the others, but can help you for multiple purposes, like uncoupling modules on your app.
Let's say you have a class Foo which has an object of type Bar, and you need to call doStuff().
Create a Protocol for Bar. So Foo is decoupled from Bar and becomes fully testable without exposing its content to Foo. Something like this:
protocol BarProtocol {
func doStuff()
}
class Bar:BarProtocol {
func doStuff() {
print("Hello world")
}
}
class Foo {
var bar:BarProtocol
init() {
self.bar = Bar()
self.bar.doStuff()
}
}

Related

How does the Kotlin/Native compiler handle polymorphism?

In a personal project of mine on Kotlin/JVM, I was told that I should avoid polymorphic method calls in performance sensitive code. Wondering why this was the case, I ended up finding this article which highlights why.
Naturally, I wondered why this limitation was necessary. Can Kotlin/Native avoid virtual method table lookups by enforcing polymorphism just at compile time? Consider the following example.
interface A {
fun foo()
}
class B : A {
override fun foo() = Unit
}
class C : A {
override fun foo() = println("")
}
val bar = listOf(B(), C())
bar.forEach {
it.foo()
}
In the current version of the Kotlin/Native compiler (1.4.20), are virtual method lookups necessary for the above example? Furthermore, are they theoretically necessary? Can the above code be completely enforced by the compiler?

Cannot convert return expression of type

I am currently struggling figuring out this problem.
I have a dynamic framework which implements a Network API f.e lets use GitHub.
The dynamic framework implements a class named GitHub with the following method:
func repos() -> Promise<[Repository]>
The promise implementation is my own implementation which is shared with the app target and the dynamic framework target.
In the app target I define a protocol Client.
protocol Client {
func repositories() -> Promise<[RepositoryWrapper]>
}
Then I let GitHub extend from this protocol in order to transform [Repository] to [RepositoryWrapper].
extension GitHub: Client {
func repos() -> Promise<[RepositoryWrapper]> {
return repositories().map({ repos in
repos.map { transform(repository: $0) }
})
}
private func transform(repository: Repository) -> RepositoryWrapper {
return RepositoryWrapper(id: repository.id, nameWithOwner: repository.nameWithOwner)
}
}
However I am currently getting the error message:
Cannot convert return expression of type 'Promise<[RepositoryWrapper]>' to return type 'Promise<[RepositoryWrapper]>'
I am not quite sure how to solve this since the error message states that the types are the same. If the implementation of map on Promise is needed I am happy to extend this question.
Seems like the issue was that I used the Promise implementation by sharing it to both targets. Once I added it only to the framework target and made it public to use it in the app the above implementation started working.

What's happening behind the scenes in XCTest's #testable?

I know that
#testable import MyModule
gives ability to explore non-public members of MyModule from a "test" (built with "testTarget") module MyModuleTests.
I need the same functionality in my "non-test" module. Not in production, just in debug mode.
My question is: do you know how to do this?
And related (I think, harder question): what magic is actually happening behind #testable?
To answer your question, for debugging purposes, you can actually use this. Let's say you have a workspace MyAwesomeWkspace and a project inside MyAwesomeProject.
Now, create a new framework aka module called MyAwesomeModule. Inside that module create a non-public class called Person.
If you try to use the class Person inside MyAwesomeProject by doing import MyAwesomeModule and then something like let p = Person() you will have an error.
But if you do #testable import MyAwesomeModule, the magic happens and you can now use the class.
Basically #testable allows you to test things that you didn't declare public. The annotation only works with import as you can see it here.
So in order to work, the target is compiled with -enable-testing so that you can have access to non-public members. At least based on what's here
Because, by default, the debug build configuration is compiled with -enable-testing, the example I showed you will work. But if you change the build config to release, you'll see an error saying Module .. was not compiled for testing since the release config is not built with the flag.
The Swift access control model, as described in the Access Control
section of The Swift Programming Language (Swift 4), prevents an
external entity from accessing anything declared as internal in an app
or framework. By default, to be able to access these items from your
test code, you would need to elevate their access level to at least
public, reducing the benefits of Swift’s type safety.
Xcode provides a two-part solution to this problem:
When you set the Enable Testability build setting to Yes, which is
true by default for test builds in new projects, Xcode includes the
-enable-testing flag during compilation. This makes the Swift entities declared in the compiled module eligible for a higher level of access.
When you add the #testable attribute to an import statement for a
module compiled with testing enabled, you activate the elevated access
for that module in that scope. Classes and class members marked as
internal or public behave as if they were marked open. Other entities
marked as internal act as if they were declared public.
More here
Late edit: One of the cool parts of swift is that is open source. So if you want to dive deep into the "magic", check it out: https://github.com/apple/swift
#testable import <module_name> and -enable-testing
[Swift access modifiers]
[Swift module]
consumer side uses #testable import -> producer side should use `-enable-testing` flag
producer side: enable -enable-testing
Enable Testability(ENABLE_TESTABILITY) - YES
Other Swift Flags(OTHER_SWIFT_FLAGS) - -enable-testing
consumer side: #testable
internal(default) and public access level for class is visible for current module as open
internal(default) access level for others(struct, enum) is visible for current module as public
If you build test schema(consumer) with #testable but producer doesn't include -enable-testing you get
Module '<module_name>' was not compiled for testing
Some experiments:
SomeModule
internal class SomeInternalClass {
internal func foo() { }
}
public class SomePublicClass {
public func foo() { }
}
internal class SomeInternalStruct {
internal func foo() { }
}
internal enum SomeInternalEnum: String {
case foo = "hello world"
}
Tests: If you omit #testable next errors will occur
import XCTest
#testable import ExperimentsTests
class ExperimentsTestsTests: XCTestCase {
func testExample() throws {
let someInternalStruct = SomeInternalStruct() //Cannot find 'SomeInternalStruct' in scope
someInternalStruct.foo()
let someInternalEnum = SomeInternalEnum(rawValue: "") //Cannot find 'SomeInternalEnum' in scope
SomeInternalEnum.foo //Cannot find 'SomeInternalEnum' in scope
}
class SomePublicSubClass: SomePublicClass { //Cannot inherit from non-open class 'SomePublicClass' outside of its defining module
override func foo() { } //Overriding non-open instance method outside of its defining module
}
class SomeInternalSubClass: SomeInternalClass { //Cannot find type 'SomeInternalClass' in scope
override func foo() { } //Method does not override any method from its superclass
}
}

Will marking swift extension public change the property in the extension to be implicitly public or internal?

So in Apple documentation:
Any type members added in an extension have the same default access level as type members declared in the original type being extended. If you extend a public or internal type, any new type members you add will have a default access level of internal.
Giving a sub class of UIView extension:
extension UIViewSubClass
{
var helloWorld : String {
get {
return "helloWorld"
}
}
}
This will mark helloWorld as internal, I have no problem, and I cannot see it in my Objective-C based project.
However, if I mark the extension to be public:
public extension UIViewSubClass
{
var helloWorld : String {
get {
return "helloWorld"
}
}
}
Now helloWorld apprears in my Objective-C based code, which means it is marked as public.
However, I don't see Apple mentions this, did it?
I just saw the documentation said a public class will still has implicit internal level.
public class SomePublicClass { // explicitly public class
public var somePublicProperty = 0 // explicitly public class member
var someInternalProperty = 0 // implicitly internal class member
private func somePrivateMethod() {} // explicitly private class member
}
Marking public for extension seems have different effect than marking a Class definition. This makes me confused.
Could someone help me, is this supposed to be so, or this is a sort of swift bug? I am with swift 2.1 and Xcode 7.2
Answer: Yes, placing access level modifiers (in your case, public, specifically) in front of extensions modify the default access level of all new types in the scope of that extension.
Note that the modifier does not affect the access level of the class/struct/etc being extended (only it's members. However, there are things that ought to be considered, as I will discuss below.
In this discussion, I'll post a few important facts regarding regarding access levels in Swift. All these are from the Swift Language Guide - Access Control - Access Levels.
Let's first assure what you've already stated:
All entities in your code (with a few specific exceptions, as
described later in this chapter) have a default access level of
internal if you do not specify an explicit access level yourself.
OK, this goes in line with what you've quoted in you question: any new type members, whether in a class or structure definition, will have a default access level of internal.
Now, lets look at the access level modifier that you can add in front of extensions:
You can extend a class, structure, or enumeration in any access
context in which the class, structure, or enumeration is available.
Any type members added in an extension have the same default access
level as type members declared in the original type being extended. If
you extend a public or internal type, any new type members you add
will have a default access level of internal. If you extend a private
type, any new type members you add will have a default access level of
private.
Alternatively, you can mark an extension with an explicit access level
modifier (for example, private extension) to set a new default access
level for all members defined within the extension. This new default
can still be overridden within the extension for individual type
members.
This sorts things out. We look at your example, and assume that your class UIViewSubClass has access level public (or compile time error, se below):
/* no access level modifier: default access level will be 'internal' */
extension UIViewSubClass
{
// default access level used: internal
var helloWorld : String {
get {
return "helloWorld"
}
}
}
// modify default access level to public
public extension UIViewSubClass
{
// default access level used: public
var helloWorld : String {
get {
return "helloWorld"
}
}
}
With the discussion above in mind, it's expected that your helloWorld in you public extension ... is marked as internal, as this is, in this context, the default access level. In the context of extensions, access level modifiers work differently than when applied to types.
Finally, we should point out that using a public access modifier when extending a non-public class will yield a compile time error in Swift. So in your case above:
If UISubViewClass is an internal or a private class, then the public extension ... on the class will yield an compile time error.
If UISubViewClass is a public class, then adding the public extension will be redundant as the default access modifier of a public class is already, by definition, public.
I'd say that the error described above is not really an error to avoid runtime errors, but rather to avoid redundant (and confusing) code: public member types or private or internal classes will never make use of itspublic` access level.
class MyImplicitlyInternalClass {
private var myExplicitlyPrivateVar = 0
var myImplicitlyInternalVar = 0
public var myExplicitlyPublicVar = 0 // warning, see (Note 1) below
// redundant 'public': can never be accessed publicly
// myExplicitlyPublicVar will behave as 'internal'
}
public extension MyImplicitlyInternalClass { // error, see (Note 2)
var myNewVarIsInternal : Int { get { return 0 } }
}
/* (Note 1) Compile type warning:
"Declaring a public var for an internal class."
(Note 2) Compile time error:
"Extension of internal class cannot be declared public."
Summary: in theory, these two above are the same type of
'faults', but only the latter is flagged as and error. */
Hence, it only ever makes sense to use the access level modifiers on extensions to make the default access level more restrictive, i.e., using internal extension ... of a public class, or private extension or an internal class.

How to use Namespaces in Swift?

The documentation only mentions nested types, but it's not clear if they can be used as namespaces. I haven't found any explicit mentioning of namespaces.
I would describe Swift's namespacing as aspirational; it's been given a lot of advertising that doesn't correspond to any meaningful reality on the ground.
For example, the WWDC videos state that if a framework you're importing has a class MyClass and your code has a class MyClass, those names do not conflict because "name mangling" gives them different internal names. In reality, however, they do conflict, in the sense that your own code's MyClass wins, and you can't specify "No no, I mean the MyClass in the framework" — saying TheFramework.MyClass doesn't work (the compiler knows what you mean, but it says it can't find such a class in the framework).
My experience is that Swift therefore is not namespaced in the slightest. In turning one of my apps from Objective-C to Swift, I created an embedded framework because it was so easy and cool to do. Importing the framework, however, imports all the Swift stuff in the framework - so presto, once again there is just one namespace and it's global. And there are no Swift headers so you can't hide any names.
EDIT: In seed 3, this feature is now starting to come online, in the following sense: if your main code contains MyClass and your framework MyFramework contains MyClass, the former overshadows the latter by default, but you can reach the one in the framework by using the syntax MyFramework.MyClass. Thus we do in fact have the rudiments of a distinct namespace!
EDIT 2: In seed 4, we now have access controls! Plus, in one of my apps I have an embedded framework and sure enough, everything was hidden by default and I had to expose all the bits of the public API explicitly. This is a big improvement.
Answered by SevenTenEleven in the Apple dev forum:
Namespaces are not per-file; they're per-target (based on the
"Product Module Name" build setting). So you'd end up with something
like this:
import FrameworkA
import FrameworkB
FrameworkA.foo()
All Swift declarations are considered to be part of
some module, so even when you say "NSLog" (yes, it still exists)
you're getting what Swift thinks of as "Foundation.NSLog".
Also Chris Lattner tweeted about namespacing.
Namespacing is implicit in Swift, all classes (etc) are implicitly
scoped by the module (Xcode target) they are in. no class prefixes
needed
Seems to be very different what I have been thinking.
While doing some experimentation with this I ended up creating these "namespaced" classes in their own files by extending the root "package". Not sure if this is against best practices or if it has any implications I'm mot aware of(?)
AppDelegate.swift
var n1 = PackageOne.Class(name: "Package 1 class")
var n2 = PackageTwo.Class(name: "Package 2 class")
println("Name 1: \(n1.name)")
println("Name 2: \(n2.name)")
PackageOne.swift
import Foundation
struct PackageOne {
}
PackageTwo.swift
import Foundation
struct PackageTwo {
}
PackageOneClass.swift
extension PackageOne {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
PackageTwoClass.swift
extension PackageTwo {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Edit:
Just found out that creating "subpackages" in above code wont work if using separate files. Maybe someone can hint on why that would be the case?
Adding following files to the above:
PackageOneSubPackage.swift
import Foundation
extension PackageOne {
struct SubPackage {
}
}
PackageOneSubPackageClass.swift
extension PackageOne.SubPackage {
class Class {
var name: String
init(name:String) {
self.name = name
}
}
}
Its throwing a compiler error:
'SubPackage' is not a member type of 'PackageOne'
If I move the code from PackageOneSubPackageClass.swift to PackageOneSubPackage.swift it works. Anyone?
Edit 2:
Fiddling around with this still and found out (in Xcode 6.1 beta 2) that by defining the packages in one file they can be extended in separate files:
public struct Package {
public struct SubPackage {
public struct SubPackageOne {
}
public struct SubPackageTwo {
}
}
}
Here are my files in a gist:
https://gist.github.com/mikajauhonen/d4b3e517122ad6a132b8
I believe this is achieved using:
struct Foo
{
class Bar
{
}
}
Then it can be accessed using:
var dds = Foo.Bar();
Namespaces are useful when you need to define class with the same name as class in existing framework.
Suppose your app has MyApp name, and you need to declare your custom UICollectionViewController.
You don't need to prefix and subclass like this:
class MAUICollectionViewController: UICollectionViewController {}
Do it like this:
class UICollectionViewController {} //no error "invalid redeclaration o..."
Why?. Because what you've declared is declared in current module, which is your current target. And UICollectionViewController from UIKit is declared in UIKit module.
How to use it within current module?
var customController = UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
How to distinguish them from another module?
var customController = MyApp.UICollectionViewController() //your custom class
var uikitController = UIKit.UICollectionViewController() //class from UIKit
Swift uses modules much like in python (see here and here) and as #Kevin Sylvestre suggested you can also use the nested types as namespaces.
And to extend the answer from #Daniel A. White, in WWDC they were talking about the modules in swift.
Also here is explained:
Inferred types make code cleaner and less prone to mistakes, while
modules eliminate headers and provide namespaces.
You can use extension to use the mentioned structs approach for namespacing without having to indent all of your code towards the right. I've been toying with this a bit and I'm not sure I'd go as far as creating Controllers and Views namespaces like in the example below, but it does illustrate how far it can go:
Profiles.swift:
// Define the namespaces
struct Profiles {
struct Views {}
struct ViewControllers {}
}
Profiles/ViewControllers/Edit.swift
// Define your new class within its namespace
extension Profiles.ViewControllers {
class Edit: UIViewController {}
}
// Extend your new class to avoid the extra whitespace on the left
extension Profiles.ViewControllers.Edit {
override func viewDidLoad() {
// Do some stuff
}
}
Profiles/Views/Edit.swift
extension Profiles.Views {
class Edit: UIView {}
}
extension Profiles.Views.Edit {
override func drawRect(rect: CGRect) {
// Do some stuff
}
}
I haven't used this in an app since I haven't needed this level of separation yet but I think it's an interesting idea. This removes the need for even class suffixes such as the ubiquitous *ViewController suffix which is annoyingly long.
However, it doesn't shorten anything when it's referenced such as in method parameters like this:
class MyClass {
func doSomethingWith(viewController: Profiles.ViewControllers.Edit) {
// secret sauce
}
}
Even though it is possible to implement namespaces using Framework and Libraries but the best solution is to use local packages using Swift Package Manager. Besides having access modifiers, this approach has some other benefits. As in Swift Package Manager, the files are managed based on the directory system, not their target member ship, you won't have to struggle with merge conflicts that arise frequently in teamworks. Furthermore, there is no need to set file memberships.
To check how to use local Swift packages refer to the following link:
Organizing Your Code with Local Packages
In case anyone was curious, as of June 10th 2014, this is a known bug in Swift:
From SevenTenEleven
"Known bug, sorry! rdar://problem/17127940 Qualifying Swift types by their module name doesn't work."

Resources