From 143980b6dab8ad87c44518e5b7befb614fb83b85 Mon Sep 17 00:00:00 2001
From: wei <>
Date: Fri, 14 Jul 2006 06:56:16 +0000
Subject: Add time-tracker sample and docs. (Incomplete)
---
.gitattributes | 38 ++++
demos/quickstart/themes/PradoSoft/style.css | 58 ++++++
demos/time-tracker/index.php | 20 ++
demos/time-tracker/protected/.htaccess | 1 +
demos/time-tracker/protected/APP_CODE/BaseDao.php | 18 ++
demos/time-tracker/protected/APP_CODE/Project.php | 17 ++
.../time-tracker/protected/APP_CODE/ProjectDao.php | 76 ++++++++
.../protected/APP_CODE/TimeTrackerException.php | 14 ++
.../protected/APP_CODE/TimeTrackerUser.php | 31 +++
.../time-tracker/protected/APP_CODE/exceptions.txt | 3 +
demos/time-tracker/protected/controls/Layout.php | 7 +
demos/time-tracker/protected/controls/Layout.tpl | 45 +++++
.../time-tracker/protected/controls/TopicList.php | 8 +
.../time-tracker/protected/controls/TopicList.tpl | 27 +++
demos/time-tracker/protected/data/time_tracker.db | Bin 0 -> 16384 bytes
.../protected/pages/Docs/CreateBusinessCode.page | 127 +++++++++++++
.../protected/pages/Docs/GettingStarted.page | 67 +++++++
demos/time-tracker/protected/pages/Docs/Home.page | 10 +
.../protected/pages/Docs/Introduction.page | 64 +++++++
.../protected/pages/Docs/MoreTests.page | 140 ++++++++++++++
.../pages/Docs/UserClassAndExceptions.page | 202 ++++++++++++++++++++
.../protected/pages/Docs/UsingSQLMap.page | 210 +++++++++++++++++++++
.../pages/Docs/WritingFunctionalTest.page | 39 ++++
.../protected/pages/Docs/WritingUnitTest.page | 73 +++++++
demos/time-tracker/protected/pages/Docs/config.xml | 8 +
demos/time-tracker/protected/pages/Docs/db.png | Bin 0 -> 26879 bytes
.../protected/pages/Docs/functional_test1.png | Bin 0 -> 92502 bytes
.../protected/pages/Docs/functional_test2.png | Bin 0 -> 104726 bytes
.../time-tracker/protected/pages/Docs/preface.page | 19 ++
.../time-tracker/protected/pages/Docs/project1.png | Bin 0 -> 338441 bytes
.../protected/pages/Docs/unit_test1.png | Bin 0 -> 55855 bytes
.../protected/pages/Docs/unit_test2.png | Bin 0 -> 87439 bytes
.../protected/pages/Docs/unit_test3.png | Bin 0 -> 61923 bytes
demos/time-tracker/tests/functional.php | 10 +
.../tests/functional/HelloPradoTestCase.php | 14 ++
demos/time-tracker/tests/unit.php | 11 ++
.../tests/unit/AddUserToProjectTestCase.php | 35 ++++
.../tests/unit/CreateNewProjectTestCase.php | 90 +++++++++
.../time-tracker/tests/unit/ProjectDaoTestCase.php | 92 +++++++++
demos/time-tracker/tests/unit/ProjectTestCase.php | 15 ++
40 files changed, 1589 insertions(+)
create mode 100644 demos/time-tracker/index.php
create mode 100644 demos/time-tracker/protected/.htaccess
create mode 100644 demos/time-tracker/protected/APP_CODE/BaseDao.php
create mode 100644 demos/time-tracker/protected/APP_CODE/Project.php
create mode 100644 demos/time-tracker/protected/APP_CODE/ProjectDao.php
create mode 100644 demos/time-tracker/protected/APP_CODE/TimeTrackerException.php
create mode 100644 demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php
create mode 100644 demos/time-tracker/protected/APP_CODE/exceptions.txt
create mode 100644 demos/time-tracker/protected/controls/Layout.php
create mode 100644 demos/time-tracker/protected/controls/Layout.tpl
create mode 100644 demos/time-tracker/protected/controls/TopicList.php
create mode 100644 demos/time-tracker/protected/controls/TopicList.tpl
create mode 100644 demos/time-tracker/protected/data/time_tracker.db
create mode 100644 demos/time-tracker/protected/pages/Docs/CreateBusinessCode.page
create mode 100644 demos/time-tracker/protected/pages/Docs/GettingStarted.page
create mode 100644 demos/time-tracker/protected/pages/Docs/Home.page
create mode 100644 demos/time-tracker/protected/pages/Docs/Introduction.page
create mode 100644 demos/time-tracker/protected/pages/Docs/MoreTests.page
create mode 100644 demos/time-tracker/protected/pages/Docs/UserClassAndExceptions.page
create mode 100644 demos/time-tracker/protected/pages/Docs/UsingSQLMap.page
create mode 100644 demos/time-tracker/protected/pages/Docs/WritingFunctionalTest.page
create mode 100644 demos/time-tracker/protected/pages/Docs/WritingUnitTest.page
create mode 100644 demos/time-tracker/protected/pages/Docs/config.xml
create mode 100644 demos/time-tracker/protected/pages/Docs/db.png
create mode 100644 demos/time-tracker/protected/pages/Docs/functional_test1.png
create mode 100644 demos/time-tracker/protected/pages/Docs/functional_test2.png
create mode 100644 demos/time-tracker/protected/pages/Docs/preface.page
create mode 100644 demos/time-tracker/protected/pages/Docs/project1.png
create mode 100644 demos/time-tracker/protected/pages/Docs/unit_test1.png
create mode 100644 demos/time-tracker/protected/pages/Docs/unit_test2.png
create mode 100644 demos/time-tracker/protected/pages/Docs/unit_test3.png
create mode 100644 demos/time-tracker/tests/functional.php
create mode 100644 demos/time-tracker/tests/functional/HelloPradoTestCase.php
create mode 100644 demos/time-tracker/tests/unit.php
create mode 100644 demos/time-tracker/tests/unit/AddUserToProjectTestCase.php
create mode 100644 demos/time-tracker/tests/unit/CreateNewProjectTestCase.php
create mode 100644 demos/time-tracker/tests/unit/ProjectDaoTestCase.php
create mode 100644 demos/time-tracker/tests/unit/ProjectTestCase.php
diff --git a/.gitattributes b/.gitattributes
index 6ec23882..565f4fa6 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1066,6 +1066,44 @@ demos/sqlmap-sample/tests/PersonTest.php -text
demos/sqlmap-sample/tests/readme.txt -text
demos/sqlmap-sample/tests/run_tests.php -text
demos/sqlmap-sample/tests/sqlmap.xml -text
+demos/time-tracker/index.php -text
+demos/time-tracker/protected/.htaccess -text
+demos/time-tracker/protected/APP_CODE/BaseDao.php -text
+demos/time-tracker/protected/APP_CODE/Project.php -text
+demos/time-tracker/protected/APP_CODE/ProjectDao.php -text
+demos/time-tracker/protected/APP_CODE/TimeTrackerException.php -text
+demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php -text
+demos/time-tracker/protected/APP_CODE/exceptions.txt -text
+demos/time-tracker/protected/controls/Layout.php -text
+demos/time-tracker/protected/controls/Layout.tpl -text
+demos/time-tracker/protected/controls/TopicList.php -text
+demos/time-tracker/protected/controls/TopicList.tpl -text
+demos/time-tracker/protected/data/time_tracker.db -text
+demos/time-tracker/protected/pages/Docs/CreateBusinessCode.page -text
+demos/time-tracker/protected/pages/Docs/GettingStarted.page -text
+demos/time-tracker/protected/pages/Docs/Home.page -text
+demos/time-tracker/protected/pages/Docs/Introduction.page -text
+demos/time-tracker/protected/pages/Docs/MoreTests.page -text
+demos/time-tracker/protected/pages/Docs/UserClassAndExceptions.page -text
+demos/time-tracker/protected/pages/Docs/UsingSQLMap.page -text
+demos/time-tracker/protected/pages/Docs/WritingFunctionalTest.page -text
+demos/time-tracker/protected/pages/Docs/WritingUnitTest.page -text
+demos/time-tracker/protected/pages/Docs/config.xml -text
+demos/time-tracker/protected/pages/Docs/db.png -text
+demos/time-tracker/protected/pages/Docs/functional_test1.png -text
+demos/time-tracker/protected/pages/Docs/functional_test2.png -text
+demos/time-tracker/protected/pages/Docs/preface.page -text
+demos/time-tracker/protected/pages/Docs/project1.png -text
+demos/time-tracker/protected/pages/Docs/unit_test1.png -text
+demos/time-tracker/protected/pages/Docs/unit_test2.png -text
+demos/time-tracker/protected/pages/Docs/unit_test3.png -text
+demos/time-tracker/tests/functional.php -text
+demos/time-tracker/tests/functional/HelloPradoTestCase.php -text
+demos/time-tracker/tests/unit.php -text
+demos/time-tracker/tests/unit/AddUserToProjectTestCase.php -text
+demos/time-tracker/tests/unit/CreateNewProjectTestCase.php -text
+demos/time-tracker/tests/unit/ProjectDaoTestCase.php -text
+demos/time-tracker/tests/unit/ProjectTestCase.php -text
docs/application.xml -text
docs/specs/application.dtd -text
docs/specs/application.xsd -text
diff --git a/demos/quickstart/themes/PradoSoft/style.css b/demos/quickstart/themes/PradoSoft/style.css
index 782697ae..d7e94032 100644
--- a/demos/quickstart/themes/PradoSoft/style.css
+++ b/demos/quickstart/themes/PradoSoft/style.css
@@ -517,4 +517,62 @@ pre code
background-color:#ffffee;
font-family: "Courier New", Courier, mono;
margin: 0.2em;
+}
+
+div.tip, div.info, div.note
+{
+ border:1px solid #0cf;
+ padding:1em;
+ margin: 1em 2em;
+ background-color: #eff;
+}
+
+div.info
+{
+ border-color: #32CD32;
+ background-color: #EBFFCE;
+}
+
+div.note
+{
+ border-color: Orange;
+ background-color: #FFF5E1;
+}
+
+div b.tip
+{
+ font-size: 1em;
+ padding-right: 0.5em;
+}
+
+img.figure
+{
+ display: block;
+ margin: 1em auto;
+ background-color: White;
+ padding: 15px;
+ border: 1px solid #eee;
+}
+
+div.caption
+{
+ text-align: center;
+}
+
+table.tabular, table.tabular td, table.tabular th
+{
+ border: 1px solid #ccc;
+ border-collapse: collapse;
+ padding: 0.3em;
+}
+
+table.tabular
+{
+ margin: 1em auto;
+ width: 80%;
+}
+
+table.tabular td
+{
+ padding: 0.75em;
}
\ No newline at end of file
diff --git a/demos/time-tracker/index.php b/demos/time-tracker/index.php
new file mode 100644
index 00000000..afada2c1
--- /dev/null
+++ b/demos/time-tracker/index.php
@@ -0,0 +1,20 @@
+run();
+
+?>
\ No newline at end of file
diff --git a/demos/time-tracker/protected/.htaccess b/demos/time-tracker/protected/.htaccess
new file mode 100644
index 00000000..3418e55a
--- /dev/null
+++ b/demos/time-tracker/protected/.htaccess
@@ -0,0 +1 @@
+deny from all
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/BaseDao.php b/demos/time-tracker/protected/APP_CODE/BaseDao.php
new file mode 100644
index 00000000..f9146b59
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/BaseDao.php
@@ -0,0 +1,18 @@
+_connection = $connection;
+ }
+
+ protected function getConnection()
+ {
+ return $this->_connection;
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/Project.php b/demos/time-tracker/protected/APP_CODE/Project.php
new file mode 100644
index 00000000..ad9f7d19
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/Project.php
@@ -0,0 +1,17 @@
+
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/ProjectDao.php b/demos/time-tracker/protected/APP_CODE/ProjectDao.php
new file mode 100644
index 00000000..25a2845d
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/ProjectDao.php
@@ -0,0 +1,76 @@
+getConnection();
+ $creator = $sqlmap->queryForObject('GetUserByName', $project->CreatorUserName);
+ $manager = $sqlmap->queryForObject('GetUserByName', $project->ManagerUserName);
+ $exists = $sqlmap->queryForObject('GetProjectByName', $project->Name);
+ if($exists)
+ {
+ throw new TimeTrackerException(
+ 'project_exists', $project->Name);
+ }
+ else if(!$creator || !$manager)
+ {
+ throw new TimeTrackerException(
+ 'invalid_creator_and_manager',
+ $project->Name, $project->CreatorUserName,
+ $project->ManagerUserName);
+ }
+ else
+ {
+ $param['project'] = $project;
+ $param['creator'] = $creator->ID;
+ $param['manager'] = $manager->ID;
+ return $sqlmap->insert('CreateNewProject', $param);
+ }
+ }
+
+ public function getProjectByID($projectID)
+ {
+ $sqlmap = $this->getConnection();
+ return $sqlmap->queryForObject('GetProjectByID', $projectID);
+ }
+
+ public function addUserToProject($project, $user)
+ {
+ $sqlmap = $this->getConnection();
+ $project = $this->getProjectByID($project->ID);
+ $user = $sqlmap->queryForObject('GetUserByName', $user->Name);
+ $list = $sqlmap->queryForList('GetProjectMembers', $project);
+ $userExists = false;
+ foreach($list as $k)
+ {
+ if($k->ID == $user->ID)
+ $userExists = true;
+ }
+ if(!$project)
+ {
+ throw new TimeTrackerException(
+ 'invalid_project', $project->Name);
+ }
+ else if(!$user)
+ {
+ throw new TimeTrackerException(
+ 'invalid_user', $user->Name);
+ }
+ else if($userExists)
+ {
+ throw new TimeTrackerException(
+ 'project_member_exists', $projet->Name, $user->Name);
+ }
+ else
+ {
+ $param['project'] = $project;
+ $param['user'] = $user;
+ return $sqlmap->insert('AddUserToProject', $param);
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php b/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php
new file mode 100644
index 00000000..d715eefa
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/TimeTrackerException.php
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php b/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php
new file mode 100644
index 00000000..4b6987bd
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/TimeTrackerUser.php
@@ -0,0 +1,31 @@
+_ID; }
+ public function setID($value)
+ {
+ if(is_null($this->_ID))
+ $this->_ID = $value;
+ else
+ throw new TimeTrackerUserException(
+ 'timetracker_user_readonly_id');
+ }
+}
+
+class TimeTrackerUserException extends TimeTrackerException
+{
+
+}
+
+?>
\ No newline at end of file
diff --git a/demos/time-tracker/protected/APP_CODE/exceptions.txt b/demos/time-tracker/protected/APP_CODE/exceptions.txt
new file mode 100644
index 00000000..e948f4d0
--- /dev/null
+++ b/demos/time-tracker/protected/APP_CODE/exceptions.txt
@@ -0,0 +1,3 @@
+timetracker_user_readonly_id = Time tracker user ID is read-only.
+invalid_creator_and_manager = Unable to find time tracker usernames '{1}' and '{2}' for project '{0}'.
+project_exists = Project '{0}' already exists.
\ No newline at end of file
diff --git a/demos/time-tracker/protected/controls/Layout.php b/demos/time-tracker/protected/controls/Layout.php
new file mode 100644
index 00000000..e612d52d
--- /dev/null
+++ b/demos/time-tracker/protected/controls/Layout.php
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/demos/time-tracker/protected/controls/Layout.tpl b/demos/time-tracker/protected/controls/Layout.tpl
new file mode 100644
index 00000000..95c88fd8
--- /dev/null
+++ b/demos/time-tracker/protected/controls/Layout.tpl
@@ -0,0 +1,45 @@
+
+
+
+
+ |
+
+
+
+ |
+
We start the design with the database, the entity relationships are shown +in the diagram below.
+ +Now we can begin to create and test some business code. Let us begin +with the Project defintions. First, we add some properties or fields.
+All the fields should be self explainatory. The ManagerUserName +is the user name of the project manager. Notice that the fields +are public, later on, we can change some or all of them to be private and +provide some accessor and mutators (i.e. getters and setters). If we want +we can let the Project class inherit TComponent such +that the getters and setters can be used like properties, such as those +found in Prado.
+ +Next we want to add users to the project. For this, we start with some +unit tests. We are going to design the business logic around the concept of +Data Access Objects (DAO).
+ +So what are we doing here? First we create a new Project named +"Project 1". Then we create a new ProjectDao so we can insert new projects +and retrieve it. We assert that a project will be create sucessfully using +assertTrue($do->createNewProject(...)). We also assert that +getProjectByID(1) will return an instance of Project class +with same data (the reference may be different).
+ +If we run the above unit test case, nothing is going to pass since we have +not even defined the ProjectDao class. So lets do that first and import +the class in the tests as well.
+ +We will create a base Dao class as follows, and we save as BaseDao.php +in our APP_CODE directory.
+And finally our ProjectDao class.
+If we run the unit test again, we get an error message something like +"Fatal error: Call to undefined method ProjectDao::createNewProject() in ...". +So let us, fix this. +
+Run the unit test again, we see a different type of error now. This time +the unit test runner complians that the test fails.
+We shall see how we can make this test pass in the next section.
+There are a few pieces of tools and software needed throughout the development +of the application. First we shall setup the environment for coding and testing. We +shall from here on assume that you have access to a working installation of a web server with +PHP and possibilly a MySQL database server. The first thing to do is install Prado and some +testing tools.
+ +The minimum requirement by PRADO is that the Web server support PHP 5. + For the Time Tracker sample application, you need Prado version 3.1 or greater.
+Installation of PRADO mainly involves downloading and unpacking.
+You should at least first check that the demos bundled with the Prado distribution are + working. See the + quickstart tutorial for further instructions on running the demos. +
+ +If you encounter problems in downloading, unpacking and running the demo applications, please + visit the forum to seek help. Please + do a search on the forum first or read the PDF version of the quickstart. + The friendly and wonderful people at the forum can better assist you if you can provide as much detail regarding your problem. + You should include in your post your server configuration details, the steps you took to reproduce your problem, and any error messages encountered.
+ +Prado is bundled with a command line tool to create the necessary directory structure to run a hello world application. +The command tool prado-cli.php is a php script and can be found in the prado/framework/ directory. +To create a new application, go to your document root and type the following command in console. +
+A directory named time-tracker will be created containing the following.
+
The time-tracker directory is where we are going to put all our code for the Time Tracker application. +Since -t was passed into the prado-cli.php script, unit and functional test + skeletons are also created.
+The Time Tracker is a fully functional sample application designed to + introduce you to many of Prado's features. This guide is a step by step + walkthrough starting from installation to deployment. The Time Tracker + application is based on the + ASP.NET's Time Tracker Starter Kit. +
+ +The Time Tracker is a business web application for keeping track of hours spent +on a project, with ability to handle multiple resources as well as multiple projects.
+The functional requirements of the Time Tracker is based on the + ASP.NET's Time Tracker Starter Kit + description.
++
The Time Tracker web application requires the following software and knowledge.
+It is assumed that you are able to obtain and install the following pieces of software.
+In addition to software requirements, we assumed that you have some of the following knowledge.
+Up to this point, you should have the follow pieces of files and code.
+ class="figure" />
+
So what else can we test for at this point? A few reasonable +tests are to see what happens if the project already exists, and what if +the username does not exists.
+ +First we shall refactor our test code since much of the setup code +for the mocked connection will need to be repeated in other test assertions. +We change the test case to have these three new methods. +
+ +Our refactored test method testProjectDaoCanCreateNewProject() +is as follows.
+To test that the project already exists, we modify the mock +connection and test for an exception.
+Other test method for testing missing customer and manager users +are done similarly. At this point, the test case file looks quite large. +We shall not add more tests to this case and we should rename the file +from ProjectDaoTestCase.php to CreateNewProjectTestCase.php. + +
+In creating a new project, we need to check the following: +
It may seem very weird that there is so much code in the tests +and why we even bother to write all these test codes. Well, using the +above test code we have the following advantages.
+Of couse, the test will not be able to cover the higher interactions, such as +the user interface, so intergration or functional web test will be used later on. +
+ +So how did we come up with the above tests? We started simple, then we +ask what sort of things it should handle. We assume that the connection object +work as expect or known to be unexpected and see how the method we want to test handle +these situations.
+ +If we run the above test, we will be faced with numerous errors. First will be +that the TimeTrackerUser can not be found.
+ +Notice that the Project class contains CreatorUserName
+and ManagerUserName properties. So at some point we
+are going to need at least one User class. We shall name the class as
+TimeTrackerUser and save it as APP_CODE/TimeTrackerUser.php
+
We enforce that the ID of the user to be read-only once it has been +set by throwing a custom exception. Prado's exception classes +uses a string key to find a localized exception string containing more +detailed description of the exception. The default exception messages +are stored in the framework/Exceptions/messages.txt. This +file location can be changed by overriding the getErrorMessageFile() +method of TException class. We define a custom exception class +for all Time Tracker application exceptions as TimeTrackerException +and save the class as APP_CODE/TimeTrackerException.php.
+ +We then create a exceptions.txt file in the APP_CODE +directory with the following content.
+ +Additional parameters passed in the exception constructor can be +added the message string using {0} as the first additional parameter, +and {1} as the second additional parameter, and so on. +For example, suppose we want to raise the follow exception. +
+ +The exception error message in exceptions.txt may contain something like:
+From the unit test code, we can pretty much see what the implementation +for createNewProject() will look like.
+ +Before proceeding with write the code to pass the test in the previous section, we shall +make a design decision. We shall use SQLMap as our data access layer. Note +that SQLMap is only available offically in Prado 3.1 or later.
+ +SQLMap is an PHP implemenation of an Object/Relational +data mapper. SQLMap has the following basic features: +
SQLMap can be seen as a generic data mapper, rather than an +Object Relational Mapping (ORM) solution.
+ +The SQLMap API consists of the following methods. See the SQLMap manual +for further details.
+ +Back to our ProjectDao class, for testing we shall write the code +assuming we have an SQLMap client instance. The SQLMap client or connection +will be mocked or faked using a proxy. Later on, we shall extend our tests, +to become an intergration test, to include +a test database connection.
+ +We can test the ProjectDao using mock objects (see SimpleTest documentation +regarding mock objects) or using a real database connection. In PHP version +5.0.x, the sqlite database client is bundled by default. For version 5.1 or later +the sqlite database client is available as an extension. We shall use a sqlite +database to conduct our unit tests because the database can be restored to +the orginal state by just reloading the orginal database file.
+ +First, let us define the database table for projects.
+The corresponding SQLite query to create the table is given below.
+ +At this point, we have said nothing about databases. To create some unit tests +for the ProjectDao class, we are not going to use real database connections +but using a Mocked TSqlMapper. We modifiy the test as follows. +
+The test code looks slight more complicated because later on we want to +test the same assertions against some real data.
++In the first two lines above, we simply import the business code and the TSqlMapper class. +We generate a MockTSqlMapper, a mock class or TSqlMapper using +Mock::generate('TSqlMapper'). The method Mock::generate() is available from +the SimpleTest unit testing framework. An instance of MockTSqlMapper +will be used as our test connection for the DAO objects. This allows us to interogate the +internal workings of our ProjectDao class. +
+ +In the setup() (this method is called before every test method), we create an instance of +ProjectDao and set the connection to an instance of MockTSqlMapper. +
+ +So how do we test the internal workings of the ProjectDao createNewProject method? +First, we assume that the connection object will perform the correct database insertion and queries. +Then, we set the return value of the MockTSqlMapper instance to return what we have assumed. +In addition, we expect that the TSqlMapper method queryForObject is called only once with +the parameters we have assumed (e.g. $project). See the SimpleTest tutorial for further details regarding +unit testing with Mocks. +
+ +In our assertions and expectations, we have
+
We now run the unit tests, we see that there are some failures or errors. Since we
+have not created any code in ProjectDao that performs what we want, the tests will fail.
+So lets make these test pass, we add some code to ProjectDao class.
+
+
If we run the unit tests again, we should see a green bar indicating that the tests have passed. +We can now proceed further and add more tests. Of course, the above test does not cover many +conditions, such as, what happens if the project already exists?, the details of these +tests is the subject of the next section. The full test suite can be found in the source. +
+In addition to unit testing, we shall also do some functional +testing or web testing. Functional tests are, in this case, basically automated tests that will +interact with the overall web application, as if it was the user, while checking the output for correctness. +The functional test tool we shall use here is based on Selenium where the test cases can be written and run using PHP and SimpleTest. +
+Save the code as HelloPradoTestCase.php in the document_root/time-tracker/tests/functional/ +directory.
+ ++Functional test cases are written very similar to unit test cases. The method such as +open($url) are those found in Selenium. All the methods available in Selenium are available. +
+ +Point your browser to your development server's unit test case runner, e.g.
+ http://web-server-address/time-tracker/tests/functional.php. You should see the following
+
+
Clicking on the All button, you should see
+
+
Unit testing is a useful tool when we want to start to test + our individual business logic classes. + The tests/unit directory will be used to hold the unit test cases and tests/functional directory +to hold the function test cases. +
+ +We will start be writing a very simple unit test case.
+Save the code as ProjectTestCase.php in the document_root/time-tracker/tests/unit/ +directory.
+ +Point your browser to your development server's unit test case runner, e.g.
+ http://web-server-address/time-tracker/tests/unit.php. You should see the following
+
+
Clicking on the ProjectTestCase.php like, you should see
+
+
Obviously, we need create the class Project, so lets define the class.
+Save the above code as time-tracker/protected/pages/APP_CODE/Project.php. + Where the APP_CODE directory will contain most of your business logic code for the Time Tracker application.
+We also need to add the following line in our test case so as to include the Project class file when running the tests.
+ ++The statement Prado::using('Application.APP_CODE.Project') basically +loads the Project.php class file. It assumes that a class name Project has filename Project.php. +For futher details regarding Prado::using can be found in Prado Namespaces documentation. +
+ +Run the unit test runner again, we see that the test has passed.
+
+
+Later on, we shall write more test cases. See the SimpleTest documentation for detailed tutorial on writing test cases.
+ +This documentation is complete walk-through guide detailing the +steps involved in implementating of the Prado Time Tracker web application. +
+The guide is intended for readers who has some experience +using PHP version 5 and some basic concepts of Object-Oriented application +design. The guide will assume that the reader understands the primary concepts +of class, methods, class inheritance, and other basic features offered by PHP +version 5 or later.
+Readers are encouraged to ask questions as the forum regarding any +particular aspect of this documentation. Comment and constructive criticisms +are most welcome. Questions and comments may be directed at +http://www.pradosoft.com/forum/. +
+ +