01.02.2015 Views

How to unit test SugarCRM modules? - SugarForge

How to unit test SugarCRM modules? - SugarForge

How to unit test SugarCRM modules? - SugarForge

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>How</strong> <strong>to</strong> <strong>unit</strong> <strong>test</strong> <strong>SugarCRM</strong> <strong>modules</strong><br />

Ingo Jaeckel (ingo.jaeckel@student.hpi.uni-potsdam.de)<br />

January 27, 2009<br />

1 Introduction<br />

You may experienced that it is not possible <strong>to</strong> write and execute <strong>unit</strong> <strong>test</strong>s as usual for<br />

<strong>SugarCRM</strong> using the “usual suspects” (PHPUnit [1], SimpleTest [2]). I even developed a<br />

tiny <strong>unit</strong> <strong>test</strong>ing “framework” on my own and tried <strong>to</strong> <strong>unit</strong> <strong>test</strong> my <strong>SugarCRM</strong> <strong>modules</strong><br />

with it. Unfortunately, this was without any success.<br />

<strong>How</strong>ever, there are other people having the same or related issues (see PHP bugtracker<br />

[3], [4]).<br />

I think that the way PHP handles global 1 variables and the way you execute the<br />

<strong>SugarCRM</strong> code during the <strong>unit</strong> <strong>test</strong> 2 is the reason for these problems 3 .<br />

This document shows you how <strong>to</strong> workaround most problems and be able<br />

<strong>to</strong> <strong>unit</strong> <strong>test</strong> your code.<br />

2 What’s the problem (short version)<br />

<strong>SugarCRM</strong> uses a lot global variables (around 280). If you write some PHP <strong>unit</strong><br />

<strong>test</strong>cases you will write some methods. Within these methods you will write some<br />

require_once statements <strong>to</strong> load the classes or methods you need. Or you wrote those<br />

statements above the <strong>test</strong> case class that you defined.<br />

<strong>How</strong>ever, when PHPUnit executes your <strong>test</strong>s after each other, something similiar<br />

will happen: The <strong>SugarCRM</strong> code that will be executed in a <strong>test</strong>method will at some<br />

point do some require_once calls <strong>to</strong> load the classes, methods or variables it needs.<br />

Unfortunately those variables will never be “real globals” - Meaning if you try <strong>to</strong> get<br />

access <strong>to</strong> them using the global statement, they will just be uninitialized 4 .<br />

This means <strong>SugarCRM</strong> tries <strong>to</strong> create global variables at some point which does not<br />

work, because we are in a <strong>test</strong>method and cannot create variables with global scope.. As<br />

a consequence NOTHING really works. You will get <strong>to</strong>ns of errors. If you fixed one<br />

1 See the manual [5] for more information about the global statement in PHP.<br />

2 See how Joel Hainley works around this problem by moving all global variables <strong>to</strong> a single<strong>to</strong>n [6].<br />

3 Sebastian Bergmann gives a few hints about PHPUnit and globals on [7].<br />

4 Sometimes () it is possible <strong>to</strong> access those variables with the $GLOBALS array. But you probably do<br />

not want <strong>to</strong> modify any <strong>SugarCRM</strong> code just <strong>to</strong> get your <strong>unit</strong> <strong>test</strong>ing stuff working.<br />

1


3 The solution..<br />

problem (by modifying <strong>SugarCRM</strong> core files which is a great idea) you will constantly<br />

get other problems. Yehaa!<br />

3 The solution..<br />

.. is actually quite simple. All you have <strong>to</strong> do is<br />

1. Insert six <strong>SugarCRM</strong> specific lines in<strong>to</strong> the php<strong>unit</strong> script (see listing 1, lines 5-15).<br />

Now all neccessary global variables are initialized and accessable.<br />

1 #! / usr / bin / php -d safe_mode = Off<br />

2 < php<br />

3 // change <strong>to</strong> the sugarcrm root direc<strong>to</strong>ry .<br />

4 // this depends on your direc<strong>to</strong>ry structure !!<br />

5 chdir (’../../../ ’);<br />

