diff --git DrunitTestListener.inc DrunitTestListener.inc
new file mode 100755
index 0000000..c8dab28
--- /dev/null
+++ DrunitTestListener.inc
@@ -0,0 +1,62 @@
+<?php
+
+require_once 'PHPUnit/Framework.php';
+
+class DrunitTestListener implements PHPUnit_Framework_TestListener {
+
+  public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) {
+    printf(
+      "Error while running test '%s'.\n",
+      $test->getName()
+    );
+  }
+
+  public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) {
+    printf(
+      "Test '%s' failed.\n",
+      $test->getName()
+    );
+  }
+
+  public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) {
+    printf(
+      "Test '%s' is incomplete.\n",
+      $test->getName()
+    );
+  }
+
+  public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) {
+    printf(
+      "Test '%s' has been skipped.\n",
+      $test->getName()
+    );
+  }
+
+  public function startTest(PHPUnit_Framework_Test $test) {
+    printf(
+      "Test '%s' started.\n",
+      $test->getName()
+    );
+  }
+
+  public function endTest(PHPUnit_Framework_Test $test, $time) {
+    printf(
+      "Test '%s' ended.\n",
+      $test->getName()
+    );
+  }
+
+  public function startTestSuite(PHPUnit_Framework_TestSuite $suite) {
+    printf(
+      "TestSuite '%s' started.\n",
+      $suite->getName()
+    );
+  }
+
+  public function endTestSuite(PHPUnit_Framework_TestSuite $suite) {
+    printf(
+      "TestSuite '%s' ended.\n",
+      $suite->getName()
+    );
+  }
+}
diff --git Extensions/SeleniumTestCase.php Extensions/SeleniumTestCase.php
old mode 100644
new mode 100755
index b652b51..73aa30f
--- Extensions/SeleniumTestCase.php
+++ Extensions/SeleniumTestCase.php
@@ -1,22 +1,258 @@
 <?php
 
