Chaining #imports in UIAutomation javascript - ios-ui-automation

I'm trying to break up my UIAutomation test scripts into chunks, to make it possible to run them one piece at a time or all together. So I have a structure:
all-tests.js:
#import "tab-dates.js"
#import "tab-temperatures.js"
tab-dates.js:
#import "../../../Libraries/tuneup_js/tuneup.js"
#import "dpl_assertions.js"
var target = UIATarget.localTarget();
var app = target.frontMostApp();
test("Verify date view is shown", function() {
assertEquals(tabBar.selectedButton().name(), "Date");
});
Both of these live in the same directory, and are imported into an automation trace file that also lives in the same directory.
When I run tab-dates.js directly, everything is fine. tuneup.js is found, path is correct, test passes. But when I try to run all-tests.js, I get:
Script threw an uncaught JavaScript error: Can't find variable: test on line 8 of tab-dates.js
It's not a straight path problem, because if I edit the script to break the path I get a different error that explicitly says 'file not found'.
As far as I can tell, chaining imports is supposed to work -- I mean, this is the entirety of tuneup.js (https://github.com/alexvollmer/tuneup_js):
#import "assertions.js"
#import "lang-ext.js"
#import "uiautomation-ext.js"
#import "screen.js"
#import "test.js"
#import "image_assertion.js"
So I have the weird situation that
tab-dates.js imports tuneup.js imports test.js => OK
all-tests.js imports tab-dates.js imports tuneup.js imports test.js => NOT OK
What's going on?

TL;DR the initial script you run is special. To work around this, create an initial script that includes exactly one other script, and then these general rules apply:
imports are done in the order they appear in a file
a script will first execute, then do its imports
imports are done depth first
a script imported once will not be re-imported
However, the initial script does not obey these rules.
I spent some time figuring this out by creating four scripts: one.js; two.js; three.js and other.js, where one.js imports two.js; which imports three.js; which imports one.js and they all import other.js. Apart from the import, the scripts log their name, like so:
#import "two.js";
#import "other.js";
UIALogger.logMessage("one.js");
If I then run one.js, the output I get is
2015-03-04 21:21:20 +0000 Default: two.js
2015-03-04 21:21:20 +0000 Default: three.js
2015-03-04 21:21:20 +0000 Default: one.js
2015-03-04 21:21:20 +0000 Default: other.js
2015-03-04 21:21:21 +0000 Default: one.js
Then I created a script called launch.js, that imports one.js and nothing else. When I run this script, the output I get is:
2015-03-04 21:27:59 +0000 Default: one.js
2015-03-04 21:27:59 +0000 Default: two.js
2015-03-04 21:27:59 +0000 Default: three.js
2015-03-04 21:28:00 +0000 Default: other.js
2015-03-04 21:28:00 +0000 Default: launch.js
From this we can deduce that:
the initial script called will first do its imports, then execute
the initial script will be re-imported and run if imported by other scripts, exactly once
imports are done depth first
So use the launch.js strategy to reduce pain in your life.

As Jonathan Penn said this is a known bug but you can create a header file that imports all the necessary files for your tests, and then import that header file at the beginning of whatever script runs first.

Related

How to ignore import file from Global import in Robot framework

I have imported Resource from the submodule and then I need to rewrite some data in the file but it doesn't work because it calling the global file import
Example:
# submodule/imports/web_global.robot
*** Settings ***
Variables ${CURDIR}/../test_data/products_data.yaml
${products_data}: global
# imports/web_local.robot
*** Settings ***
Resource ${CURDIR}/../submodule/imports/web_global.robot
Variables ${CURDIR}/../test_data/products_data.yaml
${products_data}: local
# testcases/web/test_file.robot
*** Settings ***
Resource ${CURDIR}/../../imports/web_local.robot
*** Test Cases ***
Example
Log To Console ${products_data}
I got the last result is global. How to get the last result to local
You might be confusing the yaml method of supplying variables with the ${} "usual way". As given, your "${var}: " causes a syntax error because it is an illegal variable name (cannot end with a colon).
You do not show your products_data.yaml (please supply all code), but I am guessing that your ${products_data}: should be expressed as
VAR: value
PRODUCTS_DATA: global
It is a confusing question and I am struggling to grasp it.
Here is my attempt to re-create your question, but I could not re-produce the full sense of your question.
*** Settings ***
Variables ${CURDIR}/test_data/products_data.yaml
*** Variables ***
${products_data} local
*** Test Cases ***
Example
Log To Console Value of products_data is ${products_data}\n
and the result:
==============================================================================
SOExample
==============================================================================
Example Value of products_data is local
Example | PASS |
I painstakingly re-created your entire, convoluted chain.
The semantic answer to your question: when there is a naming conflict, Robot takes the first one (ignores your 2nd definition of the like-named variable products_data).
You can read about it in the RF User Guide, section on variables
Here is the relevant paragraph:
All variables from a variable file are available in the test data file that imports it. If several variable files are imported and they contain a variable with the same name, the one in the earliest imported file is taken into use. Additionally, variables created in Variable tables and set from the command line override variables from variable files.
Simplest solution: in imports/web_local.robot, remove the Resource which you do not want:
*** Settings ***
#Resource ${CURDIR}/../submodule/imports/web_global.robot
Variables ${CURDIR}/test_data/products_data.yaml
Now your variable from imports/test_data/products_data.yaml is used.
Good luck untangling! I recommend re-thinking your structure.

Testing net/http?

I am a little confused about how to structure a go web app and its tests. I have read the How to Write Go Code but still don't get it. For example, I have a go project called "beacon" with a beacon.go file at the root. Adding a trivial beacon_test.go file (copied verbatim from http://golang.org/pkg/net/http/httptest/#example_Server) causes this error:
$ go test
# github.com/jelder/beacon
./beacon_test.go:11: main redeclared in this block
previous declaration at ./beacon.go:216
FAIL github.com/jelder/beacon [build failed]
Sure enough, line 11 is func main(). If I instead change the package main line in my beacon_test.go to package hello, I get this error instead:
can't load package: package github.com/jelder/beacon: found packages main (beacon.go) and hello (beacon_test.go) in /Users/jacob/src/github.com/jelder/beacon
beacon_test.go has also a function called main() rename it to TestFirst (or any other name you like as long as it starts with Test, note the uppercase T is important). There is no need for that. Just run go test . from inside the package you are working on (the one containing the *.go files). Post the full files if you need more help.

How do I get XCode to build a project with Objective-C++ in it?

I added the Scintilla framework successfully to my XCode project (i.e. it finds the header files correctly), but because it is written in Objective-C++ it doesn't compile. I get 8 syntax errors because of ::s. I already found you can't include Objective-C++ from a pure Objective-C file, so I changed the file extension to mm. It still gives me the same 8 errors.
I also changed the file type (of the importing file) to sourcecode.cpp.objcpp.
The relevant lines of code (with the errors in comments - the line numbers are from the original file, so without the errors in the comments):
ScintillaView.h
// Line 47-49
#protocol ScintillaNotificationProtocol
- (void)notification: (Scintilla::SCNotification*)notification; // 4 errors on this line:
// 1. expected type-specifier
// 2. expected ')'
// 3. expected identifier
// 4. expected ';'
#end
// [snip]
// Line 131
- (void) notification: (Scintilla::SCNotification*) notification; // The exact same errors.
When copying this code I noticed the :: operator is used a few more times in the file, so somehow the parser is only able to match it succesfully in certain places.
Once more, this code is not mine, but taken from the Scintilla Cocoa Library.
(See here for more info: http://www.scintilla.org/)
XCode 3.2.6, Mac OS X 10.6.8
Adding
typedef tdSCNotification Scintilla::SCNotification
Before the first offending line revealed that there was no type called SCNotification in that namespace. So I searched through the included header files (which, luckily, count only three) for namespace Scintilla {. It was in the first included header file, Scintilla.h. But it looked like this:
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
and
#ifdef SCI_NAMESPACE
}
#endif
So I assumed SCI_NAMESPACE wasn't defined. I added #define SCI_NAMESPACE to Scintilla.h somewhere online 45 and it worked. Almost. I got another error message:
Framework not found Scintilla
Command /Developer/usr/bin/llvm-g++-4.2 failed with exit code 1
I think this has to do with how I added the framework to my project, so it should be a separate question.

LESS: Unrecognised input "#import ..."

I have a really simply LESS file which for now just imports Bootstrap. I'm using grunt and grunt-contrib-less#0.9.0 to compile the LESS files on save (less#1.6.3).
My file looks like this:
#charset "utf-8";
/**
* This is the root style file for the app
* to include styles in your html, you only need to include either:
* dist/styles.dev.css (for development)
* dist/styles.css (for production)
*/
// Libraries
#import "../lib/bootstrap/less/bootstrap"
// Our own files
and I'm getting the following error whenever I try to run my less:dev task.
Running "less:dev" (less) task
>> ParseError: Unrecognised input in style/styles.less on line 10, column 1:
>> 9 // Libraries
>> 10 #import "../lib/bootstrap/less/bootstrap"
>> 11
I've tried removing everything from the file except the import line and it still fails, so something weird is going on with the #import directive.
Any ideas?
Use semi-colon after #import
#import "../lib/bootstrap/less/bootstrap";

How to add a user defined function in QDB Library?

QDB is a database provided by QNX Neutrino package. I went through the QDB documentation to add a user defined SQL function: http://www.qnx.com/developers/docs/6.5.0/topic/com.qnx.doc.qdb_en_dev_guide/writing_functions.html?cp=2_0_8
I created a source file which had my user define SQL function written in C and qdb_function structure definition. I built it with a make file to create libudf.so.
As suggested by QDB I added Function = udftag#libudf.so in the qdb.cfg. But while running the qdb in the shell prompt, it is giving the error (in bold):
qdb -I basic -V -R set -v -c /etc/sql/qdb.cfg -s de_DE#cldr -o tempstore=/fs/tmpfs
QDB: No script registered for handling corrupt database.
qdb: processing [TempMainAddressBook]Function - Can't access shared library
and qdb is getting exited immediately.
I have tried following things:
made sure sqlite3 library is added in the make file
source code is in strictly in C by using directive : extern "C" to avoid name mangling as the file extension is .cpp. I also tried with .c extension.
given the absolute path of the libudf.so in qdb.cfg as : Function = udftag#/usr/lib/libudf.so
qdb_funcion struct is properly defined in library's source code only.
tried without using the static declaration of function(mentioned in the qdb docs)
After trying all hits and trials also, I am getting the same error every time which is Can't access shared library
If any one has any idea to resolve this error please share.
Suggestion 1: run qdb by setting LD_DEBUG=1, like in:
LD_DEBUG=1 qdb command line options
This will output a lot of debug information from the dynamic loader as it attempts to locate and then load the .so files. Check what is the path that it output before the "Can't access" message is displayed.
Suggestion 2: obvious but make sure that the permissions are OK for the .so file. Do you have the execution permission set?
Suggestion 3: check if the error message is identical if you completely remove the .so file from the system
Suggestion 4: increase the number of lower-case 'v'-s. QDB likely supports more, with progressively more verbose information provided as you increase the numbers (6 should be enough for full verbosity)