6 // initialize sugarcrm environment _before_ doing anything<br />

else<br />

7 define (’sugarEntry ’, TRUE );<br />

8 require_once (’include / utils . php ’);<br />

9 require_once (’include / <strong>modules</strong> . php ’);<br />

10 require_once (’include / entryPoint . php ’);<br />

11<br />

12 // change <strong>to</strong> the direc<strong>to</strong>ry containing your <strong>unit</strong> <strong>test</strong>s and the<br />

13 // php<strong>unit</strong> direc<strong>to</strong>ry if neccessary . this depends on your setup<br />

14 // and direc<strong>to</strong>ry structure .<br />

15 chdir (" include / UnitTests / PHP ");<br />

16<br />

17 /* here starts the original content of the php<strong>unit</strong> script<br />

18 * leave unchanged<br />

19 */<br />

20 require_once ’ PHPUnit / Util / Filter . php ’;<br />

21 PHPUnit_Util_Filter :: addFileToFilter ( __FILE__ , ’ PHPUNIT ’);<br />

22 require ’ PHPUnit / TextUI / Command . php ’;<br />

23 ><br />

Listing 1: You have <strong>to</strong> adjust the php<strong>unit</strong> script like <strong>to</strong> workaround the <strong>unit</strong> <strong>test</strong>ing<br />

problems.<br />

2. Disable the backup global variables feature of PHPUnit for your <strong>test</strong>case(s) by<br />

setting $backupGlobals (see listing 2).<br />

1 < php<br />

2 require_once (’PHPUnit / Framework . php ’);<br />

3<br />

4 class FirstTest extends PHPUnit_Framework_TestCase {<br />

2


References<br />

5 protected $backupGlobals = FALSE ;<br />

6 ...<br />

7 }<br />

8 ><br />

Listing 2: Declare the protected variable $backupGlobals and set it <strong>to</strong> FALSE in your<br />

<strong>test</strong>case.<br />

If you are through this list and disabled the backup of globals as shown in listing 2<br />

you should be able <strong>to</strong> write <strong>unit</strong> <strong>test</strong>s as usual for your <strong>SugarCRM</strong> <strong>modules</strong> (see listing<br />

3 for an example).<br />

1 < php<br />

2 require_once (’PHPUnit / Framework . php ’);<br />

3<br />

4 class FirstTest extends PHPUnit_Framework_TestCase {<br />

5 protected $backupGlobals = FALSE ;<br />

6<br />

7 public function <strong>test</strong>Something () {<br />

8 chdir (’../../../../ ’);<br />

9 require_once (’<strong>modules</strong> / Users / User . php ’);<br />

10<br />

11 $u = new User ();<br />

12 $list = $u -> get_list (’’, ’’);<br />

13 $userList = $list [’list ’];<br />

14<br />

15 foreach ( $userList as $user ) {<br />

16 $this -> assertNotNull ( $user );<br />

17 $this -> assertFalse ( empty ( $user ->id));<br />

18 }<br />

19 }<br />

20 }<br />

21 ><br />

Listing 3: A basic <strong>unit</strong> <strong>test</strong> that can be executed with a modified version of your php<strong>unit</strong><br />

script.<br />

References<br />

[1] Php<strong>unit</strong>. http://www.php<strong>unit</strong>.de/.<br />

[2] Simple<strong>test</strong>. http://www.simple<strong>test</strong>.org/.<br />

[3] Objects disappear from the global scope.<br />

http://bugs.php.net/bug.phpid=40604.<br />

3


References<br />

[4] Inconsistent handling of $globals from included files.<br />

http://bugs.php.net/bug.phpid=34689.<br />

[5] Php manual entry about global statement. http://www.php.net/global.<br />

[6] Php<strong>unit</strong> and global variables. http://www.joelhainley.com/index.php/2008/<br />

04/30/php<strong>unit</strong>-and-global-variables/.<br />

[7] Global variables and php<strong>unit</strong>. http://sebastian-bergmann.de/archives/<br />

797-Global-Variables-and-PHPUnit.html.<br />

4

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!