Dienstag, 12. Juli 2011

How To: Setting up your continuous integration server for PHP projects...

STATUS: WORK IN PROGRESS

To make short things shorter: this gonna be a long post.

In this post want to describe how to set up a continuous integration server or environment. in the same way i set it up for myself, so this post ist also (maybe mainly) a reminder to myself.

Actually, there are two widely use CI implementations for PHP projects used:

  • phpUnderControl, an extension for cruise control
  • jenkins, the open source fork moved out of formally known hudson ci server


Both implementations are java based systems, which brings in the mainly functionality of a build system for CI.
More details should be taken from the project websites.

I'm going to describe the set up with both implementations. Why? You could run only the one of them you need, or both if you think it's cool. The other point is, the decision which one you prefer should not depend on how easy one solution is to install. Use the one which best fits your needs. So both are described here, test them, and give feedback to the maintainers if you are happy or unhappy with it.

The CI Server covers the following build and software tools:

  • phpunit
  • php_codebrowser
  • phploc
  • phpcpd
  • selenium
  • php_depend
  • php_codesniffer
  • php_pmd
  • phpdcd


I've tried to use headlines for each part. Some parts are used for both implementation, some are not. These parts have the used implementation in the headline.

For usual, i install optional software in the /opt directory. Replace this directory with your own if you prefer another directory, for example /usr/local

1. The requirements
First, i've set up a System with actually debian version (squeeze). I'm alwys installing debian from the smaller netboot.iso and install all packagaes via aptitude, not via the install dialogs, where it asks if you plan a web server, dns server and so on.
(Just because i just had some troubles with these pre defined package sets in history. Thats why i'm reloading apache configuration changes always with restart instead of reload, too. If you want to know why, ask for it.)
For now, squeeze is the stable debian release.
After installation always my first packages i'm going to install are less, wget, ssh.

2. Who knows the Java and sex practise comparison?
For both implementations, we need Java. the most uncomplicated Java implementation on my way as a developer isbuild by Sun. So i suggest to use the Sun Java implementation. But this is only my opinion. If you think different, its your way. This how to covers my way.
To take advantage of debians packages system, we change the used repositories.
Change your /etc/apt/sources.list as follows:
sudo vi /etc/apt/sources.list
# deb http://ftp.de.debian.org/debian/ squeeze main

deb http://ftp.de.debian.org/debian/ squeeze main contrib non-free
deb-src http://ftp.de.debian.org/debian/ squeeze main contrib non-free

deb http://security.debian.org/ squeeze/updates main contrib non-free
deb-src http://security.debian.org/ squeeze/updates main contrib non-free

# squeeze-updates, previously known as 'volatile'
deb http://ftp.de.debian.org/debian/ squeeze-updates main contrib non-free
deb-src http://ftp.de.debian.org/debian/ squeeze-updates main contrib non-free
Fire
sudo aptitude update
to bring your package lists up to date.

3. Anything else?
There are now some packages which we need to install.
sudo aptitude install sun-java6-jre ant ant-optional rake php-pear php5-dev make php5-curl php5-imagick sun-java6-jdk subversion subversion-tools postgresql mysql-server php5 php5-mysql php5-pgsql php5-sqlite git unzip
- sun-java6-jre and sun-java6-jdk are required for jenkins and cruisecontrol and also for selenium.
- ant ant-optional are used for the build process of a project and also selenium startup
- rake there is another way to start up selenium with rake
- php-pear php5-dev make php5-curl php5-imagick php5 are required for installing xdebug via pecl and the PHP quality assurance tools from pear
- subversion subversion-tools git to checkout project sources PHP quality assurance tools
- php5-mysql php5-pgsql php5-sqlite postgresql mysql-server are optional for project for example

4. [phpUnderControl] Selenium Grid standalone
If you plan to take advantage of frontend tests via selenium (and you should do it), we use selenium grid. With grid, we can manage multiple browser on multiple clients. This speed up tests a lot.
cd /opt
wget http://release.seleniumhq.org/selenium-grid/selenium-grid-1.0.8-bin.zip

unzip selenium-grid-1.0.8-bin.zip

cd selenium-grid-1.0.8

ant sanity-check
You can test the functionality by starting a hub:
ant launch-hub
If no error occures, stop selenium with ctrl^c. With rake you can easily start selenium grid as deamon in background. You need a pid subdirectory in the selenium directory.
mkdir pid
Start the daemon with
rake hub:start BACKGROUND=true
You can stop the deamon with a post to the selenium lifecycle manager
wget -q -t1 --post-data action=shutdown http://localhost:4444/lifecycle-manager
If you need to pass arguments to selenium, you can pass them to the rake start command
rake hub:start BACKGROUND=true SELENIUM_ARGS="-multiWindow -debug"
Both, start and stop command, can easily be taken to configura a start--stop script in /etc/init.d/.
vi /etc/init.d/selenium-grid
#!/bin/bash

case "$1" in
  start)
    rake hub:start BACKGROUND=true SELENIUM_ARGS="-multiWindow -debug"
    ;;
  stop)
    wget -q -t1 --post-data action=shutdown http://localhost:4444/lifecycle-manager
    ;;
  *)
    echo "Usage: $SCRIPTNAME {start|stop}" >&2
    exit 3
    ;;
