Global variables and functions argument in unittest

Asked by Sebastian

Hi All,

I have just started working with SIKULI, its look very promising. I working on Windows 7 64bit.
I have two questions about unit test
1. how can I create global variables in unit test scrip ? I have following example, but cause exception:

globalvar = 0

def useFilter(self):
 print "in filter"
 global globalvar
 print "in filter1"
 globalvar = globalvar + 1
 print "in filter2"
 print globalvar
 print "in filter3"

def setUp(self):
 closeApp("my app")
 wait(4)
 switchApp("C:\Program Files (x86)\myApp\myApp.exe")

 wait(myApp.png ,30)
 self.closeUpdateIfAppear()
 self.maximizeApp()
 wait(1)
 self.resetAppLayout()
 wait(1)
 print "use filter"
 self.useFilter()

I see that after step "in filter1" apears exception.

2. how can I create functions with more argument ?
Now I use only functions that have one "sefl" argument; is it possible to pass more arguments to functions in unit test ?

Regards

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
Last query:
Last reply:

This question was reopened

Revision history for this message
Tsung-Hsiang Chang (vgod) said :
#1

1. use self. globalvar to access that "global variable" (which is not actually global, but a class attribute).
2. Unit testing framework doesn't know what parameters needed to pass into the test* methods. You can create your own functions with arbitrary parameters and call them from the test* methods.

Revision history for this message
Sebastian (zawada-s) said :
#2

Hi,
1. this is clear - thanks for help.
2. Unfortunately i still don't know how can I write my own method. Until now I've wrote something like this :

def myMethod(self)
 print "this is my method"
 click(someButton.png)

and I call it :

def test_some(self)
 self.myMethod()
 ....

It works, but now I want to pass more arguments e.g. I want to write my own method for typing some text and as argument pass text that will be typed. Could you please give me some example ?

Revision history for this message
RaiMan (raimund-hocke) said :
#3

def myMethod(self, text, img=None)
 print text
 if img: click(img)

--- and I call it (version 1)

def test_some(self)
 self.myMethod("this is my method")

should only type text.

--- and I call it (version 2)

def test_some(self)
 self.myMethod("this is my method", "someButton.png")

should type text and click

more info on own functions: http://jythonpodcast.hostjava.net/jythonbook/en/1.0/DefiningFunctionsandUsingBuilt-Ins.html#chapter-4-defining-functions-and-using-built-ins

Revision history for this message
Sebastian (zawada-s) said :
#4

It works fine, thanks RaiMan.
How can I import functions from separate files in unit tests ? I've tried with following example :

My functions in separate sikuli project witeMethod.sikuli :

from sikuli.Sikuli import *

def typeTxt(self, text):
 print "in typeTxt"
 type(text)

My unit test :

def importLibs(self):
 import os
 myPath = os.path.dirname(getBundlePath())
 if not myPath in sys.path: sys.path.append(myPath)
 from writeMethod import *

def setUp(self):
 print "in setUp"
 switchApp("notepad")
 self.importLibs()

def tearDown(self):
 print "in tearDown"
 closeApp("notepad")

def test_1(self):
 print "in test1"
 wait(0.1)
 self.typeTxt("some text")
 wait(1)

I get error:
There was 1 error:
1) test_1(org.python.proxies.__main__$unit2$4)Traceback (most recent call last):

  File "<string>", line 12, in runTest
  File "<string>", line 31, in test_1
AttributeError: 'unit2' object has no attribute 'typeTxt'

seems likes don't know my imported method. How actually should be ?
Regards

Revision history for this message
RaiMan (raimund-hocke) said :
#5

sorry, that is currently not possible this way with the built in unittest feature of Sikuli, because the imported function names are only known in the context of the def() with the import statement. all functions have to be physically there on the first level of your script.

If you want to use imports, you have to implement the standard Python unittest classes yourself
(see http://docs.python.org/library/unittest.html#module-unittest)
which is actually used by Sikuli IDE unittest internally.

Revision history for this message
Sebastian (zawada-s) said :
#6

OK, thanks for help.
Could you please give me some example or link how to use standard Python unittest classes with SIKULLI ?

Regards

Revision history for this message
RaiMan (raimund-hocke) said :
#7

Do it just as shown in the basic example under the above link to setup a test class.

To run it, use the suite approach instead of the main() approach.

this is the general template:

class TestYouNameIt(unittest.TestCase):
    def setUp(self):
        pass
    def teardown(self):
        pass
    def testName1(self):
        pass

suite = unittest.TestLoader().loadTestsFromTestCase(TestYouNameIt)
unittest.TextTestRunner().run(suite)

- substitute the pass statements with your own code
- have a look at the docs for the unittest.TextTestRunner options
- run it normally in Sikuli IDE or from command line (do NOT use option -t)

Revision history for this message
Sebastian (zawada-s) said :
#8

Thanks RaiMan, that solved my question.

Revision history for this message
Sebastian (zawada-s) said :
#9

Hello,
I have one more question - maybe I should had asked at the beginning...
Does it make sense to create large tests for complex testing some big application by use unittest ?
Unit tests "by definition", are for "unit" testing some class and method apart from anothers parts of application.
I want to create many tests for testing all of functionality of some application; Which one way is the best and simple to do it ?

Best Regards

Revision history for this message
RaiMan (raimund-hocke) said :
#10

Not really a question for this forum.

The tools you use for testing depend on your overall goals.

Unittest (Python) or JUnit (Java) allow to write thousands of smaller or bigger tests and arrange them in suites/packages.

On this level it is rather complex to arrange huge amounts of tests according to their dependencies and have an efficient reporting.

So you should look out for testframeworks, that support continuos development and testing (e.g. Hudson and others) with an appropriate workflow support and reporting.

But for most of these solutions you will use unitttest on the testcase level and be able to integrate Sikuli script for these purposes.

Revision history for this message
Sebastian (zawada-s) said :
#11

OK, thanks for your reply.
Sikuli seems appropriate for my goal, but I don't know if I should write my tests and arrange them in suites based on unittest (some limitation as you wrote earlier - can't use import etc) or maybe should I based on another solution (packages tests called e.g. from bat script)

