Change the default implementation with an extension in unit tests - swift

I have a simple protocol called Loggable that I want to use to create log entries in my app. The default implementation of the protocol is done with the use of an extension. I want to change that default implementation on my tests to discard any logs on the console while the app is being tested.
protocol Loggable {
func log(message: String, level: LogLevel, customAttributes: [String : AnyObject]?, filename: NSString, line: Int, function: String)
}
So, the default implementation is something like:
extension Loggable {
func log(message: String, level: LogLevel = .Debug, customAttributes: [String : AnyObject]? = nil, filename: NSString = #file, line: Int = #line, function: String = #function) {
// Log internally
InternalLog.log(message, level: level, customAttributes: customAttributes, filename: filename, line: line, function: function)
// Log remotely
// Fabric, LogEntries ?!
}
}
In the unit test I'm doing:
extension Loggable {
func log(message: String, level: LogLevel = .Debug, customAttributes: [String : AnyObject]? = nil, filename: NSString = #file, line: Int = #line, function: String = #function) {
// Do nothing
}
}
The problem is that all the logs are being printed when I run the test suite. It never uses the extension of Loggable added on the unit test.
I know that Swift Extensions can not override but this example is using different targets.
Any nature way to achieve my idea?

Protocol extensions don't use dynamic dispatch which means that any type conforming to that protocol will only use extensions available at compile time or its own implementation if implemented.
In your case, the test target can define another protocol extension but to be used within your test target only, it won't affect your other target which was already compiled and wasn't aware of this other extension.

Related

`XCTest` for a custom `XCTestCase` assert

