How do I access my app code from my tests in a Swift project? - xcode

I have an Swift Xcode project with code such as:
class Utils: NSObject {
class func cleanString (input: String, trim: Bool) -> String {
// ...
}
}
and then I try to test it:
import XCTest
class AppTests: XCTestCase {
func testConfiguratio() {
Utils.cleanString("foo", trim: true)
}
}
but I get this error:
/Users/pupeno/Projects/macninja/AppTests/AppTests.swift:35:9: Use of unresolved identifier 'Utils'
I have Host Application APIs enabled:
What am I missing?

As it has been said already, the library code and the test code are 2 different modules. So you have to import the library into the test code and also make the functions that you want to test public, e.g:
public class Utils: NSObject {
public class func cleanString (input: String, trim: Bool) -> String {
// ...
}
}
and
import XCTest
import Utils
class AppTests: XCTestCase {
func testConfiguratio() {
Utils.cleanString("foo", trim: true)
}
}
If you want to see working code look at my IBANtools library project which implements exactly this scenario (class functions, swift framework, lots of testing).

If this is an OSX project - make sure you included
#Testable import YOURPROJECTNAME
Above the 'class AppTests: XCTestCase'
and clean your project files.
My Previous question where I had a similar issue is here
Hope this helps ( even a year later...)

The module that contains your tests is distinct from the module that contains your app code. When you want to access classes that are contained within a separate module you need to ensure that the to-be-imported classes are marked as public:
public class Utils: NSObject {
class func cleanString (input: String, trim: Bool) -> String {
// ...
}
}

Related

How to Mock inner methods in GoLang

e.g
type test struct { // few fields}
func (t *test) createresource(res1 string,res2 string)error {
//doing some task
t.createsubresource(res1)
}
func (t *test)createsubresource(res1 string)error{
//perform some task
}
I want to write test function for createresource , how can I mock t.createsubresource(res1) call. This is legacy code and I don't have permission to modify any above function.
Your mock can be done using interfaces, as for example:
main.go
package main
type TestInterface interface {
CreateResource(res1 string, res2 string) error
CreateSubresource (res1 string) error
}
func main() {
DoSomething(new(Test))
}
func DoSomething(t TestInterface) {
t.CreateResource()
}
main_test.go
package main
import "testing"
type TestMock struct {}
func (tm *TestMock) CreateResource(res1 string, res2 string) error {
return nil
}
func (tm *TestMock) CreateSubresource(res1 string) error {
return nil
}
func TestDoSomething(t *testing.T) {
err := DoSomething(new(TestMock))
//... do your assertions
}
Why does it works like that?
Calling a function that depends on a specific structure does not allow you to inject alternatives to it, that's why a solution using interface needs to be created. By having an interface, just implement a new structure that matches that interface and pass it as a dependency injection to the procedure that will be tested.
Also, check this out:
There is no easy way, by default, to just point your original structure and tell Go to make a mock from it. Maybe some 3rd party lib can do it (but I didn't saw that yet).
In go, public and private declarations are defined by the first letter as uppercase. By the lower cases declarations in your sample I've noticed that everything is private.
Usually it is not a good practice to test private methods. There are a lot of discussions about this topic, you can take a look in this one here
There are also some support libs to make assertions and mocks like for example stretchr/testify, please make a research first.
I hope that it helps you.

How to use someClass.android.ts and someClass.ios.ts without errors

I'm using nativescript angular. I have a class called SomeClass that access the native API of iOS and Android separately.
I've written two files:
someclass.android.ts
export class SomeClass {
someFunction() {
if(isAndroid) {
// do some android specific code
}
}
}
someclass.ios.ts
export class SomeClass {
someFunction() {
if(isIOS) {
// do some ios specific code
}
}
}
Now, in app.component.ts, I'm using SomeClass like this:
import { SomeClass } from './../shared-code/someclass';
without .android.ts or .ios.ts, to enable nativescript to pick the right file depending on the running platform.
and then in the code, I user SomeFunction like this:
...
const someClass = new SomeClass();
someClass.someFunction();
...
With this setting, everything works perfectly on both iOS and Android, but I get the following error
error TS2307: Cannot find module './../shared-code/someclass'.
Do you have any idea how to tell nativescript/tslint to take into account the .android and .ios files and not to display this error?
Thanks
Here's the solution:
Alongside 'someclass.ios.ts' and 'someclass.android.ts', create a definitions file and name it 'someclass.d.ts' (Not index.d.ts). No need to put the files in a separate folder.
In someclass.d.ts, export declare the class like this:
export declare class SomeClass {
/**
* someFunction, is a function that does this and that (description)
*/
someFunction(): void;
}
Then, you can use this from another file like this:
In app.component.ts:
import { SomeClass } from './../shared-code/someclass';
Remember to use /someclass without any extensions.
This would solve build and tslint errors.

How to write extension method for Gradle dependencies {} block

I'm trying to write extension methods for DependencyHandler.
One of main goals to have autocompletion of these methods.
So I wrote extension function in buildSrc project like this (Shortcuts.kt):
fun DependencyHandler.autoValue() {
add("compileOnly", Libs.Auto.autoValueAnnotations)
add("annotationProcessor", Libs.Auto.autoValueCompiler)
}
And registered it as extension module as described here:
# File: src/main/resources/META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
moduleName = buildSrc
moduleVersion = 1.0
extensionClasses = com.example.test.ShortcutsKt
I want to use these methods in build.gradle files like:
dependencies {
...
autoValue()
}
It appears in autocompletion list inside dependencies{} block, but at configuration time I got error:
org.gradle.internal.metaobject.AbstractDynamicObject$CustomMessageMissingMethodException: Could not find method autoValue() for arguments [] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
at org.gradle.internal.metaobject.AbstractDynamicObject.methodMissingException(AbstractDynamicObject.java:179)
at org.gradle.internal.metaobject.ConfigureDelegate.invokeMethod(ConfigureDelegate.java:87)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:430)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:369)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:158)
at build_dh4v5lw1dkt4b2nii5ope5rmy$_run_closure1.doCall(/.../app/build.gradle:29)
Gradle DefaultDependencyHandler implements custom method resolution strategy (to handle scopes notation like testCompile(smth)), so additional methods can be added via dependencies.ext property:
dependencies.ext.autoValue = {
dependencies.add("compileOnly", Libs.Auto.autoValueAnnotations)
dependencies.add("annotationProcessor", Libs.Auto.autoValueCompiler)
}
But in this case you don't get autocompletion.
To enable autocompletion you can mix this two approaches and proxy extension methods from buildSrc via dependencies.ext:
import com.example.test.ShortcutsKt
import java.lang.reflect.Method
import java.lang.reflect.Modifier
// DependencyHandler implementation resolves all undeclared methods by self,
// so we need to add these extension methods to dependencies.ext
def methodNames = ShortcutsKt.declaredMethods
.findAll { isDependencyHandlerExtension(it) }
.collect { it.name }
.unique()
methodNames.each { String methodName ->
dependencies.ext[methodName] = { Object... args ->
ShortcutsKt."$methodName"(dependencies, *args)
}
}
private static boolean isDependencyHandlerExtension(Method method) {
return Modifier.isPublic(method.getModifiers()) &&
Modifier.isStatic(method.getModifiers()) &&
method.parameterCount > 0 &&
method.parameterTypes[0] == DependencyHandler.class
}

