3

If I want to unit-test some of my javascript functions, would it be more efficient (and doable) to use the already installed PHP unit-testing framework, or should I use a javascript unit-testing framework?

EDIT: It seems I have to clarify things a bit. I'm using javascript for form validation. It seems that some logic doesn't work as I want it to be, and I thought to myself that would be a good point to begin to use unit-testing (something that came to my scope only recently). I already began to use SimpleTest on a little project of mine, but never to test logic that is generated client-side.

Now I know that SimpleTest have the possibility to emulate a browser for example. But I was wondering what other method would they be to unit-test my form validation. While I was searching for idea, I realized that there is also unit-testing framework for javascript, but after a bit of searching on some of the SE sites, I didn't find anything about use of PHP and Javascript Framework together, so I wondered how common such a situation it was, and how do other people manage in such an environment.

2
  • There are javascript and jQuery frameworks available for form validation in the browser. If you use one of those, a lot of your unit testing will already have been accomplished by someone else. Dec 20, 2010 at 16:38
  • Definitely possible. See e.g. here for phpUnit. However, things like these usually focus on on how the JavaScript interacts with the web page (e.g. you automatically click a button and then assert whether something changes in the page), not unit testing JavaScript functions. Mar 29, 2022 at 8:42

4 Answers 4

5

The short answer is no.

You cannot effectively test JavaScript with PHP. To do it effectively, you need to use JavaScript.

More than likely you will have to use a JavaScript unit testing library such as the one used for Prototype.js. Essentially, you need to be able to execute the JavaScript in browser, and get the results of the JavaScript run. You won't be able to do that from the server side (PHP).

Unit testing frameworks are most efficient and useful when you are using the same language to test as you are to write the code in. For that reason we have PHP unit testing frameworks, Java unit testing frameworks, C#/.Net unit testing frameworks, and yes, JavaScript unit testing frameworks. A big part of the reason for this is that your unit tests need to examine the results of what your code is doing in the environment where it runs. SimpleTest runs in the PHP environment, and examines to assert that your PHP functions are doing what you expect. It doesn't run directly in the client browser, but as all PHP code it runs on the server and generates HTML output.

In order to run and test JavaScript functionality--particularly when the problem might be how a one browser implements it--you need to execute and assert functionality in JavaScript. Now, you can roll your own JavaScript unit testing framework for your environment, or you can use one that already exists.

The JavaScript lives 100% on the client side. That's why you didn't see anything about running JavaScript and PHP together--just as you won't find information on Java and JavaScript together (in the same context we are talking here).

10
  • Well I'll have to beg to differ, because there is always the possibility to call dynamically a PHP script and display the result with AJAX.
    – Eldros
    Dec 20, 2010 at 16:15
  • Maybe I'm misunderstanding the question, but it looks like you are trying to unit test the JavaScript--not the server responses from AJAX. What are you trying to accomplish with the test? That the JavaScript works across different browsers? If so the JavaScript has to be executed in those browsers. Dec 20, 2010 at 16:19
  • Well I see that I need to clarify a few things, see my edit.
    – Eldros
    Dec 20, 2010 at 16:37
  • I've expanded my answer, but the conclusion hasn't changed. Dec 20, 2010 at 17:41
  • One last thing, to see if I understand the crux of your answer: Let's I've got this PHP script (not the unit-test one) that is called dynamically through an AJAX call, so it's content would be loaded in a div. To unit-test this story, I'll have to (1) unit-test the AJAX call with a javascript framework and (2) unit-test the script itself with my PHP framework, am I correct?
    – Eldros
    Dec 21, 2010 at 7:18
1

You could probably hack it in, but I can't see the end result being particularly pretty or easy to use. Are you just looking to use the PHP testing framework to report test results, or are you hoping to call the javascript via the PHP?

Personally I'd use something like QUnit; the jquery testing framework. It's very easy to use and lets you use javascript to test javascript within a browser. You can also link it into Rhino (with env.js) to allow for automated headless test runs.

1
  • See my edit for more clarification.
    – Eldros
    Dec 20, 2010 at 16:37
0

Why aren't you using Firebug? In particular there is an extension called Firesymfony that integrates PHP debugging support from the Symfony framework but there are other extensions that might be more suitable for what you are trying to do.

1
  • I use Firebug, but it hasn't the same role as a unit-testing framework. There is times where the code would run without errors, but would not behave as expected. In TTD, one write the unit-test beforehand to ensure that the developed function would do what it is supposed to do.
    – Eldros
    Dec 21, 2010 at 11:18
0

I have done something similar with javascript validation, not execution.

I use the command line tool gjslint from Google to validate javascript.

/**
 * 
 * @test
 * @dataProvider dataprovider_javascript_file
 */
public function javascript_files_are_valid ($fn){
    $dn = getcwd();
    $fn = "$dn/$fn";
    // most of these are whitespace- file-ending- and missing-semicolon flags
    $cmd1 = "gjslint --disable 131,1,2,5,10,11,300,-2 --nojsdoc --max_line_length 12000";
    $cmd .= "$cmd1 $fn";
    $flag = 1;
    $act_string = system($cmd, $flag);
    $exp_string = "1 files checked, no errors found.";
    $this->assertEquals($exp_string, $act_string, print_r("cmd: $cmd", 1));
}

public function dataprovider_javascript_file() {
    $dt->confArray = array("dirname1" => "", "dirname2" => "");
    $files = array_filter($dt->confArray, "self::getfilenames2"); 
    $files = array_map("self::val2array", $files); 
    return $files;
}

private function val2array($v){
    return array($v);
}


private function getfilenames2($var){
    //fetch js files, but not minified files
    //return preg_match('/\.js$/', $var) ; #&& ! preg_match('/\.min\./', $var);

    return preg_match('/\.js$/', $var) && ! preg_match('/\.min\./', $var);

}

Here I grab the output from the system() command and check the message string. That's a poor-man's method but it might suffice for a start.

A similar strategy would be to include the headless browser phantomjs to really execute your javascript. Then grab the output string and check that it does not contain any error messages.

I came here to look for some answers where someone might have done that, but didn't find any code so far. maybe have to write it myself.

Edit:

phantomjs-1.9.7-linux-x86_64/bin/phantomjs --web-security=false /phantomjs-1.9.7-linux-x86_64/examples/arguments.js test hello

Output:

0: /opt/smallapps/phantomjs-1.9.7-linux-x86_64/examples/arguments.js 1: test 2: a

Grab this output from the command line and check it with phpunit assertions.

example.js contains:

var system = require('system');
if (system.args.length === 1) {
    console.log('Try to pass some args when invoking this script!');
} else {
    system.args.forEach(function (arg, i) {
            console.log(i + ': ' + arg);
    });
}
phantom.exit();

Unfortunately, all this will only work with the simplest javascript files - without any dependencies to frameworks such as jQuery, or real interactions with other javascript-files that need to be embedded in a real html page, e.g. for accessing the DOM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.