esac

exit 0
chmod +x /etc/init.d/selenium-grid
Thats it. Until now, we have a selenium hub, but the test should run on remote controls. Instructions for remote controls are described later.

The concepts of selenium grid are explained on the projects website http://selenium-grid.seleniumhq.org/

5. The PHP tools
Currently, the most used PHP tools for quality assurance by myself are



Except Xdebug, all tools can be installed with pear.
sudo pecl install xdebug

sudo pear channel-discover pear.phpunit.de

sudo pear channel-discover components.ez.no

sudo pear channel-discover pear.symfony-project.com

sudo pear channel-discover pear.phpmd.org

sudo pear channel-discover pear.pdepend.org

sudo pear upgrade-all

sudo pear install --alldeps phpunit/PHPUnit

sudo pear install pdepend/PHP_Depend

sudo pear install phpmd/PHP_PMD

sudo pear install phpunit/phploc

sudo pear install PHP_CodeSniffer

sudo pear install phpunit/phpcpd
If you want to know which packages are available on a channel, try pear remote-list -c phpunit for example.

6. [phpUnderControl] Never gonna give you up...
The installation of phpUnderControl works easy with the pear installer:
sudo pear channel-discover pear.phpundercontrol.org

sudo pear install --alldeps phpuc/phpUnderControl-beta
PhpUnderControl is an extension for Cruise Control (current latest version is 2.8.4). So the next step:
sudo cd /opt

sudo wget http://downloads.sourceforge.net/project/cruisecontrol/CruiseControl/2.8.4/cruisecontrol-bin-2.8.4.zip

sudo unzip cruisecontrol-bin-2.8.4.zip

sudo mv cruisecontrol-bin-2.8.4 cruisecontrol

sudo phpuc install /opt/cruisecontrol

sudo useradd cruisecontrol

sudo chown -R cruisecontrol cruisecontrol
You can now start your Cruise Control and phpUnderControl instance with
sudo /opt/cruisecontrol/cruisecontrol.sh
and stop the instance with
wget http://localhost:8000/invoke?operation=halt&objectname=CruiseControl+Manager%3Aid%3Dunique
There is an example of a startup script I often use. I changed the port cruise control runs on to get no conflicts with jenkins later:
vi /etc/init.d/cruisecontrol
#!/bin/sh
#content of /opt/cruisecontrol/init script
# chkconfig: 345 99 05
# description: CruiseControl build loop (see /home/tools)

# CruiseControl Unix Startup Script Version 2.1
#
# based on http://confluence.public.thoughtworks.org/display/CC/RunningCruiseControlFromUnixInit
# adapted for multiple projects
# also based on the file attached to the above page created by Jerome Lacoste

#
# CruiseControl startup: Startup and kill script for Cruise Control
#


###################################################################################################
# USER CONFIGURATION
#
# Fill in these values for your Cruise Control setup

# What user will Cruise Control run as?  The user will need permission to write and modify files
# in the next entries.
CC_USER=cruisecontrol


# Where is the CC startup script located?
CC_INSTALL_DIR=/opt/cruisecontrol

# In what directory is the config.xml file located for CC?
# default: CC_WORK_DIR=$CC_INSTALL_DIR
CC_WORK_DIR=$CC_INSTALL_DIR

# Where will the cruisecontrol.log file be located?
# default: CC_LOGFILE_DIR=$CC_INSTALL_DIR
CC_LOGFILE_DIR=$CC_INSTALL_DIR


#######################
# ENVIRONMENT ADDITIONS

# Add environement variables here that are needed by your build.
# example:
export JAVA_HOME=/usr
#
# or like this for local variables ONLY used in this file:
#  JAVA_HOME=/usr/local/java


# Add path to additional executables needed for project build.  See PATH entry below for base config.
# No additional action taken when blank.
PATH_ADDITIONS=



##############################
# CRUISE CONTROL PORT SETTINGS

# Port for Jetty reporting application.  You can access it by going to http://localhost:8080
# default CC_WEBPORT=8080
CC_WEBPORT=8081

# JMX port for webapp and Java Management eXtensions (JMX).  You can access it by going to http://localhost:8080
# Change only if this port is in use as the webapp will also need modification.
# default CC_JMXPORT=8082
CC_JMXPORT=8082

# RMI port for control via Java's Remote Management Interface (RMI)
# Leave blank to disable.
CC_RMIPORT=



###################################################################################################
# DO NOT MODIFY ENTRIES BELOW THIS LINE

NAME=cruisecontrol
DESC="CruiseControl - continuous integration build loop"


PATH=/sbin:/usr/sbin:/usr/bin:/bin
# add additions if variable has text defined
if [ -n "$PATH_ADDITIONS" ]; then
    PATH=$PATH_ADDITIONS:$PATH
fi
export PATH


CC_DAEMON=$CC_INSTALL_DIR/cruisecontrol.sh

CC_CONFIG_FILE=$CC_WORK_DIR/config.xml

CC_LOG_FILE=$CC_LOGFILE_DIR/cruisecontrol.log

CC_COMMAND="$CC_DAEMON -configfile $CC_CONFIG_FILE -webport $CC_WEBPORT -jmxport $CC_JMXPORT -rmiport $CC_RMIPORT"

# overwrite settings from default file
if [ -f /etc/default/cruisecontrol ]; then
  . /etc/default/cruisecontrol
fi

# does the executable exist?
test -f $CC_DAEMON || (echo "The executable $CC_DAEMON does not exist!" && exit 0)

if [ `id -u` -ne 0 ]; then
        echo "Not starting/stopping $DESC, you are not root."
        exit 4
fi

# Get the PID output from the startup script
if [ -f $CC_INSTALL_DIR/cc.pid ]; then
 CC_PID=`cat $CC_INSTALL_DIR/cc.pid`
else
 echo "No cc.pid file found.  CC process may not be controllable from this script!"
fi


case "$1" in

  'start')
    cd $CC_INSTALL_DIR
    #echo "CC environtment at startup" > cc.startup.env
    #env >> cc.startup.env
    su $CC_USER -c "/bin/sh -c \"$CC_COMMAND >> $CC_LOG_FILE 2>&1\"" & RETVAL=$?
    echo "$NAME started with jmx on port ${CC_JMXPORT}"
    ;;

  'stop')
    if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
     kill -9 ${CC_PID}
      $0 status
      RETVAL=$?
    else
      echo "$NAME is not running"
      RETVAL=1
    fi
    ;;

  'status')
    if [ -n "$CC_PID" ] && ps -p ${CC_PID} > /dev/null ; then
      echo $NAME \(pids $CC_PID\) is running
      RETVAL=0
    else
      echo "$NAME is stopped"
      RETVAL=1
    fi
    ;;

  'restart')
    $0 stop && $0 start
    RETVAL=$?
    ;;

  *)
    echo "Usage: $0 { start | stop | status | restart }"
    exit 1
    ;;
esac
#echo ending $0 $$....
exit 0;
chmod +x /etc/init.d/cruisecontrol
Now you can start and stop your CI instance with
/etc/init.d/cruisecontrol start
/etc/init.d/cruisecontrol stop
The webserver needs a few seconds to come up, so don't be eager and breathe deeply, then fire up your browser.

Thats it! For now...