+require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
+
 class Drunit_Extensions_SeleniumTestCase extends PHPUnit_Extensions_SeleniumTestCase {
 
+  protected $drupal_user;
+  protected $drupal_password;
+
+  /**
+   * The current user logged in using the internal browser.
+   *
+   * @var bool
+   */
+  protected $loggedInUser = FALSE;
+
   protected $captureScreenshotOnFailure = TRUE;
-  protected $screenshotPath = DRUNIT_FILEPATH_FILES_SCREENSHOTS;
-  protected $screenshotUrl = DRUNIT_URL_FILES_SCREENSHOTS;
+  protected $screenshotPath;
+  protected $screenshotUrl;
   
   protected function setUp() {
-    $this->setBrowser("*chrome");
-    parent::setUp();
+    $drunit_conf = variable_get('drunit_conf', array());
+    if (empty($drunit_conf)) {
+      $message = <<<MSG
+      \n
+      Please add the following in your settings.php file
+      \$conf['drunit_selenium_conf'] = array(
+        // Drupal user settings to be used by selenium
+        'drupal_user' => 'admin',
+        'drupal_password' => 'pass',
+        // Selenium settings
+        'sel_browser' => '*firefox',
+        'sel_browser_url' => 'http://example.com/', // url where your Drupal installation resides
+        'sel_host' => 'localhost', // hostname where the selenium server is running
+        'sel_port' => 4444,
+        'sel_timeout' => 30000,
+        'sel_speed' => 0,
+      );\n\n
+MSG;
+      exit($message);
+    }
+
+    $this->drupal_user = $drunit_conf['drupal_user'];
+    $this->drupal_password = $drunit_conf['drupal_password'];
+
+    $this->setBrowser($drunit_conf['sel_browser']);
+    $this->setBrowserUrl($drunit_conf['sel_browser_url']);
+    $this->setHost($drunit_conf['sel_host']);
+    $this->setPort($drunit_conf['sel_port']);
+    $this->setTimeout($drunit_conf['sel_timeout']);
+    $this->setSpeed($drunit_conf['sel_speed']);
   }
-  
-  public function run(PHPUnit_Framework_TestResult $result = NULL) {
-    $this->setPreserveGlobalState(FALSE);
-    $this->setBackupGlobals(FALSE);
-    $this->setBackupStaticAttributes(FALSE);
-    $this->setRunTestInSeparateProcess(TRUE);
-    return parent::run($result);
+
+  /**
+   * Adds support for *AndAjaxWait function calls.
+   * We can call methods like clickAndAjaxWait()
+   * @link http://agilesoftwaretesting.com/?p=111
+   */
+  public function __call($command, $arguments) {
+    if (preg_match('/AndAjaxWait$/', $command)) {
+      $command = str_replace('AndAjaxWait', '', $command);
+      if (is_callable(array($this, $command))) {
+        $return = call_user_func_array(array($this, $command), $arguments);
+        $this->waitForAjaxFinish();
+        return $return;
+      }
+    }
+    return parent::__call($command, $arguments);
+  }
+
+  static public function LogToC($string = "") {
+    print "$string;\n";
+  }
+
+  /**
+   * Waits until there is no more active AJAX calls or until it reaches $timeout
+   */
+  function waitForAjaxFinish($timeout = 5000) {
+    $this->waitForCondition('selenium.browserbot.getCurrentWindow().jQuery.active == 0', $timeout);
+  }
+
+  function seleniumLogout() {
+    try {
+      $this->openAndWait('/logout');
+    } catch (Exception $e) {
+
+    }
+  }
+
+  function seleniumLogin() {
+    static $tries = 0;
+    $tries++;
+    try {
+      $this->openAndWait("/user");
+      if (!$this->isElementPresent('id=edit-name')) {
+        if ($tries > 2) {
+          exit('Could not login, #edit-name form element not found.');
+        }
+        $this->seleniumLogout();
+        $this->seleniumLogin();
+        return;
+      }
+      $this->type("edit-name", $this->drupal_user);
+      $this->type("edit-pass", $this->drupal_password);
+      $this->click("edit-submit");
+      $this->waitForPageToLoad();
+    } catch (Exception $e) {
+      if ($tries > 2) {
+        exit('Could not login.');
+      }
+    }
+  }
+
+  function seleniumCreateNode($settings = array()) {
+    $settings += array(
+      'type' => 'page',
+      'edit-title' => $this->randomName(),
+    );
+    $node_add_page = "/node/add/" . str_replace("_", "-", $settings['type']);
+    unset($settings['type']);
+    $this->openAndWait($node_add_page);
+    foreach ($settings as $key => $value) {
+      $this->type($key, $value);
+    }
+    $this->clickAndWait("edit-submit");
+    $this->clickAndWait("link=Edit");
+    preg_match('/\/node\/(\d+)\/edit$/', $this->getLocation(), $matches);
+    return node_load($matches[1], NULL, TRUE);
+  }
+
+  /**
+   * Helper function. Recursively checks that
+   * all the keys of a table are present in a second and have the same value.
+   */
+  function _compareArrayForChanges($fields, $data, $message, $prefix = '') {
+    foreach ($fields as $key => $value) {
+      $newprefix = ($prefix == '') ? $key : $prefix . '][' . $key;
+      if (is_array($value)) {
+        $compare_to = isset($data[$key]) ? $data[$key] : array();
+        $this->_compareArrayForChanges($value, $compare_to, $message, $newprefix);
+      } else {
+        $this->assertEquals($value, $data[$key], t($message, array('!key' => $newprefix)));
+      }
+    }
+  }
+
+  /**
+   * Creates a node based on default settings.
+   *
+   * @param $settings
+   *   An associative array of settings to change from the defaults, keys are
+   *   node properties, for example 'title' => 'Hello, world!'.
+   * @return
+   *   Created node object.
+   */
+  protected function drupalCreateNode($settings = array()) {
+    // Populate defaults array.
+    $settings += array(
+      'body' => $this->randomName(32),
+      'title' => $this->randomName(8),
+      'comment' => 2,
+      'changed' => time(),
+      'format' => FILTER_FORMAT_DEFAULT,
+      'moderate' => 0,
+      'promote' => 0,
+      'revision' => 1,
+      'log' => '',
+      'status' => 1,
+      'sticky' => 0,
+      'type' => 'page',
+      'revisions' => NULL,
+      'taxonomy' => NULL,
+    );
+
+    // Use the original node's created time for existing nodes.
+    if (isset($settings['created']) && !isset($settings['date'])) {
+      $settings['date'] = format_date($settings['created'], 'custom', 'Y-m-d H:i:s O');
+    }
+
+    // If the node's user uid is not specified manually, use the currently
+    // logged in user if available, or else the user running the test.
+    if (!isset($settings['uid'])) {
+      if ($this->loggedInUser) {
+        $settings['uid'] = $this->loggedInUser->uid;
+      } else {
+        global $user;
+        $settings['uid'] = $user->uid;
+      }
+    }
+
+    $node = (object) $settings;
+    node_save($node);
+
+    db_query('UPDATE {node_revisions} SET uid = %d WHERE vid = %d', $node->uid, $node->vid);
+    return $node;
+  }
+
+  function drupalLogin($uid = 1) {
+    global $user;
+    $user = user_load(array('uid' => $uid));
+    $this->loggedInUser = $user;
+  }
+
+  function drupalFlushAllCaches() {
+    // Flush all caches; no need to re-implement this.
+    module_load_include('inc', 'system', 'system.admin');
+    $form = $form_state = array();
+    system_clear_cache_submit($form, $form_state);
+  }
+
+  /**
+   * Generates a random string of ASCII characters of codes 32 to 126.
+   *
+   * The generated string includes alpha-numeric characters and common misc
+   * characters. Use this method when testing general input where the content
+   * is not restricted.
+   *
+   * @param $length
+   *   Length of random string to generate which will be appended to $db_prefix.
+   * @return
+   *   Randomly generated string.
+   */
+  public static function randomString($length = 8) {
+    global $db_prefix;
+
+    $str = '';
+    for ($i = 0; $i < $length; $i++) {
+      $str .= chr(mt_rand(32, 126));
+    }
+    return str_replace('simpletest', 's', $db_prefix) . $str;
+  }
+
+  /**
+   * Generates a random string containing letters and numbers.
+   *
+   * The letters may be upper or lower case. This method is better for
+   * restricted inputs that do not accept certain characters. For example,
+   * when testing input fields that require machine readable values (ie without
+   * spaces and non-standard characters) this method is best.
+   *
+   * @param $length
+   *   Length of random string to generate which will be appended to $db_prefix.
+   * @return
+   *   Randomly generated string.
+   */
+  public static function randomName($length = 8) {
+    global $db_prefix;
+
+    $values = array_merge(range(65, 90), range(97, 122), range(48, 57));
+    $max = count($values) - 1;
+    $str = '';
+    for ($i = 0; $i < $length; $i++) {
+      $str .= chr($values[mt_rand(0, $max)]);
+    }
+    return str_replace('simpletest', 's', $db_prefix) . $str;
   }
 
 }
\ No newline at end of file
diff --git Framework/TestCase.php Framework/TestCase.php
old mode 100644
new mode 100755
diff --git drunit.drush.inc drunit.drush.inc
new file mode 100755
index 0000000..b693801
--- /dev/null
+++ drunit.drush.inc
@@ -0,0 +1,176 @@
+<?php
+
+/**
+ * @file
+ *   Drunit module drush integration.
+ */
+
+/**
+ * Implementation of hook_drush_command().
+ *
+ * @See drush_parse_command() for a list of recognized keys.
+ *
+ * @return
+ *   An associative array describing your command(s).
+ */
+function drunit_drush_command() {
+  $items = array();
+
+  $items['drunit-list'] = array(
+    'description' => "List all the available phpunits for your site.",
+  );
+
+  $items['drunit-run'] = array(
+    'arguments' => array(
+      'class' => 'PHPUnitTest to run (the class name).',
+    ),
+  );
+
+  $items['drunit-run-all'] = array(
+    'description' => "Run all PHPUnit tests.",
+  );
+
+  return $items;
+}
+
+/**
+ * Implementation of hook_drush_help().
+ */
+function drunit_drush_help($section) {
+  switch ($section) {
+    case 'drush:drunit-list':
+      return dt("List all the available phpunits for your site.");
+    case 'drush:drunit-run-all':
+      return dt("Run all PHPUnit tests.");
+  }
+}
+
+function drush_drunit_list() {
+  $classes = drunit_test_get_all_classes();
+  $rows = array(array(dt('Module Name'), dt('Class')));
+  foreach ($classes as $class) {
+    $rows[] = array(
+      $class['module_name'],
+      $class['class'],
+    );
+  }
+  drush_print_table($rows, TRUE);
+}
+
+function drush_drunit_run_all() {
+  drush_drunit_include_files();
+
+  $classes = drunit_test_get_all_classes();
+
+  foreach ($classes as $class) {
+    _drush_drunit_run_test_suite($class);
+  }
+}
+
+function drush_drunit_run() {
+  $args = func_get_args();
+
+  if (empty($args)) {
+    exit("Please specify a UnitTest.");
+  }
+
+  drush_drunit_include_files();
+
+  $drupal_root = drush_locate_root();
+  $classes = drunit_test_get_all_classes();
+
+  $listener = new DrunitTestListener();
+
+  foreach ($classes as $class) {
+    if (!in_array($class['class'], $args)) {
+      continue;
+    }
+    _drush_drunit_run_test_suite($class);
+  }
+}
+
+function _drush_drunit_run_test_suite($class) {
+  $drupal_root = drush_locate_root();
+
+  $listener = new DrunitTestListener();
+
+  $suite = new PHPUnit_Framework_TestSuite($class['class']);
+  $suite->addTestFile($drupal_root . '/' . $class['file']);
+  return PHPUnit_TextUI_TestRunner::run($suite, array(
+      'backupGlobals' => FALSE,
+      'backupStaticAttributes' => FALSE,
+      'listeners' => array($listener),
+      'colors' => TRUE,
+      'processIsolation' => TRUE,
+    )
+  );
+}
+
+function drunit_test_get_all_classes() {
+  drush_drunit_include_files();
+
+  $classes = array();
+  $files = module_rebuild_cache();
+  foreach ($files as $file) {
+    $directory = dirname($file->filename);
+    $test_files = file_scan_directory($directory, 'Test\.php$', array('.', '..', 'CVS'), FALSE, FALSE);
+    $test_files += file_scan_directory($directory . '/tests', 'Test\.php$');
+
+    foreach ($test_files as $test_file) {
+      $pre = get_declared_classes();
+      require_once $test_file->filename;
+      $post = get_declared_classes();
+
+      $classes_new = array_values(array_diff($post, $pre));
+      foreach ($classes_new as $class) {
+        if (drunit_class_extends('PHPUnit_Framework_TestCase', $class) && method_exists($class, 'setUp')) {
+          $classes[$class] = array(
+            'file' => $test_file->filename,
+            'class' => $class,
+            'module' => $file->name,
+            'module_name' => $file->info['name'],
+          );
+        }
+      }
+    }
+  }
+
+  return $classes;
+}
+
+function drush_drunit_include_files() {
+  // include PHPUnit files
+  require_once 'PHPUnit/Framework.php';
+  require_once 'PHPUnit/TextUI/TestRunner.php';
+  require_once 'PHPUnit/Extensions/SeleniumTestCase.php';
+
+  // include Drunit files
+  require_once dirname(__FILE__) . '/DrunitTestListener.inc';
+  require_once dirname(__FILE__) . '/Framework/TestCase.php';
+  require_once dirname(__FILE__) . '/Extensions/SeleniumTestCase.php';
+}
+
+/**
+ * Check if a class extends or implements a specific class/interface
+ *
+ * @param $search
+ *   The class or interface name to look for
+ * @param $className
+ *   The class name of the object to compare to
+ * @return bool
+ */
+function drunit_class_extends($search, $className) {
+  $class = new ReflectionClass($className);
+  if (FALSE === $class) {
+    return FALSE;
+  }
+  do {
+    $name = $class->getName();
+    if ($search == $name) {
+      return TRUE;
+    }
+    $class = $class->getParentClass();
+  } while (FALSE !== $class);
+  return FALSE;
+}
+
diff --git drunit.info drunit.info
new file mode 100755
index 0000000..4243d17
--- /dev/null
+++ drunit.info
@@ -0,0 +1,2 @@
+version=1
+name = Drunit
\ No newline at end of file
diff --git drunit.module drunit.module
new file mode 100755
index 0000000..b3d9bbc
--- /dev/null
+++ drunit.module
@@ -0,0 +1 @@
+<?php
diff --git tests/drunitTest.php tests/drunitTest.php
new file mode 100755
index 0000000..cd82ad1
--- /dev/null
+++ tests/drunitTest.php
@@ -0,0 +1,18 @@
+<?php
+
+class DrunitTest extends Drunit_Framework_TestCase {
+  protected function setUp() {}
+
+  public function testDrunitClassExtends() {
+    // this should evaluate to TRUE
+    $this->assertTrue(drunit_class_extends('DrunitClassExtendsDummyClass2', 'DrunitClassExtendsDummyClass'));
+    // the other way around shouldn return FALSE
+    $this->assertFalse(drunit_class_extends('DrunitClassExtendsDummyClass', 'DrunitClassExtendsDummyClass2'));
+    // FALSE
+    $this->assertFalse(drunit_class_extends('DrunitClassExtendsDummyClass3', 'DrunitClassExtendsDummyClass'));
+  }
+}
+
+class DrunitClassExtendsDummyClass extends DrunitClassExtendsDummyClass2 {}
+class DrunitClassExtendsDummyClass2 {}
+class DrunitClassExtendsDummyClass3 {}
