Monday, September 29, 2008

Google Customer Service?

See Google Customer Service? at its new home on bradley-holt.com.

My customer service experience with Google rivals my experience with Verizon Wireless for winner of the "worst customer support possible" award. Verizon Wireless would not let me pay them more money for a service with more minutes without forcing me into a contract. After many phone calls I finally got the privilege of spending more money with them. I was able to wrangle some choice quotes from the Verizon Wireless customer service representative such as "marketing doesn't talk to customers." Apparently at Google, customer service doesn't talk to customers.

Let me start at the beginning (since that's usually a good place to start). We decided to use Google Checkout and Google Checkout Shopping cart for one of our client's projects. The reason was that they needed it done quickly, they were only selling a handful of products, and a full shopping cart seemed like overkill. One of the products they were offering was a donation on behalf of a non-profit.

Three days ago our client got an email from Google Checkout support indicating that soliciting donations is against their policies unless you are a non-profit. Google indicated that they had removed the Checkout badges from our client's AdWords ads but did not say anything about suspending their account. We immediately removed the donation item so as to reinstate the Checkout badges and not risk having the client's account suspended. At this time we verified that the the Google Checkout account was still working and had not been suspended.

Yesterday I sent an email to Google Checkout support asking if there was any way our client could collect these donations on behalf of a non-profit. I clearly indicated that we had already removed the offending item from the website. This morning I received a response that did not answer my questions, but instead said "We were unable to verify your organization's tax exempt status. As a result, your Google Checkout account has been suspended."

Our client never claimed to be a non-profit. We immediately removed the donation item in order to comply with Google Checkout policies once this issue was brought to our attention. Only after we had removed the donation item was our client's account suspended.

I immediately emailed back to support explaining everything above and asking them to reinstate the account. This is a micro-site for a nationally known brand and is part of a larger campaign. Not being able to accept orders is a big problem. In the last eight hours I have sent seventeen emails to support and have yet to receive a response. I have also posted a message to the Google Group with no official response yet. If the lack of response is because the support department is closed, then why did they suspend the account of a nationally known brand while support was closed without first double-checking that that policy violation was still in place?

We went so far as to try and call the corporate number. The absurdity of that phone call was beyond imaginable. We explained the problem and the Google representative said we needed to know the first and last name of the person we wanted to talk to. Of course, the email we had received from support about the account suspension only had a first name. They would not forward us to a department either. When we asked for the Google representative's name we were told, "I'm not authorized to give you that information." When we asked to speak to their supervisor we were told, "I'm not authorized to transfer you to a supervisor. You need to have their first name and last name." This was after we had said, "Don't you know your supervisor's name?" We were told to wait for an email reply. I'm still waiting.

Google Checkout is a service that Google offers to businesses. This is not a consumer-oriented service. It is completely ridiculous to expect businesses to use your service if this is the type of support that is offered. Google, fix your customer service - it is completely broken!

One last message for Google: I didn't take "no" for an answer from Verizon Wireless, in my opinion one of the most evil companies around. I called them again and again until they bent the rules on their asinine policy. Do you think I'm going to stop hounding the company that claims, "Don't be evil?" Wake up call: your lack of customer service for business customers is downright evil. I have been a Google evangelist for many years and this experience has been a huge slap in the face from a company that I thought was different.

Saturday, September 27, 2008

Testing Requirements with Unit Tests

See Testing Requirements with Unit Tests at its new home on bradley-holt.com.

I'm currently working on a project where the client is running their own web server that I will not have direct access to. This is actually a good thing in that it is a nice way to enforce the separation of the development and integration environments from the staging and production environments. However, how do I be sure that all of the system requirements will be met so that I can address any potential problems early on in the project? Sure, I could just give them a file with phpinfo() in it and have them send me the results. However, I plan on also shipping them unit tests for the application so why not have the requirements tested through unit tests as well?

My first thought was, since the application is being built in Zend Framework, just ship them the Zend Framework unit tests. It turns out there are a lot of unit tests and they have some heavy memory requirements. So, I decided on a simpler approach. I would run unit tests that simply tested for the requirements outlined in the Zend Framework documentation. Here are the tests:

/**
* The Requirements test case.
*
* @category Requirements
* @package Requirements
* @copyright Copyright (c) 2005-2008 Found Line, Inc. (http://www.foundline.com/)
* @license http://www.foundline.com/legal/software-license/ New BSD License
*/
class Requirements extends PHPUnit_Framework_TestCase
{

public function testVersionOfPhpIs5Dot1Dot4OrLater()
{
$this->assertTrue(version_compare(PHP_VERSION, '5.1.4', '>='));
}

public function testVersionOfPhpIs5Dot2Dot3OrLater()
{
$this->assertTrue(version_compare(PHP_VERSION, '5.2.3', '>='));
}

/**
* @dataProvider requiredExtensions
* @param string $extensionName the name of the extension for which to test
*/
public function testExtensionLoaded($extensionName)
{
$this->assertTrue(extension_loaded($extensionName));
}

public static function requiredExtensions()
{
return array(
'apc' => array('apc'),
'bcmath' => array('bcmath'),
'bitset' => array('bitset'),
'ctype' => array('ctype'),
'curl' => array('curl'),
'dom' => array('dom'),
'gd' => array('gd'),
'hash' => array('hash'),
'ibm_db2' => array('ibm_db2'),
'iconv' => array('iconv'),
'interbase' => array('interbase'),
'json' => array('json'),
'libxml' => array('libxml'),
'mbstring' => array('mbstring'),
'memcache' => array('memcache'),
'mime_magic' => array('mime_magic'),
'mysqli' => array('mysqli'),
'oci8' => array('oci8'),
'pcre' => array('pcre'),
'pdo' => array('pdo'),
'pdo_mssql' => array('pdo_mssql'),
'pdo_mysql' => array('pdo_mysql'),
'pdo_oci' => array('pdo_oci'),
'pdo_pgsql' => array('pdo_pgsql'),
'pdo_sqlite' => array('pdo_sqlite'),
'posix' => array('posix'),
'reflection' => array('Reflection'),
'session' => array('session'),
'simpleXml' => array('SimpleXML'),
'soap' => array('soap'),
'spl' => array('SPL'),
'sqlite' => array('SQLite'),
'standard' => array('standard'),
'xml' => array('xml'),
'zlib' => array('zlib'),
);
}

}

Note that I've checked for both the recommended PHP version 5.2.3 and the required PHP version 5.1.4. Also, I've tested for both hard and soft dependencies for all components. This means that many of these tests could fail and my application could still be OK. I wanted as much information as possible so that I can detect any potential problems before I write too much code. As the specific requirements for this application become clearer, I will update the test to add or remove requirements. Of course, once there is real code and unit tests these requirements tests will become irrelevant. The point is to test for the presence of these requirements before I write the code.

Running these tests with the command phpunit --testdox Requirements.php (I've actually wrapped this into a bigger test suite, but that's outside the scope of this blog post) gives me the following output on one of my development machines:

PHPUnit 3.3.1 by Sebastian Bergmann.

Requirements
[x] Version of php is 5 dot 1 dot 4 or later
[x] Version of php is 5 dot 2 dot 3 or later
[x] Extension loaded with data set "apc"
[x] Extension loaded with data set "bcmath"
[x] Extension loaded with data set "bitset"
[x] Extension loaded with data set "ctype"
[x] Extension loaded with data set "curl"
[x] Extension loaded with data set "dom"
[x] Extension loaded with data set "gd"
[x] Extension loaded with data set "hash"
[ ] Extension loaded with data set "ibm_db 2"
[x] Extension loaded with data set "iconv"
[x] Extension loaded with data set "interbase"
[x] Extension loaded with data set "json"
[x] Extension loaded with data set "libxml"
[x] Extension loaded with data set "mbstring"
[x] Extension loaded with data set "memcache"
[x] Extension loaded with data set "mime_magic"
[x] Extension loaded with data set "mysqli"
[ ] Extension loaded with data set "oci 8"
[x] Extension loaded with data set "pcre"
[x] Extension loaded with data set "pdo"
[ ] Extension loaded with data set "pdo_mssql"
[x] Extension loaded with data set "pdo_mysql"
[ ] Extension loaded with data set "pdo_oci"
[ ] Extension loaded with data set "pdo_pgsql"
[x] Extension loaded with data set "pdo_sqlite"
[x] Extension loaded with data set "posix"
[x] Extension loaded with data set "reflection"
[x] Extension loaded with data set "session"
[x] Extension loaded with data set "simple xml"
[x] Extension loaded with data set "soap"
[x] Extension loaded with data set "spl"
[x] Extension loaded with data set "sqlite"
[x] Extension loaded with data set "standard"
[x] Extension loaded with data set "xml"
[x] Extension loaded with data set "zlib"


There are a couple of potential problems to be aware of. First, PHPUnit will have to be installed on the machine that this will be tested on. This should probably only be done on the staging machine, not the production machine. Second, the CLI version of PHP often uses a different php.ini file then the CGI or ISAPI version. This means that some requirements may actually be available to your web application but they will fail the test when run at the command line.

Friday, September 26, 2008

ZendCon Highlights Presentation

See ZendCon Highlights Presentation at its new home on bradley-holt.com.

I presented highlights from ZendCon at last night's Burlington, VT PHP Users Group meeting. I've uploaded my slides for anyone who wants to take a look. The presentation uses the S5 slide show format in case you are curious.

Monday, September 22, 2008

ZendCon Highlights at PHP UG Meeting

See ZendCon Highlights at PHP UG Meeting at its new home on bradley-holt.com.

I'll be presenting some highlights from ZendCon at this Thursday's Burlington, VT PHP Users Group meeting. We'll be meeting at Draker Laboratories from 6:00 pm to 8:00 pm. Hope to see you there!

ZendCon 2008

See ZendCon 2008 at its new home on bradley-holt.com.

ZendCon 2008 wrapped up last week. This was my first time going to ZendCon and it was definitely worth it. There were over 650 people and over 60 sessions at the Santa Clara conference. I'll try to post summaries and highlights from the sessions I attended. It was a great opportunity to attended presentations from some of the most well respected people in the PHP community including Vermont's own Matthew Weier O'Phinney (Zend Technologies), Mike Naberezny (Maintainable Software), Sebastian Bergmann (eZ Systems), Derick Rethans (eZ Systems), Ben Galbraith (Ajaxian.com) , Marcus Boerger (Google), and Ben Ramsey (Schematic).

Zend Certified Engineer (ZCE) in Zend FrameworkLast Tuesday during the opening keynote Zend announced the new Zend Framework certification. I was fortunate enough to get a testing slot on Thursday morning. After reading the 214 page study guide on Wednesday I passed the test, so am now a Zend Certified Engineer (ZCE) in Zend Framework! If you plan on taking the test, I definitely recommend reading the study guide. I've been using Zend Framework since 1.0 and I'm not sure I would have passed if I hadn't read the study guide.