7. [jenkins] together forever...
Parts in this step are taken from http://jenkins-php.org/ by Sebastian Bergmann. He also created the php-template project used later.

Jenkins can be installed with use of a repository:
sudo wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
sudo echo "deb http://pkg.jenkins-ci.org/debian binary/" > /etc/apt/sources.list.d/jenkins.list
sudo aptitude update
sudo aptitude install jenkins
Thats it! Jenkins listens by default on port 8080.

To get useful results in the jenkins instance, we use some plugins, installed by the client tool jenkins provides:
wget http://localhost:8080/jnlpJars/jenkins-cli.jar
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin checkstyle
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin clover
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin dry
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin htmlpublisher
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin jdepend
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin plot
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin pmd
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin violations
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin xunit
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin redmine

java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin collapsing-console-sections
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin iphoneview
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin analysis-core
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin analysis-collector
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin selenium
java -jar jenkins-cli.jar -s http://localhost:8080 install-plugin piwikanalytics

java -jar jenkins-cli.jar -s http://localhost:8080 safe-restart

8. [phpUnderControl] The build.xml file




 

 
  
  
  
  
  
  

  
  
  
  
  
  
 

 
  
    
  
 

 
  
   
    
    
   
   
   
   
   
  
 
 

 
  
   
  
 

 
  
   
  
 

 
  
   
  
 

 
  
   
  
 

 
  
   
  
 

 
  
   
  
 

 
  
   
  
 

 


9. [phpUnderControl] cruise control config.xml


        
                
                        
                
                
                
                        
                
                
                        
                
                
                        
                 
                
                        
                 
                
                         
                        
                        
                        
                        
                 
        

Donnerstag, 14. April 2011

Selenium Grid and Linux Debian Squeeze

This is just a quick reminder how to install or extend your (and ours) development environment with selenium grid.

First of all, set up a fresh debian installation (actually "Squeze" 6.0.1).

First step is to install Java JRE and Ant. Mostly i'm using Sun Java JRE, so first we need to add the non-free target to our sources.list:
/etc/apt/sources.list:
deb http://ftp.de.debian.org/debian/ squeeze main contrib non-free
deb-src http://ftp.de.debian.org/debian/ squeeze main contrib non-free

deb http://security.debian.org/ squeeze/updates main contrib non-free
deb-src http://security.debian.org/ squeeze/updates main contrib non-free

# squeeze-updates, previously known as 'volatile'
deb http://ftp.de.debian.org/debian/ squeeze-updates main contrib non-free
deb-src http://ftp.de.debian.org/debian/ squeeze-updates main contrib non-free

Ant is needed by selenium grid.

Now we can install Java JRE and Ant:
sudo aptitude update
sudo aptitude install sun-java6-jre ant ant-optional zip rake
rake is optional, but the easiest way to run hub and remote controls in background

Next we fetch selenium grid and extract the package:
cd /opt
wget http://release.seleniumhq.org/selenium-grid/selenium-grid-1.0.8-bin.zip
unzip selenium-grid-1.0.8-bin.zip
cd selenium-grid-1.0.8
Now we are able to test and start selenium and continue with testing;
ant sanity-check
mkdir pid
rake hub:start BACKGROUND=true
The Hub starts listening on port 4444 by default. To kill the hub, just send a HTTP POST request:
wget -q -t1 --post-data action=shutdown http://localhost:4444/lifecycle-manager
so long,

cheers!

Mittwoch, 6. April 2011

Linux, PHP (and Zend Framework) and MS SQL Server

As mentioned in my previous post Mac OS X, PHP, Zend Server CE, FreeTDS and MS SQL setting up a database connection to Microsoft SQL Server is quite easy.

In the case you are not using Zend Server or you are on Linux (Debian, Ubuntu, SuSE, RedHat, Fedora, Gentoo or one of the other distributions) i am going to show an easy way to connect to a Microsoft SQL Server (SQL Server 2005 Standard Edition x64 in my case, but this also works for all other actual supported SQL Server Versions from Microsoft). In my examples I use Ubuntu 10.10.

