CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 1.3 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.3
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Classes

  • AclBase
  • AclBehavior
  • AclComponent
  • AclNode
  • AclShell
  • Aco
  • AcoAction
  • AjaxHelper
  • ApcEngine
  • ApiShell
  • App
  • AppController
  • AppHelper
  • AppModel
  • Aro
  • AuthComponent
  • BakeShell
  • BakeTask
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeRoute
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbConfigTask
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • FileLog
  • FixtureTask
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JqueryEngineHelper
  • JsBaseEngineHelper
  • JsHelper
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • MootoolsEngineHelper
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginShortRoute
  • PluginTask
  • ProjectTask
  • PrototypeEngineHelper
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • Set
  • Shell
  • String
  • TemplateTask
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

  • mb_encode_mimeheader
  • mb_stripos
  • mb_stristr
  • mb_strlen
  • mb_strpos
  • mb_strrchr
  • mb_strrichr
  • mb_strripos
  • mb_strrpos
  • mb_strstr
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
  1: <?php
  2: /**
  3:  * The TestTask handles creating and updating test files.
  4:  *
  5:  * PHP versions 4 and 5
  6:  *
  7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9:  *
 10:  * Licensed under The MIT License
 11:  * Redistributions of files must retain the above copyright notice.
 12:  *
 13:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
 14:  * @link          http://cakephp.org CakePHP(tm) Project
 15:  * @package       cake
 16:  * @subpackage    cake.cake.console.libs.tasks
 17:  * @since         CakePHP(tm) v 1.3
 18:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 19:  */
 20: 
 21: include_once dirname(__FILE__) . DS . 'bake.php';
 22: 
 23: /**
 24:  * Task class for creating and updating test files.
 25:  *
 26:  * @package       cake
 27:  * @subpackage    cake.cake.console.libs.tasks
 28:  */
 29: class TestTask extends BakeTask {
 30: 
 31: /**
 32:  * path to TESTS directory
 33:  *
 34:  * @var string
 35:  * @access public
 36:  */
 37:     var $path = TESTS;
 38: 
 39: /**
 40:  * Tasks used.
 41:  *
 42:  * @var array
 43:  * @access public
 44:  */
 45:     var $tasks = array('Template');
 46: 
 47: /**
 48:  * class types that methods can be generated for
 49:  *
 50:  * @var array
 51:  * @access public
 52:  */
 53:     var $classTypes =  array('Model', 'Controller', 'Component', 'Behavior', 'Helper');
 54: 
 55: /**
 56:  * Internal list of fixtures that have been added so far.
 57:  *
 58:  * @var string
 59:  * @access protected
 60:  */
 61:     var $_fixtures = array();
 62: 
 63: 
 64: /**
 65:  * Execution method always used for tasks
 66:  *
 67:  * @access public
 68:  */
 69:     function execute() {
 70:         if (empty($this->args)) {
 71:             $this->__interactive();
 72:         }
 73: 
 74:         if (count($this->args) == 1) {
 75:             $this->__interactive($this->args[0]);
 76:         }
 77: 
 78:         if (count($this->args) > 1) {
 79:             $type = Inflector::underscore($this->args[0]);
 80:             if ($this->bake($type, $this->args[1])) {
 81:                 $this->out('done');
 82:             }
 83:         }
 84:     }
 85: 
 86: /**
 87:  * Handles interactive baking
 88:  *
 89:  * @access private
 90:  */
 91:     function __interactive($type = null) {
 92:         $this->interactive = true;
 93:         $this->hr();
 94:         $this->out(__('Bake Tests', true));
 95:         $this->out(sprintf(__("Path: %s", true), $this->path));
 96:         $this->hr();
 97: 
 98:         if ($type) {
 99:             $type = Inflector::camelize($type);
100:             if (!in_array($type, $this->classTypes)) {
101:                 $this->error(sprintf('Incorrect type provided.  Please choose one of %s', implode(', ', $this->classTypes)));
102:             }
103:         } else {
104:             $type = $this->getObjectType();
105:         }
106:         $className = $this->getClassName($type);
107:         return $this->bake($type, $className);
108:     }
109: 
110: /**
111:  * Completes final steps for generating data to create test case.
112:  *
113:  * @param string $type Type of object to bake test case for ie. Model, Controller
114:  * @param string $className the 'cake name' for the class ie. Posts for the PostsController
115:  * @access public
116:  */
117:     function bake($type, $className) {
118:         if ($this->typeCanDetectFixtures($type) && $this->isLoadableClass($type, $className)) {
119:             $this->out(__('Bake is detecting possible fixtures..', true));
120:             $testSubject =& $this->buildTestSubject($type, $className);
121:             $this->generateFixtureList($testSubject);
122:         } elseif ($this->interactive) {
123:             $this->getUserFixtures();
124:         }
125:         $fullClassName = $this->getRealClassName($type, $className);
126: 
127:         $methods = array();
128:         if (class_exists($fullClassName)) {
129:             $methods = $this->getTestableMethods($fullClassName);
130:         }
131:         $mock = $this->hasMockClass($type, $fullClassName);
132:         $construction = $this->generateConstructor($type, $fullClassName);
133: 
134:         $plugin = null;
135:         if ($this->plugin) {
136:             $plugin = $this->plugin . '.';
137:         }
138: 
139:         $this->Template->set('fixtures', $this->_fixtures);
140:         $this->Template->set('plugin', $plugin);
141:         $this->Template->set(compact('className', 'methods', 'type', 'fullClassName', 'mock', 'construction'));
142:         $out = $this->Template->generate('classes', 'test');
143: 
144:         $filename = $this->testCaseFileName($type, $className);
145:         $made = $this->createFile($filename, $out);
146:         if ($made) {
147:             return $out;
148:         }
149:         return false;
150:     }
151: 
152: /**
153:  * Interact with the user and get their chosen type. Can exit the script.
154:  *
155:  * @return string Users chosen type.
156:  * @access public
157:  */
158:     function getObjectType() {
159:         $this->hr();
160:         $this->out(__("Select an object type:", true));
161:         $this->hr();
162: 
163:         $keys = array();
164:         foreach ($this->classTypes as $key => $option) {
165:             $this->out(++$key . '. ' . $option);
166:             $keys[] = $key;
167:         }
168:         $keys[] = 'q';
169:         $selection = $this->in(__("Enter the type of object to bake a test for or (q)uit", true), $keys, 'q');
170:         if ($selection == 'q') {
171:             return $this->_stop();
172:         }
173:         return $this->classTypes[$selection - 1];
174:     }
175: 
176: /**
177:  * Get the user chosen Class name for the chosen type
178:  *
179:  * @param string $objectType Type of object to list classes for i.e. Model, Controller.
180:  * @return string Class name the user chose.
181:  * @access public
182:  */
183:     function getClassName($objectType) {
184:         $type = strtolower($objectType);
185:         if ($this->plugin) {
186:             $path = Inflector::pluralize($type);
187:             if ($type === 'helper') {
188:                 $path = 'views' . DS . $path;
189:             } elseif ($type === 'component') {
190:                 $path = 'controllers' . DS . $path;
191:             } elseif ($type === 'behavior') {
192:                 $path = 'models' . DS . $path;
193:             }
194:             $options = App::objects($type, App::pluginPath($this->plugin) . $path, false);
195:         } else {
196:             $options = App::objects($type);
197:         }
198:         $this->out(sprintf(__('Choose a %s class', true), $objectType));
199:         $keys = array();
200:         foreach ($options as $key => $option) {
201:             $this->out(++$key . '. ' . $option);
202:             $keys[] = $key;
203:         }
204:         $selection = $this->in(__('Choose an existing class, or enter the name of a class that does not exist', true));
205:         if (isset($options[$selection - 1])) {
206:             return $options[$selection - 1];
207:         }
208:         return $selection;
209:     }
210: 
211: /**
212:  * Checks whether the chosen type can find its own fixtures.
213:  * Currently only model, and controller are supported
214:  * 
215:  * @param string $type The Type of object you are generating tests for eg. controller
216:  * @param string $className the Classname of the class the test is being generated for.
217:  * @return boolean
218:  * @access public
219:  */
220:     function typeCanDetectFixtures($type) {
221:         $type = strtolower($type);
222:         return ($type == 'controller' || $type == 'model');
223:     }
224: 
225: /**
226:  * Check if a class with the given type is loaded or can be loaded.
227:  *
228:  * @param string $type The Type of object you are generating tests for eg. controller
229:  * @param string $className the Classname of the class the test is being generated for.
230:  * @return boolean
231:  * @access public
232:  */
233:     function isLoadableClass($type, $class) {
234:         return App::import($type, $class);
235:     }
236: 
237: /**
238:  * Construct an instance of the class to be tested.
239:  * So that fixtures can be detected
240:  *
241:  * @param string $type The Type of object you are generating tests for eg. controller
242:  * @param string $class the Classname of the class the test is being generated for.
243:  * @return object And instance of the class that is going to be tested.
244:  * @access public
245:  */
246:     function &buildTestSubject($type, $class) {
247:         ClassRegistry::flush();
248:         App::import($type, $class);
249:         $class = $this->getRealClassName($type, $class);
250:         if (strtolower($type) == 'model') {
251:             $instance =& ClassRegistry::init($class);
252:         } else {
253:             $instance =& new $class();
254:         }
255:         return $instance;
256:     }
257: 
258: /**
259:  * Gets the real class name from the cake short form.
260:  *
261:  * @param string $type The Type of object you are generating tests for eg. controller
262:  * @param string $class the Classname of the class the test is being generated for.
263:  * @return string Real classname
264:  * @access public
265:  */
266:     function getRealClassName($type, $class) {
267:         if (strtolower($type) == 'model') {
268:             return $class;
269:         }
270:         return $class . $type;
271:     }
272: 
273: /**
274:  * Get methods declared in the class given.
275:  * No parent methods will be returned
276:  *
277:  * @param string $className Name of class to look at.
278:  * @return array Array of method names.
279:  * @access public
280:  */
281:     function getTestableMethods($className) {
282:         $classMethods = get_class_methods($className);
283:         $parentMethods = get_class_methods(get_parent_class($className));
284:         $thisMethods = array_diff($classMethods, $parentMethods);
285:         $out = array();
286:         foreach ($thisMethods as $method) {
287:             if (substr($method, 0, 1) != '_' && $method != strtolower($className)) {
288:                 $out[] = $method;
289:             }
290:         }
291:         return $out;
292:     }
293: 
294: /**
295:  * Generate the list of fixtures that will be required to run this test based on
296:  * loaded models.
297:  *
298:  * @param object $subject The object you want to generate fixtures for.
299:  * @return array Array of fixtures to be included in the test.
300:  * @access public
301:  */
302:     function generateFixtureList(&$subject) {
303:         $this->_fixtures = array();
304:         if (is_a($subject, 'Model')) {
305:             $this->_processModel($subject);
306:         } elseif (is_a($subject, 'Controller')) {
307:             $this->_processController($subject);
308:         }
309:         return array_values($this->_fixtures);
310:     }
311: 
312: /**
313:  * Process a model recursively and pull out all the
314:  * model names converting them to fixture names.
315:  *
316:  * @param Model $subject A Model class to scan for associations and pull fixtures off of.
317:  * @return void
318:  * @access protected
319:  */
320:     function _processModel(&$subject) {
321:         $this->_addFixture($subject->name);
322:         $associated = $subject->getAssociated();
323:         foreach ($associated as $alias => $type) {
324:             $className = $subject->{$alias}->name;
325:             if (!isset($this->_fixtures[$className])) {
326:                 $this->_processModel($subject->{$alias});
327:             }
328:             if ($type == 'hasAndBelongsToMany') {
329:                 $joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']);
330:                 if (!isset($this->_fixtures[$joinModel])) {
331:                     $this->_processModel($subject->{$joinModel});
332:                 }
333:             }
334:         }
335:     }
336: 
337: /**
338:  * Process all the models attached to a controller
339:  * and generate a fixture list.
340:  *
341:  * @param Controller $subject A controller to pull model names off of.
342:  * @return void
343:  * @access protected
344:  */
345:     function _processController(&$subject) {
346:         $subject->constructClasses();
347:         $models = array(Inflector::classify($subject->name));
348:         if (!empty($subject->uses)) {
349:             $models = $subject->uses;
350:         }
351:         foreach ($models as $model) {
352:             $this->_processModel($subject->{$model});
353:         }
354:     }
355: 
356: /**
357:  * Add classname to the fixture list.
358:  * Sets the app. or plugin.plugin_name. prefix.
359:  *
360:  * @param string $name Name of the Model class that a fixture might be required for.
361:  * @return void
362:  * @access protected
363:  */
364:     function _addFixture($name) {
365:         $parent = get_parent_class($name);
366:         $prefix = 'app.';
367:         if (strtolower($parent) != 'appmodel' && strtolower(substr($parent, -8)) == 'appmodel') {
368:             $pluginName = substr($parent, 0, strlen($parent) -8);
369:             $prefix = 'plugin.' . Inflector::underscore($pluginName) . '.';
370:         }
371:         $fixture = $prefix . Inflector::underscore($name);
372:         $this->_fixtures[$name] = $fixture;
373:     }
374: 
375: /**
376:  * Interact with the user to get additional fixtures they want to use.
377:  *
378:  * @return array Array of fixtures the user wants to add.
379:  * @access public
380:  */
381:     function getUserFixtures() {
382:         $proceed = $this->in(__('Bake could not detect fixtures, would you like to add some?', true), array('y','n'), 'n');
383:         $fixtures = array();
384:         if (strtolower($proceed) == 'y') {
385:             $fixtureList = $this->in(__("Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'", true));
386:             $fixtureListTrimmed = str_replace(' ', '', $fixtureList);
387:             $fixtures = explode(',', $fixtureListTrimmed);
388:         }
389:         $this->_fixtures = array_merge($this->_fixtures, $fixtures);
390:         return $fixtures;
391:     }
392: 
393: /**
394:  * Is a mock class required for this type of test?
395:  * Controllers require a mock class.
396:  *
397:  * @param string $type The type of object tests are being generated for eg. controller.
398:  * @return boolean
399:  * @access public
400:  */
401:     function hasMockClass($type) {
402:         $type = strtolower($type);
403:         return $type == 'controller';
404:     }
405: 
406: /**
407:  * Generate a constructor code snippet for the type and classname
408:  *
409:  * @param string $type The Type of object you are generating tests for eg. controller
410:  * @param string $className the Classname of the class the test is being generated for.
411:  * @return string Constructor snippet for the thing you are building.
412:  * @access public
413:  */
414:     function generateConstructor($type, $fullClassName) {
415:         $type = strtolower($type);
416:         if ($type == 'model') {
417:             return "ClassRegistry::init('$fullClassName');\n";
418:         }
419:         if ($type == 'controller') {
420:             $className = substr($fullClassName, 0, strlen($fullClassName) - 10);
421:             return "new Test$fullClassName();\n\t\t\$this->{$className}->constructClasses();\n";
422:         }
423:         return "new $fullClassName();\n";
424:     }
425: 
426: /**
427:  * Make the filename for the test case. resolve the suffixes for controllers
428:  * and get the plugin path if needed.
429:  *
430:  * @param string $type The Type of object you are generating tests for eg. controller
431:  * @param string $className the Classname of the class the test is being generated for.
432:  * @return string filename the test should be created on.
433:  * @access public
434:  */
435:     function testCaseFileName($type, $className) {
436:         $path = $this->getPath();;
437:         $path .= 'cases' . DS . strtolower($type) . 's' . DS;
438:         if (strtolower($type) == 'controller') {
439:             $className = $this->getRealClassName($type, $className);
440:         }
441:         return $path . Inflector::underscore($className) . '.test.php';
442:     }
443: 
444: /**
445:  * Show help file.
446:  *
447:  * @return void
448:  * @access public
449:  */
450:     function help() {
451:         $this->hr();
452:         $this->out("Usage: cake bake test <type> <class>");
453:         $this->hr();
454:         $this->out('Commands:');
455:         $this->out("");
456:         $this->out("test model post\n\tbakes a test case for the post model.");
457:         $this->out("");
458:         $this->out("test controller comments\n\tbakes a test case for the comments controller.");
459:         $this->out("");
460:         $this->out('Arguments:');
461:         $this->out("\t<type>   Can be any of the following 'controller', 'model', 'helper',\n\t'component', 'behavior'.");
462:         $this->out("\t<class>  Any existing class for the chosen type.");
463:         $this->out("");
464:         $this->out("Parameters:");
465:         $this->out("\t-plugin  CamelCased name of plugin to bake tests for.");
466:         $this->out("");
467:         $this->_stop();
468:     }
469: }
470: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs