Yesterday I had a major debugging problem when one of my tests refused to pass. It just happened that this test covered the major functionality of what I had been working on for the previous 10 hours.
This part of the code called a command line utility to fill a form in a pdf. It refused to work. It would work when I tested it on the command line; it would work when I tested it from my cygwin console; it worked when I created a unit test.
Finally I found the problem: it was the forward slashes. When you are in php, php takes care of the forward slashes for you. The same thing with the cygwin console. However, when I used the exec() command, it obviously was back in the windows world from where I am developing, so it wouldn't work.
So here is my hard earned checklist on troubleshooting command line commands in scripting languages via exec() or equivalent.
0. Does your the command string run on the native command line?
Example:
grep 'tasty pies' pgtips.txt
'grep' is not recognized as an internal or external command, operable command or batch file.
(Or our command line command complaining about lacking something, such as lack of parameters or permissions)
1. Do you have all of the arguments in your command string?
Example: exec("grep 'tasty pies' "); #Ouch! We forgot to put the directory!
2. Do you have spaces in between your command string?
Example:
$pattern = 'tasty pies';
exec('grep' . $pattern); #No spaces. The concatenated string is 'greptasty pies'. There is no such command called greptasty, that I know. Not a bad name for a unix utility, actually.
3. Does it work from the working directory?
Example:
exec("grep 'tasty pies' pgtips.txt ");
4. Does it work if you use a path to it?
Example:
exec('grep 'tasty pies' uk/tea/pgtips.txt');
5. Are the slashes correct for your os?
Example:
exec("grep 'tasty pies' uk/tea/pgtips.txt"); #This is wrong if you are working in Windows!
6. Does the user executing the script has the right permissions to do it?
Bonus:
Troubleshoot this via unit tests.
Obviously one cannot unit test the tests performed directly on the command line, but since it is only one and quickly done, it shouldn't be a big deal. The reason why you should write tests is because it will document what you have tried. Hard to crack problems makes us lose perspective, and we often try to do the same test again and again.
By writing a unit test, you will have will have it tested again and again, but one won't forget about it for a few minutes only to try it again as a possible solution later 10 minutes later. Because of this, it should reduce the troubleshooting time. In my case, I only figured the problem out once I began methodically writing tests for the scenarios that I wrote above.
I find it amazing that it took me this long to figure this one out, but here it is: if one is developing on Visual Studio, bypassing the F5 and just testing directly on the site will knock between 1 second to or 5 per test. This is especially useful if it is very apparent whether the change has worked or not by testing the functionality.
It doesn't seem like a lot, but those 5 seconds build up after repeated iterations. Also, those 5 seconds can be enough to break your concentration on what are you looking for, meaning that the true time lost could be greater is we take into account the seconds needed to refocus on the task.
By testing it this way, we only incurred the time penalty of starting the debugger when we actually need to step through the code or to debug per se.
So when the change will work or not, avoid the debugger: build and test, build and test.