First step is installing php via the distributions package and repository system, aptitude or apt-get in my case with Ubuntu or any other Debian based distribution.
sudo aptitude install libapache2-mod-php5 php5
After the installation process is done, i have to restart the apache to getting the php5 module to work. Its easily done by
sudo /etc/init.d/apache restart
Testing the successful installation is easy by creating a index.php in the Apache document root.
sudo vi /var/www/index.php
index.php:
phpinfo();

You should see your php informations when browsing to http:///

Next step is the database connectivity:

On Linux, the used PDO Module for MS SQL Connections is dblib.
Sometimes the package is called dblib, sometimes sybase, and on ubuntu there is a virtual package php5-mssql

sudo aptitude install php5-mssql
Reload the Webserver configuration:
sudo /etc/init.d/apache2 reload
And check if the module is correctly loaded:
php -i | grep MSSQL  # should print MSSQL Support => enabled
php -i | grep PDO # should print PDO Driver for FreeTDS/Sybase DB-lib => enabled

At this point, you are able to connect to a MS SQL Server. But there are several issues with this type of connection:

  • Date Format (depends on user settings of connected database user)
  • UTF-8 Support (there is an option for the connection string to solve it)
  • binary and (long) text data

So the next step is configuring freeTDS (details of configuration can be found on the freeTDS User Guide)

the date time formatting:
/etc/freetds/locales.conf:
[default]
    date format = %Y-%m-%d %H:%M:%S.%z
the database connection settings
/etc/freetds/freetds.conf:
[mydbhost]
        host = your database hostname or ip
        tds version = 8.0
        # text size don't need to be such a high value, its just an example
        text size = 4294967295
        client charset = UTF-8
example script
/var/www/index.php:
try
 {
  $dbh = new PDO('dblib:host=yourdbhost;dbname=databasename;', 'username', 'password');
  echo "Yeaha!";
  $stmt = $dbh->prepare("SELECT column_xyz FROM table_xyz");
    $stmt->execute();
    while ($row = $stmt->fetch()) {
          // the returned values are UTF-8 encoded
          var_dump($row);
    }
    unset($stmt);
    unset($dbh); 
 }
 catch (PDOException $e)
 {
  die($e);
 }

At least, we are going to connect to the database with zend frameworks db adapter:

Note: Example here is done by ubuntu repository package for zend framework, but this version may be outdated (surely it is ;-)). grab the latest version from http://framework.zend.com
install zend framework:
sudo aptitude install zend-framework zend-framework-bin
be sure to have the zend framework library path in your include dirs.
sudo vi /etc/php5/conf.d/zend-framework.ini
[Zend]
include_path=${include_path} ":/usr/share/php/libzend-framework-php"

cd /var/www
sudo zf.sh create project /var/www/ zftest
sudo zf.sh configure db-adapter "adapter=Pdo_Mssql&host=mydbhost&dbname=mydbname&username=myusername&password=mypassword&pdoType=dblib"
sudo vi application/controllers/IndexController.php
Be sure you include pdoType=dblib in your connection string, otherwise you got an error similar to "The mssql driver is not currently installed".

Edit the indexAction() method content to test connection:
$db = $this->getFrontController()
            ->getParam('bootstrap')
            ->getResource('db');

        $result = $db->fetchAll("SELECT * FROM myexampletable");
        var_dump($result);

And move your browser of choice to http://<your_ip_here>/public/.

You are done! Congratulations...

Montag, 10. Januar 2011

Mac OS X, PHP, Zend Server CE, FreeTDS and MS SQL

This post handles the configuration of a database connection from Mac OS X (Snow Leopard) and Microsoft SQL Server 2005/2008.

By default, you can connect to a SQL Server from Mac OS X PHP with pdo_dblib.
But for my needs, i had trouble with the following points:
  • troubles in correct displaying or saving of special characters like äöü in german or else in cause of UTF-8 charset and database collation
  • differences in returning datetime values, also depending on settings for the connecting user of the database
  • returning text and binary fields, espacially with large content
A solution to the first point is to add the client charset encoding to the DSN connection string:
header('Content-Type: text/html; charset=UTF-8');
try
 {
  $dbh = new PDO('dblib:host=192.168.1.1;dbname=databasename;charset=utf8', 'username', 'password');
  echo "Yeaha!";
  $stmt = $dbh->prepare("SELECT column_xyz FROM table_xyz");
    $stmt->execute();
    while ($row = $stmt->fetch()) {
          // the returned values are UTF-8 encoded
          var_dump($row);
    }
    unset($stmt);
    unset($dbh); 
 }
 catch (PDOException $e)
 {
  die($e);
 }