Apple Concurrency framework is lacking support for async version of XCTAssertThrowsError. I have created a public function as a substitute for it.
func XCTAssertThrowsErrorAsync<T>(_ expression: #autoclosure () async throws -> T,
_ message: #autoclosure () -> String = "",
_ handler: (_ error: Error) -> Void = { _ in },
file: StaticString = #filePath,
line: UInt = #line) async {
do {
_ = try await expression() as T
XCTFail(
message(),
file: file,
line: line
)
} catch {
handler(error)
}
}
I would like to cover this function with unit tests.
What would be the best way to do it?
It depends.
If this is internal to your project: I extract custom test assertions from existing test cases. Then I manually break code to confirm that the assertion works the way I want it to. I especially want to see if I can make failure messages more informative.
I do this manually, without automation.
But if you intend to publish this to open source, then it makes sense to get test coverage. The goal would be to give developers who are not working with you immediate feedback on changes they make to your test framework.
I assume you know how to test the handler(error) call. (If you don't, let me know so I can add to this answer.) The problem is, how do we test the call to XCTFail? Here's how we did it to write ApprovalTests.Swift:
import XCTest
public protocol Failer {
func fail(_ message: String, file: StaticString, line: UInt) throws
}
public struct XCTFailer: Failer {
public func fail(_ message: String, file: StaticString, line: UInt) throws {
XCTFail(message, file: file, line: line)
}
}
Source: https://github.com/approvals/ApprovalTests.Swift/blob/master/ApprovalTests.Swift/Approvers/TestFailer.swift
Instead of calling XCTFail directly, we introduced a Failer protocol. By default, our code uses an XCTFailer() which calls the XCTFail for real. To test it, inject a Test Spy instead.

Swift: obtain module at runtime?

In Swift, at runtime, is it possible to know the name of the module code is running in?
I'd want something like (and this is totally imaginary code)
let moduleName: String = CompileTimeInfo.moduleName
Related.
You might take advantage of the fact that the module name is used as a namespace and debugPrint ing a type will be prefixed with the module name:
enum Test {}
var string: String = ""
debugPrint(Test.self, to: &string)
print("Module name: \(string.split(separator: ".").first ?? "")")
Note: the type must be defined in the actual module. So, wrap first three lines into a function and return the module name, done.
Riffing off of #CouchDeveloper's excellent answer, you can get the module name for an arbitrary Swift type. You can use this to get the module name of any arbitrary code, by creating a type for this purpose.
func moduleName(for type: Any.Type) -> String {
// parse module name from string that looks like "ModuleName.ClassName"
if let subSequence = String(reflecting: type.self).split(separator: ".").first {
return String(subSequence)
} else {
return ""
}
}
print(moduleName(for: String.self)) // -> Swift
enum Test {}
print(moduleName(for: Test.self)) // -> SwiftModuleNameExample
This can even be embedded into a protocol.
public protocol Module {}
extension Module {
static var name: String { moduleName(for: Self.self) }
}
class ThisModule: Module {}
print(ThisModule.name) // -> SwiftModuleNameExample
A macOS command-line Xcode project for this code lives here.

custom console log in swift [duplicate]

I am writing some Swift code and I would like to know the class of the object that called the function. I don't want to pass in any parameters. From within the function I want to be able to know who called it.
Any suggestion?
If you want to do that using Swift, you can do this:
func debug(file: String = #file, line: Int = #line, function: String = #function) -> String {
return "\(file):\(line) : \(function)"
}
To access the underlying class of a method from within itself, use the dynamicType property:
self.dynamicType
If you want to know the origin of the original call, you can use NSThread to return debugging information about the stack:
NSThread.callStackSymbols()
This method returns a descriptive array of values that you're used to seeing when exceptions are thrown. The strings represent a backtrace of all current activity on your call stack.
I don't want to be presumptuous, but it seems to me that outside of debugging, there isn't a good reason, conceptually, at least, to know the origin of a specific method call for any and every function. If you need to retrieve the class Type of the last method call on the stack, why not implement an interface that lets you access this information through a straightforward route?
You can use following template to know from which file, line number in file, and function this someFunction is called:
func someFunction(file: String = #file, line: Int = #line, function: String = #function)
{
NSLog("\(file.lastPathComponent):\(line) : \(function)")
}
Swift:
Add a (sender: Anyobject) as parameter to that function, and then print the sender (the function caller) like this:
func yourFunc(sender: AnyObject){
print(sender)
}
Or add a symbolic breakpoint with a po thread to see the stack trace of the caller of the method
The final way, use the follow protocol:
protocol PrefixPrint {
func formatPrint(_ text: String, function: String, line: Int) -> Void
}
extension PrefixPrint {
#inline(__always)
func formatPrint(_ text: String, function: String = #function, line: Int = #line) {
#if DEBUG
print("\(self).\(function).\(line): \(text)")
#endif
}
}
Console like: FootBall.VNSocketManager.init().44: xx
Joining together a couple of answers and comments:
func function(file: String = #file) {
if let url = URL(string: file) {
let className = url.deletingPathExtension().lastPathComponent
print(className)
}
}

Swift: determine what object called a function?

I am writing some Swift code and I would like to know the class of the object that called the function. I don't want to pass in any parameters. From within the function I want to be able to know who called it.
Any suggestion?
If you want to do that using Swift, you can do this:
func debug(file: String = #file, line: Int = #line, function: String = #function) -> String {
return "\(file):\(line) : \(function)"
}
To access the underlying class of a method from within itself, use the dynamicType property:
self.dynamicType
If you want to know the origin of the original call, you can use NSThread to return debugging information about the stack:
NSThread.callStackSymbols()
This method returns a descriptive array of values that you're used to seeing when exceptions are thrown. The strings represent a backtrace of all current activity on your call stack.
I don't want to be presumptuous, but it seems to me that outside of debugging, there isn't a good reason, conceptually, at least, to know the origin of a specific method call for any and every function. If you need to retrieve the class Type of the last method call on the stack, why not implement an interface that lets you access this information through a straightforward route?
You can use following template to know from which file, line number in file, and function this someFunction is called:
func someFunction(file: String = #file, line: Int = #line, function: String = #function)
{
NSLog("\(file.lastPathComponent):\(line) : \(function)")
}
Swift:
Add a (sender: Anyobject) as parameter to that function, and then print the sender (the function caller) like this:
func yourFunc(sender: AnyObject){
print(sender)
}
Or add a symbolic breakpoint with a po thread to see the stack trace of the caller of the method
The final way, use the follow protocol:
protocol PrefixPrint {
func formatPrint(_ text: String, function: String, line: Int) -> Void
}
extension PrefixPrint {
#inline(__always)
func formatPrint(_ text: String, function: String = #function, line: Int = #line) {
#if DEBUG
print("\(self).\(function).\(line): \(text)")
#endif
}
}
Console like: FootBall.VNSocketManager.init().44: xx
Joining together a couple of answers and comments:
func function(file: String = #file) {
if let url = URL(string: file) {
let className = url.deletingPathExtension().lastPathComponent
print(className)
}
}

Macros in Swift?

Does Swift currently support macros, or are there future plans to add support? Currently I'm scattering:
Log.trace(nil, function: __FUNCTION__, file: __FILE__, line: __LINE__)
In various places throughout my code.
In this case you should add a default value for the "macro" parameters.
Swift 2.2 and higher
func log(message: String,
function: String = #function,
file: String = #file,
line: Int = #line) {
print("Message \"\(message)\" (File: \(file), Function: \(function), Line: \(line))")
}
log("Some message")
Swift 2.1 and lower
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
print("Message \"\(message)\" (File: \(file.lastPathComponent), Function: \(function), Line: \(line))")
}
log("Some message")
This is what fatalError and assert functions do.
There are no other macros except the conditional compilation already mentioned in another answer.
The Apple docs state that:
Declare simple macros as global constants, and translate complex macros into functions.
You can still use #if/#else/#endif - but my feeling is that they will not introduce macro functions, the language simply doesn't need it.
Since XCode 7.3, the __FILE__ __FUNCTION__ and __LINE__ compile-time constants have become the nicer-looking #file #function and #line respectively.
Here is an updated Swift 2 answer.
func LogW(msg:String, function: String = #function, file: String = #file, line: Int = #line){
print("[WARNING]\(makeTag(function, file: file, line: line)) : \(msg)")
}
private func makeTag(function: String, file: String, line: Int) -> String{
let url = NSURL(fileURLWithPath: file)
let className = url.lastPathComponent ?? file
return "\(className) \(function)[\(line)]"
}
Example of use:
LogW("Socket connection error: \(error)")
lastPathComponent needs an NSURL, so I changed the above code to this:
func log(message: String,
function: String = __FUNCTION__,
file: String = __FILE__,
line: Int = __LINE__) {
let url = NSURL(fileURLWithPath: file)
print("Message \"\(message)\" (File: \(url.lastPathComponent ?? "?"), Function: \(function), Line: \(line))")
}
log("some message")
There is way to use macros on swift (but this used in Mixed of objective c and swift)
declare your macros into Project-name-Bridging-Header.h
#define YOUR_MACRO #"Description"
or create separate header file for macros "macros.h"
import this header "macros.h" in to your Bridging-Header.h file..
now just save your project your macros will came in swift file ..
if you don't wanna object c code on your swift project... just create dummy cocoa touch classes it will create bridging header then use my way...
Macros are evil, but sometimes you just need them. For example, I have
struct RegionEntity {
var id: Int!
}
And I want to place instances of this struct to Set. So I have to conform it to Hashable protocol.
extension RegionEntity: Hashable {
public var hashValue: Int {
return id
}
}
public func ==(first: RegionEntity, second: RegionEntity) -> Bool {
return first.id == second.id
}
Great. But what if I have dozens of such structs and the logic is the same? Maybe I can declare some protocol and conform it to Hashable implicitly. Let's check:
protocol Indexable {
var id: Int! { get }
}
extension Indexable {
var hashValue: Int {
return id
}
}
func ==(first: Indexable, second: Indexable) -> Bool {
return first.id == second.id
}
Well, it works. And now I'm gonna conform my struct to both protocols:
struct RegionEntity: Indexable, Hashable {
var id: Int!
}
Nope. I can't do that, because Equatable requires == operator with Self and there is no == operator for RegionEntity.
Swift forces me to copy-paste confirmation code for each struct and just change the name. With macro I could do that with only one line.
A macro proposal is going through Swift Evolution right now. This would allow you to define a custom type that could create a macro that can be evaluated at compile time, like the C stringify macro, for example.
https://forums.swift.org/t/se-0382-expression-macros/62090