How do I package extension functions in a library jar?

I have a set of extension functions that I would like to package into a jar and include in a project, but I can't seem to assess the extension functions from the jar. I can access non-extension functions from the same jar.
For example if I create a project in Idea including the following file, and build the jar.
package mypackagename.swtbuilder
import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.*
fun myFun() {
println("here")
}
fun Composite.tree(treeStyle: Int = SWT.NONE, init: Tree.() -> Unit): Tree {
val treeWidget = Tree(this, treeStyle)
treeWidget.init()
return treeWidget
}
Then include the jar as a dependency in another project using something like this in the build.gradle file.
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
compile "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:4.5.2"
compile files('/home/john/development/swt-builder/build/libs/swt-builder-1.0-SNAPSHOT.jar')
}
I can use myFun in the new project, but all the extension functions are unresolved.
import mypackagename.swtbuilder.myFun // this import works
import mypackagename.swtbuilder.tree // this import is "grayed out"
fun main(args: Array<String>) {
val display = Display()
myFun() // this function call works
val myTree = tree { // tree is un-resolved
}
}
What do I need to do to make the extension functions visible?
Silly mistake, the extension functions are visible, they just need to be called in the context of object they are extensions of. In this case a Shell which is a subclass of Composite. I had all this working fine when the extensions and the main were in the same project. I was trying to make the extensions a separate library and got ahead of myself trying to make sure they were imported properly.
fun main(args: Array<String>) {
val display = Display()
val myShell = shell {
tree { }
}
myShell.open()
while (!myShell.isDisposed) {
if (!display.readAndDispatch()) display.sleep()
}
display.dispose()
}

use of # in Swift 2

Hi so my friend gave me his client's existing project and it got too much bugs. I have been debugging the app, and just cam across this line of code
class func saveFile(#data: NSData, filename: String, directory: NSSearchPathDirectory = .DocumentDirectory) -> Bool {
var file = filePath(filename, directory: directory)
return data.writeToFile(file, atomically: true)
}
Noticed #? So what exactly is #?
Here's a screenshot of function with # too.
Additional Info: I think they used this library Service Stack and I think it's for xamarin only.
In Swift 1, # was used to give the same external and internal name to a function parameter. For example, the function definition:
func save(#data: Float) {
print(data)
}
Was equivalent to:
func save(data data: Float) {
print(data)
}
This was removed in Swift 2, and external names must be declared explicitly.
External parameter names are used to make function calls more idiomatic. For example:
func send(sender: String, receiver: String) {
print("Sending from \(sender) to \(receiver)")
}
Is called like this:
send("Cupertino", "New York")
By adding external parameters, you can make that function call more idiomatic without changing the body:
func send(from sender: String, to receiver: String) {
print("Sending from \(sender) to \(receiver)")
}
Making the code more readable:
send(from: "Cupertino", to: "New York")
More information in the Apple docs.

Resources