To solve all points, the easiest way is to use FreeTDS via unixODBC. The following steps describe the installation and configuration.
Requirements:
  • installed PHP Stack (e.g. Zend Server or Mac OS X own...) in latest version (5.3.3 at the moment of writing)
  • all links and descriptions are made for Mac OS X 10.6 (Snow Leopard)
1. Installing XCode

For the MacPorts installation we need XCode be installed. You need a registered AppleID for Apple's developer site. Grab it from the Apple developer website here Xcode 3.2.5 and iOS SDK 4.2. Take a coffee, its about 3.52 GB in size...
After downloading, just follow the instructions from the installer.

2. Installing MacPorts

Get the MacPorts installation package from the website Macports for Snow Leopard and follow the install instructions. After this, open up a Terminal session and run the selfupdate command to update the package repository.
sudo port -v selfupdate
If you get an error like "-sh: port: command not found" add the path /opt/local/bin to your PATH environment variable. edit your ~/.bash_profile file and add the line
export PATH=$PATH:/opt/local/bin
After you started a new shell, you are able to run the port command without giving the full path. Re-run the selfupdate command above.

3. Installing unixODBC

Now we install the unixodbc package (with all dependencies) with
sudo port install unixodbc
There's nothing special here.

4. Installing FreeTDS

ATTENTION: If you are using Zend Server (or Zend Server CE) you do not need to install FreeTDS, as Zend Server comes with it's own version. You just have to pay attention on the note in the place of your configuration files for FreeTDS.

The next step is the installation of FreeTDS. As some MacPorts packages came along with several so called variants, we have to give the port install command the variant as parameter which we want to install

sudo port install freetds +odbc +mssql

This installs FreeTDS with unixODBC and dblib/MS SQL Server support. We can check the installation with tsql -C. This should return somwthing similiar to this:
Compile-time settings (established with the "configure" script)
                            Version: freetds v0.82
             freetds.conf directory: /opt/local/etc/freetds
     MS db-lib source compatibility: yes
        Sybase binary compatibility: no
                      Thread safety: yes
                      iconv library: yes
                        TDS version: 8.0
                              iODBC: no
                           unixodbc: yes

5. Configure unixODBC and FreeTDS

The configuration needs four files. Samples of these files are installed in /opt/local/etc/.

/opt/local/etc/odbc.ini
[MyMSSQLServer]
Driver          =       FreeTDS
Description     =       My Desription
Servername      =       MyMSSQLServer
/opt/local/etc/odbcinst.ini
[FreeTDS]
Driver  = /opt/local/lib/libtdsodbc.so
/opt/local/etc/freetds/freetds.conf
[MyMSSQLServer]
        host = DB_SERVER_ADDRESS_OR_NAME
        port = PORT
        tds version = 8.0
        encryption = request
        client charset = UTF-8
        text size = 2147483647
/opt/local/etc/freetds/locales.conf
[default]
    date format = %Y-%m-%d %H:%M:%S.%z

[de_DE]
    date format = %Y-%m-%d %H:%M:%S
    language = Deutsch
ATTENTION: For Zend Server (and Zend Server CE) you have to save or better link your freetds.conf and locales.conf configuration files to the zend etc directory in /usr/local/zend/etc/.

6. Testing connection

We testing the connection to a sample database as configured above with the installed unixODBC tools isql and with PHP after this.

Testing with tsql:
On Mac OS X, you sometimes need to set your LC_ALL environment variable. On a new, fresh installed system on another installation i do not need to set this. Attention, FreeTDS needs UTF-8 in uppercase letters. A sign to this is when getting 20017 and 20002 errors in your tsql command.
export LC_ALL="de_DE.UTF-8"
Testing the connection:
tsql -S MyMSSQLServer -U username -P password
Testing with PHP:
Change line no 4 from the first code snippet on this site with the following
$dbh = new PDO('dblib:host=MyMSSQLServer', 'username', 'password');