Revision history for this message
RaiMan (raimund-hocke) said :
#12

I do not agree:
when you use the Python/Jython unittest module and run the scripts normally, you can do whatever you want (including import and giving parameters to the test scripts from commandline - anything that is possible in a Jython script).

And in cases, where you find any limitations with the Sikuli runner, you could switch to run your scripts directly with the Jython interpreter provided on your own (e.g. Jython 2.5.2).

The challenge with testing is, to make tests dependent from your development: only run necessary tests (do not repeat things), find out which features have not been tested yet and have a transparent reporting on all these things. This where test suites come on the stage.

Revision history for this message
Sebastian (zawada-s) said :
#13

OK thanks for reply.
I am newbie in Sikuli and Python (Jython) therefore I don't know some features (I wrong found its as limitations). As you wrote, I checked possibility to run script directly with Jython interpreter; I run following example :

import os
import sys
import unittest

class Test(unittest.TestCase):
    def setUp(self):
        switchApp("C:\Program Files\Internet Explorer\IEXPLORE.EXE")
        print("pass")
        print(os.getcwd()) #only for test if can I use OS module
        pass

    def tearDown(self):
        print(sys.executable) #only for test if can I use SYS module
        print("end")
        pass

    def testl(self):
        print("test1 pass")
        wait(2)
        pass

suite = unittest.TestLoader().loadTestsFromTestCase(Test)
unittest.TextTestRunner(verbosity=2).run(suite)

I run script above using command :
java -Dpython.path=Lib -jar sikuli-script.jar mytest.sikuli > test.log

Test was executed with no problems.
But I want to group some simple functions to my own library and use its in my tests.
Maybe I will explain it by example; I want to have open and close my testing application in separate method in separate file runIE.py e.g :

import sys
import os

def runIE():
    print("run IE")
    switchApp("C:\Program Files\Internet Explorer\IEXPLORE.EXE")

def closeIE():
    print("close IE")
    type(Key.F4,KEY_ALT)
    closeApp("windows internet explorer")

And I want to use these method in my setup and teardown :

import os
import sys
import unittest
import runIE

class Test(unittest.TestCase):
    def setUp(self):
        runIE.runIE()
        print("pass")
        pass

    def tearDown(self):
        runIE.closeIE()
        print("end")
        pass

    def testl(self):
        print("test1 pass")
        wait(2)
        pass

suite = unittest.TestLoader().loadTestsFromTestCase(Test)
unittest.TextTestRunner(verbosity=2).run(suite)

But seems that that despite runIE is imported correctly, it can't see Sikuli functions, I got error :

ERROR: testl (__main__.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\Program Files (x86)\Sikuli X\mytest.sikuli\mytest.py", line 8, in set
Up
    runIE.runIE()
  File ".\runIE.py", line 6, in runIE
    switchApp("C:\Program Files\Internet Explorer\IEXPLORE.EXE")
NameError: global name 'switchApp' is not defined

Idea is I want to have pack of simple functions (run testing application, close it, open project, create new project, save project etc) that will be used to test application.
How can I use my own library that will use Sikuli functionality in another scripts that are running directly from Jython interpreter ?
Regards

Revision history for this message
Best RaiMan (raimund-hocke) said :
#14

ok, that's an easy one
(... sorry for pointing it out: and documented here: http://sikuli.org/docx/globals.html#importing-other-sikuli-scripts-reuse-code-and-images on the first page under Prerequisites ;-) (worth to read through)

modules to be imported containing Sikuli features, need this generic import in the beginning (at least before the first Sikuli feature is used)
from sikuli.Sikuli import *

Revision history for this message
Sebastian (zawada-s) said :
#15

Thank, its working fine :)

Revision history for this message
Sebastian (zawada-s) said :
#16

Thanks RaiMan, that solved my question.